diff --git a/.golangci.yaml b/.golangci.yaml index c2a6a778e..c77faca81 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -43,3 +43,4 @@ linters: - stylecheck # TODO - tagliatelle # TODO - testpackage # TODO + - maintidx # TODO diff --git a/gen/dart/lib/libs/common/v1/conflict.pb.dart b/gen/dart/lib/libs/common/v1/conflict.pb.dart index 6795735f9..ee22e2c76 100644 --- a/gen/dart/lib/libs/common/v1/conflict.pb.dart +++ b/gen/dart/lib/libs/common/v1/conflict.pb.dart @@ -25,11 +25,15 @@ import '../../../google/protobuf/any.pb.dart' as $20; class Conflict extends $pb.GeneratedMessage { factory Conflict({ $core.Map<$core.String, AttributeConflict>? conflictingAttributes, + $core.bool? historyMissing, }) { final $result = create(); if (conflictingAttributes != null) { $result.conflictingAttributes.addAll(conflictingAttributes); } + if (historyMissing != null) { + $result.historyMissing = historyMissing; + } return $result; } Conflict._() : super(); @@ -38,6 +42,7 @@ class Conflict extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Conflict', package: const $pb.PackageName(_omitMessageNames ? '' : 'libs.common.v1'), createEmptyInstance: create) ..m<$core.String, AttributeConflict>(1, _omitFieldNames ? '' : 'conflictingAttributes', entryClassName: 'Conflict.ConflictingAttributesEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OM, valueCreator: AttributeConflict.create, valueDefaultOrMaker: AttributeConflict.getDefault, packageName: const $pb.PackageName('libs.common.v1')) + ..aOB(2, _omitFieldNames ? '' : 'historyMissing') ..hasRequiredFields = false ; @@ -62,9 +67,23 @@ class Conflict extends $pb.GeneratedMessage { static Conflict getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); static Conflict? _defaultInstance; - /// might be empty, in that case we don't have the history to calculate the conflicting attributes + /// when history_missing is true, this map will contain elements, that might not have been updated since you have seen them last. + /// it is then on you to compare these against your view of the world + /// + /// The key is the json-name of the field you tried to change, subkeys are split by dots ('.'), array elements are represented by the resources id: + /// e.g.: for the request: `{"description": "Conflict", "select_data": {"upsert_options": [{"id": "123", "name": "Conflict"}]}}` + /// this might be the conflict: `{"conflicting_attributes": {"description": ..., "select_data.upsert_options.123.name": ...}}` @$pb.TagNumber(1) $core.Map<$core.String, AttributeConflict> get conflictingAttributes => $_getMap(0); + + @$pb.TagNumber(2) + $core.bool get historyMissing => $_getBF(1); + @$pb.TagNumber(2) + set historyMissing($core.bool v) { $_setBool(1, v); } + @$pb.TagNumber(2) + $core.bool hasHistoryMissing() => $_has(1); + @$pb.TagNumber(2) + void clearHistoryMissing() => clearField(2); } class AttributeConflict extends $pb.GeneratedMessage { @@ -112,6 +131,9 @@ class AttributeConflict extends $pb.GeneratedMessage { static AttributeConflict getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); static AttributeConflict? _defaultInstance; + /// CAUTION: may be missing, if the is underlying value is missing (e.g., unassigned beds) + /// Enums are returned as Int32s + /// Arrays are encoded as AnyArrays @$pb.TagNumber(1) $20.Any get is_1 => $_getN(0); @$pb.TagNumber(1) @@ -123,6 +145,9 @@ class AttributeConflict extends $pb.GeneratedMessage { @$pb.TagNumber(1) $20.Any ensureIs_1() => $_ensure(0); + /// CAUTION: may be missing, if the requested value is missing (e.g., unassignment of a bed) + /// Enums are returned as Int32s + /// Arrays are encoded as AnyArrays @$pb.TagNumber(2) $20.Any get want => $_getN(1); @$pb.TagNumber(2) @@ -135,6 +160,52 @@ class AttributeConflict extends $pb.GeneratedMessage { $20.Any ensureWant() => $_ensure(1); } +/// there is no native Any-compatible wrapper for arrays, +/// so here is one +class AnyArray extends $pb.GeneratedMessage { + factory AnyArray({ + $core.Iterable<$20.Any>? elements, + }) { + final $result = create(); + if (elements != null) { + $result.elements.addAll(elements); + } + return $result; + } + AnyArray._() : super(); + factory AnyArray.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory AnyArray.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'AnyArray', package: const $pb.PackageName(_omitMessageNames ? '' : 'libs.common.v1'), createEmptyInstance: create) + ..pc<$20.Any>(1, _omitFieldNames ? '' : 'elements', $pb.PbFieldType.PM, subBuilder: $20.Any.create) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + AnyArray clone() => AnyArray()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + AnyArray copyWith(void Function(AnyArray) updates) => super.copyWith((message) => updates(message as AnyArray)) as AnyArray; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static AnyArray create() => AnyArray._(); + AnyArray createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static AnyArray getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static AnyArray? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$20.Any> get elements => $_getList(0); +} + const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/gen/dart/lib/libs/common/v1/conflict.pbjson.dart b/gen/dart/lib/libs/common/v1/conflict.pbjson.dart index 8d67aa01a..e49a4e5ff 100644 --- a/gen/dart/lib/libs/common/v1/conflict.pbjson.dart +++ b/gen/dart/lib/libs/common/v1/conflict.pbjson.dart @@ -18,6 +18,7 @@ const Conflict$json = { '1': 'Conflict', '2': [ {'1': 'conflicting_attributes', '3': 1, '4': 3, '5': 11, '6': '.libs.common.v1.Conflict.ConflictingAttributesEntry', '10': 'conflictingAttributes'}, + {'1': 'history_missing', '3': 2, '4': 1, '5': 8, '10': 'historyMissing'}, ], '3': [Conflict_ConflictingAttributesEntry$json], }; @@ -36,9 +37,9 @@ const Conflict_ConflictingAttributesEntry$json = { final $typed_data.Uint8List conflictDescriptor = $convert.base64Decode( 'CghDb25mbGljdBJqChZjb25mbGljdGluZ19hdHRyaWJ1dGVzGAEgAygLMjMubGlicy5jb21tb2' '4udjEuQ29uZmxpY3QuQ29uZmxpY3RpbmdBdHRyaWJ1dGVzRW50cnlSFWNvbmZsaWN0aW5nQXR0' - 'cmlidXRlcxprChpDb25mbGljdGluZ0F0dHJpYnV0ZXNFbnRyeRIQCgNrZXkYASABKAlSA2tleR' - 'I3CgV2YWx1ZRgCIAEoCzIhLmxpYnMuY29tbW9uLnYxLkF0dHJpYnV0ZUNvbmZsaWN0UgV2YWx1' - 'ZToCOAE='); + 'cmlidXRlcxInCg9oaXN0b3J5X21pc3NpbmcYAiABKAhSDmhpc3RvcnlNaXNzaW5nGmsKGkNvbm' + 'ZsaWN0aW5nQXR0cmlidXRlc0VudHJ5EhAKA2tleRgBIAEoCVIDa2V5EjcKBXZhbHVlGAIgASgL' + 'MiEubGlicy5jb21tb24udjEuQXR0cmlidXRlQ29uZmxpY3RSBXZhbHVlOgI4AQ=='); @$core.Deprecated('Use attributeConflictDescriptor instead') const AttributeConflict$json = { @@ -54,3 +55,16 @@ final $typed_data.Uint8List attributeConflictDescriptor = $convert.base64Decode( 'ChFBdHRyaWJ1dGVDb25mbGljdBIkCgJpcxgBIAEoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnlSAm' 'lzEigKBHdhbnQYAiABKAsyFC5nb29nbGUucHJvdG9idWYuQW55UgR3YW50'); +@$core.Deprecated('Use anyArrayDescriptor instead') +const AnyArray$json = { + '1': 'AnyArray', + '2': [ + {'1': 'elements', '3': 1, '4': 3, '5': 11, '6': '.google.protobuf.Any', '10': 'elements'}, + ], +}; + +/// Descriptor for `AnyArray`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List anyArrayDescriptor = $convert.base64Decode( + 'CghBbnlBcnJheRIwCghlbGVtZW50cxgBIAMoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnlSCGVsZW' + '1lbnRz'); + diff --git a/gen/dart/lib/services/property_svc/v1/property_value_svc.pb.dart b/gen/dart/lib/services/property_svc/v1/property_value_svc.pb.dart index 7cb5d90f7..e3605ace5 100644 --- a/gen/dart/lib/services/property_svc/v1/property_value_svc.pb.dart +++ b/gen/dart/lib/services/property_svc/v1/property_value_svc.pb.dart @@ -18,6 +18,128 @@ import '../../../libs/common/v1/conflict.pb.dart' as $22; import 'types.pb.dart' as $23; import 'types.pbenum.dart' as $23; +class SelectValueOption extends $pb.GeneratedMessage { + factory SelectValueOption({ + $core.String? id, + $core.String? name, + $core.String? description, + }) { + final $result = create(); + if (id != null) { + $result.id = id; + } + if (name != null) { + $result.name = name; + } + if (description != null) { + $result.description = description; + } + return $result; + } + SelectValueOption._() : super(); + factory SelectValueOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SelectValueOption.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'SelectValueOption', package: const $pb.PackageName(_omitMessageNames ? '' : 'services.property_svc.v1'), createEmptyInstance: create) + ..aOS(1, _omitFieldNames ? '' : 'id') + ..aOS(2, _omitFieldNames ? '' : 'name') + ..aOS(3, _omitFieldNames ? '' : 'description') + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + SelectValueOption clone() => SelectValueOption()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + SelectValueOption copyWith(void Function(SelectValueOption) updates) => super.copyWith((message) => updates(message as SelectValueOption)) as SelectValueOption; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static SelectValueOption create() => SelectValueOption._(); + SelectValueOption createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static SelectValueOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static SelectValueOption? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get id => $_getSZ(0); + @$pb.TagNumber(1) + set id($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => clearField(1); + + @$pb.TagNumber(2) + $core.String get name => $_getSZ(1); + @$pb.TagNumber(2) + set name($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasName() => $_has(1); + @$pb.TagNumber(2) + void clearName() => clearField(2); + + @$pb.TagNumber(3) + $core.String get description => $_getSZ(2); + @$pb.TagNumber(3) + set description($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasDescription() => $_has(2); + @$pb.TagNumber(3) + void clearDescription() => clearField(3); +} + +class MultiSelectValue extends $pb.GeneratedMessage { + factory MultiSelectValue({ + $core.Iterable? selectValues, + }) { + final $result = create(); + if (selectValues != null) { + $result.selectValues.addAll(selectValues); + } + return $result; + } + MultiSelectValue._() : super(); + factory MultiSelectValue.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory MultiSelectValue.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'MultiSelectValue', package: const $pb.PackageName(_omitMessageNames ? '' : 'services.property_svc.v1'), createEmptyInstance: create) + ..pc(1, _omitFieldNames ? '' : 'selectValues', $pb.PbFieldType.PM, subBuilder: SelectValueOption.create) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + MultiSelectValue clone() => MultiSelectValue()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + MultiSelectValue copyWith(void Function(MultiSelectValue) updates) => super.copyWith((message) => updates(message as MultiSelectValue)) as MultiSelectValue; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static MultiSelectValue create() => MultiSelectValue._(); + MultiSelectValue createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static MultiSelectValue getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static MultiSelectValue? _defaultInstance; + + @$pb.TagNumber(1) + $core.List get selectValues => $_getList(0); +} + class AttachPropertyValueRequest_MultiSelectValue extends $pb.GeneratedMessage { factory AttachPropertyValueRequest_MultiSelectValue({ $core.Iterable<$core.String>? selectValues, @@ -571,128 +693,6 @@ class GetAttachedPropertyValuesRequest extends $pb.GeneratedMessage { PatientPropertyMatcher ensurePatientMatcher() => $_ensure(1); } -class GetAttachedPropertyValuesResponse_Value_SelectValueOption extends $pb.GeneratedMessage { - factory GetAttachedPropertyValuesResponse_Value_SelectValueOption({ - $core.String? id, - $core.String? name, - $core.String? description, - }) { - final $result = create(); - if (id != null) { - $result.id = id; - } - if (name != null) { - $result.name = name; - } - if (description != null) { - $result.description = description; - } - return $result; - } - GetAttachedPropertyValuesResponse_Value_SelectValueOption._() : super(); - factory GetAttachedPropertyValuesResponse_Value_SelectValueOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory GetAttachedPropertyValuesResponse_Value_SelectValueOption.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'GetAttachedPropertyValuesResponse.Value.SelectValueOption', package: const $pb.PackageName(_omitMessageNames ? '' : 'services.property_svc.v1'), createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'id') - ..aOS(2, _omitFieldNames ? '' : 'name') - ..aOS(3, _omitFieldNames ? '' : 'description') - ..hasRequiredFields = false - ; - - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - GetAttachedPropertyValuesResponse_Value_SelectValueOption clone() => GetAttachedPropertyValuesResponse_Value_SelectValueOption()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - GetAttachedPropertyValuesResponse_Value_SelectValueOption copyWith(void Function(GetAttachedPropertyValuesResponse_Value_SelectValueOption) updates) => super.copyWith((message) => updates(message as GetAttachedPropertyValuesResponse_Value_SelectValueOption)) as GetAttachedPropertyValuesResponse_Value_SelectValueOption; - - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static GetAttachedPropertyValuesResponse_Value_SelectValueOption create() => GetAttachedPropertyValuesResponse_Value_SelectValueOption._(); - GetAttachedPropertyValuesResponse_Value_SelectValueOption createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static GetAttachedPropertyValuesResponse_Value_SelectValueOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static GetAttachedPropertyValuesResponse_Value_SelectValueOption? _defaultInstance; - - @$pb.TagNumber(1) - $core.String get id => $_getSZ(0); - @$pb.TagNumber(1) - set id($core.String v) { $_setString(0, v); } - @$pb.TagNumber(1) - $core.bool hasId() => $_has(0); - @$pb.TagNumber(1) - void clearId() => clearField(1); - - @$pb.TagNumber(2) - $core.String get name => $_getSZ(1); - @$pb.TagNumber(2) - set name($core.String v) { $_setString(1, v); } - @$pb.TagNumber(2) - $core.bool hasName() => $_has(1); - @$pb.TagNumber(2) - void clearName() => clearField(2); - - @$pb.TagNumber(3) - $core.String get description => $_getSZ(2); - @$pb.TagNumber(3) - set description($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasDescription() => $_has(2); - @$pb.TagNumber(3) - void clearDescription() => clearField(3); -} - -class GetAttachedPropertyValuesResponse_Value_MultiSelectValue extends $pb.GeneratedMessage { - factory GetAttachedPropertyValuesResponse_Value_MultiSelectValue({ - $core.Iterable? selectValues, - }) { - final $result = create(); - if (selectValues != null) { - $result.selectValues.addAll(selectValues); - } - return $result; - } - GetAttachedPropertyValuesResponse_Value_MultiSelectValue._() : super(); - factory GetAttachedPropertyValuesResponse_Value_MultiSelectValue.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory GetAttachedPropertyValuesResponse_Value_MultiSelectValue.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'GetAttachedPropertyValuesResponse.Value.MultiSelectValue', package: const $pb.PackageName(_omitMessageNames ? '' : 'services.property_svc.v1'), createEmptyInstance: create) - ..pc(1, _omitFieldNames ? '' : 'selectValues', $pb.PbFieldType.PM, subBuilder: GetAttachedPropertyValuesResponse_Value_SelectValueOption.create) - ..hasRequiredFields = false - ; - - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - GetAttachedPropertyValuesResponse_Value_MultiSelectValue clone() => GetAttachedPropertyValuesResponse_Value_MultiSelectValue()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - GetAttachedPropertyValuesResponse_Value_MultiSelectValue copyWith(void Function(GetAttachedPropertyValuesResponse_Value_MultiSelectValue) updates) => super.copyWith((message) => updates(message as GetAttachedPropertyValuesResponse_Value_MultiSelectValue)) as GetAttachedPropertyValuesResponse_Value_MultiSelectValue; - - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static GetAttachedPropertyValuesResponse_Value_MultiSelectValue create() => GetAttachedPropertyValuesResponse_Value_MultiSelectValue._(); - GetAttachedPropertyValuesResponse_Value_MultiSelectValue createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static GetAttachedPropertyValuesResponse_Value_MultiSelectValue getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static GetAttachedPropertyValuesResponse_Value_MultiSelectValue? _defaultInstance; - - @$pb.TagNumber(1) - $core.List get selectValues => $_getList(0); -} - enum GetAttachedPropertyValuesResponse_Value_Value { textValue, numberValue, @@ -716,8 +716,8 @@ class GetAttachedPropertyValuesResponse_Value extends $pb.GeneratedMessage { $core.bool? boolValue, $23.Date? dateValue, $21.Timestamp? dateTimeValue, - GetAttachedPropertyValuesResponse_Value_SelectValueOption? selectValue, - GetAttachedPropertyValuesResponse_Value_MultiSelectValue? multiSelectValue, + SelectValueOption? selectValue, + MultiSelectValue? multiSelectValue, $core.String? propertyConsistency, $core.String? valueConsistency, }) { @@ -792,8 +792,8 @@ class GetAttachedPropertyValuesResponse_Value extends $pb.GeneratedMessage { ..aOB(8, _omitFieldNames ? '' : 'boolValue') ..aOM<$23.Date>(9, _omitFieldNames ? '' : 'dateValue', subBuilder: $23.Date.create) ..aOM<$21.Timestamp>(10, _omitFieldNames ? '' : 'dateTimeValue', subBuilder: $21.Timestamp.create) - ..aOM(11, _omitFieldNames ? '' : 'selectValue', subBuilder: GetAttachedPropertyValuesResponse_Value_SelectValueOption.create) - ..aOM(12, _omitFieldNames ? '' : 'multiSelectValue', subBuilder: GetAttachedPropertyValuesResponse_Value_MultiSelectValue.create) + ..aOM(11, _omitFieldNames ? '' : 'selectValue', subBuilder: SelectValueOption.create) + ..aOM(12, _omitFieldNames ? '' : 'multiSelectValue', subBuilder: MultiSelectValue.create) ..aOS(13, _omitFieldNames ? '' : 'propertyConsistency') ..aOS(14, _omitFieldNames ? '' : 'valueConsistency') ..hasRequiredFields = false @@ -918,26 +918,26 @@ class GetAttachedPropertyValuesResponse_Value extends $pb.GeneratedMessage { $21.Timestamp ensureDateTimeValue() => $_ensure(9); @$pb.TagNumber(11) - GetAttachedPropertyValuesResponse_Value_SelectValueOption get selectValue => $_getN(10); + SelectValueOption get selectValue => $_getN(10); @$pb.TagNumber(11) - set selectValue(GetAttachedPropertyValuesResponse_Value_SelectValueOption v) { setField(11, v); } + set selectValue(SelectValueOption v) { setField(11, v); } @$pb.TagNumber(11) $core.bool hasSelectValue() => $_has(10); @$pb.TagNumber(11) void clearSelectValue() => clearField(11); @$pb.TagNumber(11) - GetAttachedPropertyValuesResponse_Value_SelectValueOption ensureSelectValue() => $_ensure(10); + SelectValueOption ensureSelectValue() => $_ensure(10); @$pb.TagNumber(12) - GetAttachedPropertyValuesResponse_Value_MultiSelectValue get multiSelectValue => $_getN(11); + MultiSelectValue get multiSelectValue => $_getN(11); @$pb.TagNumber(12) - set multiSelectValue(GetAttachedPropertyValuesResponse_Value_MultiSelectValue v) { setField(12, v); } + set multiSelectValue(MultiSelectValue v) { setField(12, v); } @$pb.TagNumber(12) $core.bool hasMultiSelectValue() => $_has(11); @$pb.TagNumber(12) void clearMultiSelectValue() => clearField(12); @$pb.TagNumber(12) - GetAttachedPropertyValuesResponse_Value_MultiSelectValue ensureMultiSelectValue() => $_ensure(11); + MultiSelectValue ensureMultiSelectValue() => $_ensure(11); @$pb.TagNumber(13) $core.String get propertyConsistency => $_getSZ(12); diff --git a/gen/dart/lib/services/property_svc/v1/property_value_svc.pbjson.dart b/gen/dart/lib/services/property_svc/v1/property_value_svc.pbjson.dart index c4dc33f2e..ba906d696 100644 --- a/gen/dart/lib/services/property_svc/v1/property_value_svc.pbjson.dart +++ b/gen/dart/lib/services/property_svc/v1/property_value_svc.pbjson.dart @@ -13,6 +13,34 @@ import 'dart:convert' as $convert; import 'dart:core' as $core; import 'dart:typed_data' as $typed_data; +@$core.Deprecated('Use selectValueOptionDescriptor instead') +const SelectValueOption$json = { + '1': 'SelectValueOption', + '2': [ + {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, + {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'}, + {'1': 'description', '3': 3, '4': 1, '5': 9, '10': 'description'}, + ], +}; + +/// Descriptor for `SelectValueOption`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List selectValueOptionDescriptor = $convert.base64Decode( + 'ChFTZWxlY3RWYWx1ZU9wdGlvbhIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZR' + 'IgCgtkZXNjcmlwdGlvbhgDIAEoCVILZGVzY3JpcHRpb24='); + +@$core.Deprecated('Use multiSelectValueDescriptor instead') +const MultiSelectValue$json = { + '1': 'MultiSelectValue', + '2': [ + {'1': 'select_values', '3': 1, '4': 3, '5': 11, '6': '.services.property_svc.v1.SelectValueOption', '10': 'selectValues'}, + ], +}; + +/// Descriptor for `MultiSelectValue`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List multiSelectValueDescriptor = $convert.base64Decode( + 'ChBNdWx0aVNlbGVjdFZhbHVlElAKDXNlbGVjdF92YWx1ZXMYASADKAsyKy5zZXJ2aWNlcy5wcm' + '9wZXJ0eV9zdmMudjEuU2VsZWN0VmFsdWVPcHRpb25SDHNlbGVjdFZhbHVlcw=='); + @$core.Deprecated('Use attachPropertyValueRequestDescriptor instead') const AttachPropertyValueRequest$json = { '1': 'AttachPropertyValueRequest', @@ -158,12 +186,11 @@ const GetAttachedPropertyValuesResponse_Value$json = { {'1': 'bool_value', '3': 8, '4': 1, '5': 8, '9': 0, '10': 'boolValue'}, {'1': 'date_value', '3': 9, '4': 1, '5': 11, '6': '.services.property_svc.v1.Date', '9': 0, '10': 'dateValue'}, {'1': 'date_time_value', '3': 10, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '9': 0, '10': 'dateTimeValue'}, - {'1': 'select_value', '3': 11, '4': 1, '5': 11, '6': '.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption', '9': 0, '10': 'selectValue'}, - {'1': 'multi_select_value', '3': 12, '4': 1, '5': 11, '6': '.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue', '9': 0, '10': 'multiSelectValue'}, + {'1': 'select_value', '3': 11, '4': 1, '5': 11, '6': '.services.property_svc.v1.SelectValueOption', '9': 0, '10': 'selectValue'}, + {'1': 'multi_select_value', '3': 12, '4': 1, '5': 11, '6': '.services.property_svc.v1.MultiSelectValue', '9': 0, '10': 'multiSelectValue'}, {'1': 'property_consistency', '3': 13, '4': 1, '5': 9, '10': 'propertyConsistency'}, {'1': 'value_consistency', '3': 14, '4': 1, '5': 9, '9': 2, '10': 'valueConsistency', '17': true}, ], - '3': [GetAttachedPropertyValuesResponse_Value_SelectValueOption$json, GetAttachedPropertyValuesResponse_Value_MultiSelectValue$json], '8': [ {'1': 'value'}, {'1': '_description'}, @@ -171,29 +198,11 @@ const GetAttachedPropertyValuesResponse_Value$json = { ], }; -@$core.Deprecated('Use getAttachedPropertyValuesResponseDescriptor instead') -const GetAttachedPropertyValuesResponse_Value_SelectValueOption$json = { - '1': 'SelectValueOption', - '2': [ - {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, - {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'}, - {'1': 'description', '3': 3, '4': 1, '5': 9, '10': 'description'}, - ], -}; - -@$core.Deprecated('Use getAttachedPropertyValuesResponseDescriptor instead') -const GetAttachedPropertyValuesResponse_Value_MultiSelectValue$json = { - '1': 'MultiSelectValue', - '2': [ - {'1': 'select_values', '3': 1, '4': 3, '5': 11, '6': '.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption', '10': 'selectValues'}, - ], -}; - /// Descriptor for `GetAttachedPropertyValuesResponse`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List getAttachedPropertyValuesResponseDescriptor = $convert.base64Decode( 'CiFHZXRBdHRhY2hlZFByb3BlcnR5VmFsdWVzUmVzcG9uc2USWQoGdmFsdWVzGAEgAygLMkEuc2' 'VydmljZXMucHJvcGVydHlfc3ZjLnYxLkdldEF0dGFjaGVkUHJvcGVydHlWYWx1ZXNSZXNwb25z' - 'ZS5WYWx1ZVIGdmFsdWVzGrMICgVWYWx1ZRIfCgtwcm9wZXJ0eV9pZBgBIAEoCVIKcHJvcGVydH' + 'ZS5WYWx1ZVIGdmFsdWVzGvgFCgVWYWx1ZRIfCgtwcm9wZXJ0eV9pZBgBIAEoCVIKcHJvcGVydH' 'lJZBJCCgpmaWVsZF90eXBlGAIgASgOMiMuc2VydmljZXMucHJvcGVydHlfc3ZjLnYxLkZpZWxk' 'VHlwZVIJZmllbGRUeXBlEhIKBG5hbWUYAyABKAlSBG5hbWUSJQoLZGVzY3JpcHRpb24YBCABKA' 'lIAVILZGVzY3JpcHRpb26IAQESHwoLaXNfYXJjaGl2ZWQYBSABKAhSCmlzQXJjaGl2ZWQSHwoK' @@ -201,16 +210,11 @@ final $typed_data.Uint8List getAttachedPropertyValuesResponseDescriptor = $conve '51bWJlclZhbHVlEh8KCmJvb2xfdmFsdWUYCCABKAhIAFIJYm9vbFZhbHVlEj8KCmRhdGVfdmFs' 'dWUYCSABKAsyHi5zZXJ2aWNlcy5wcm9wZXJ0eV9zdmMudjEuRGF0ZUgAUglkYXRlVmFsdWUSRA' 'oPZGF0ZV90aW1lX3ZhbHVlGAogASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEgAUg1k' - 'YXRlVGltZVZhbHVlEngKDHNlbGVjdF92YWx1ZRgLIAEoCzJTLnNlcnZpY2VzLnByb3BlcnR5X3' - 'N2Yy52MS5HZXRBdHRhY2hlZFByb3BlcnR5VmFsdWVzUmVzcG9uc2UuVmFsdWUuU2VsZWN0VmFs' - 'dWVPcHRpb25IAFILc2VsZWN0VmFsdWUSggEKEm11bHRpX3NlbGVjdF92YWx1ZRgMIAEoCzJSLn' - 'NlcnZpY2VzLnByb3BlcnR5X3N2Yy52MS5HZXRBdHRhY2hlZFByb3BlcnR5VmFsdWVzUmVzcG9u' - 'c2UuVmFsdWUuTXVsdGlTZWxlY3RWYWx1ZUgAUhBtdWx0aVNlbGVjdFZhbHVlEjEKFHByb3Blcn' - 'R5X2NvbnNpc3RlbmN5GA0gASgJUhNwcm9wZXJ0eUNvbnNpc3RlbmN5EjAKEXZhbHVlX2NvbnNp' - 'c3RlbmN5GA4gASgJSAJSEHZhbHVlQ29uc2lzdGVuY3mIAQEaWQoRU2VsZWN0VmFsdWVPcHRpb2' - '4SDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSIAoLZGVzY3JpcHRpb24YAyAB' - 'KAlSC2Rlc2NyaXB0aW9uGowBChBNdWx0aVNlbGVjdFZhbHVlEngKDXNlbGVjdF92YWx1ZXMYAS' - 'ADKAsyUy5zZXJ2aWNlcy5wcm9wZXJ0eV9zdmMudjEuR2V0QXR0YWNoZWRQcm9wZXJ0eVZhbHVl' - 'c1Jlc3BvbnNlLlZhbHVlLlNlbGVjdFZhbHVlT3B0aW9uUgxzZWxlY3RWYWx1ZXNCBwoFdmFsdW' - 'VCDgoMX2Rlc2NyaXB0aW9uQhQKEl92YWx1ZV9jb25zaXN0ZW5jeQ=='); + 'YXRlVGltZVZhbHVlElAKDHNlbGVjdF92YWx1ZRgLIAEoCzIrLnNlcnZpY2VzLnByb3BlcnR5X3' + 'N2Yy52MS5TZWxlY3RWYWx1ZU9wdGlvbkgAUgtzZWxlY3RWYWx1ZRJaChJtdWx0aV9zZWxlY3Rf' + 'dmFsdWUYDCABKAsyKi5zZXJ2aWNlcy5wcm9wZXJ0eV9zdmMudjEuTXVsdGlTZWxlY3RWYWx1ZU' + 'gAUhBtdWx0aVNlbGVjdFZhbHVlEjEKFHByb3BlcnR5X2NvbnNpc3RlbmN5GA0gASgJUhNwcm9w' + 'ZXJ0eUNvbnNpc3RlbmN5EjAKEXZhbHVlX2NvbnNpc3RlbmN5GA4gASgJSAJSEHZhbHVlQ29uc2' + 'lzdGVuY3mIAQFCBwoFdmFsdWVCDgoMX2Rlc2NyaXB0aW9uQhQKEl92YWx1ZV9jb25zaXN0ZW5j' + 'eQ=='); diff --git a/gen/dart/lib/services/tasks_svc/v1/task_svc.pb.dart b/gen/dart/lib/services/tasks_svc/v1/task_svc.pb.dart index 9503659df..1c983ed98 100644 --- a/gen/dart/lib/services/tasks_svc/v1/task_svc.pb.dart +++ b/gen/dart/lib/services/tasks_svc/v1/task_svc.pb.dart @@ -2291,7 +2291,6 @@ class UnassignTaskRequest extends $pb.GeneratedMessage { factory UnassignTaskRequest({ $core.String? taskId, $core.String? userId, - $core.String? consistency, }) { final $result = create(); if (taskId != null) { @@ -2300,9 +2299,6 @@ class UnassignTaskRequest extends $pb.GeneratedMessage { if (userId != null) { $result.userId = userId; } - if (consistency != null) { - $result.consistency = consistency; - } return $result; } UnassignTaskRequest._() : super(); @@ -2312,7 +2308,6 @@ class UnassignTaskRequest extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'UnassignTaskRequest', package: const $pb.PackageName(_omitMessageNames ? '' : 'services.tasks_svc.v1'), createEmptyInstance: create) ..aOS(1, _omitFieldNames ? '' : 'taskId') ..aOS(2, _omitFieldNames ? '' : 'userId') - ..aOS(3, _omitFieldNames ? '' : 'consistency') ..hasRequiredFields = false ; @@ -2354,15 +2349,6 @@ class UnassignTaskRequest extends $pb.GeneratedMessage { $core.bool hasUserId() => $_has(1); @$pb.TagNumber(2) void clearUserId() => clearField(2); - - @$pb.TagNumber(3) - $core.String get consistency => $_getSZ(2); - @$pb.TagNumber(3) - set consistency($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasConsistency() => $_has(2); - @$pb.TagNumber(3) - void clearConsistency() => clearField(3); } class UnassignTaskResponse extends $pb.GeneratedMessage { diff --git a/gen/dart/lib/services/tasks_svc/v1/task_svc.pbjson.dart b/gen/dart/lib/services/tasks_svc/v1/task_svc.pbjson.dart index 9aa1bb8ab..db144682c 100644 --- a/gen/dart/lib/services/tasks_svc/v1/task_svc.pbjson.dart +++ b/gen/dart/lib/services/tasks_svc/v1/task_svc.pbjson.dart @@ -476,18 +476,13 @@ const UnassignTaskRequest$json = { '2': [ {'1': 'task_id', '3': 1, '4': 1, '5': 9, '10': 'taskId'}, {'1': 'user_id', '3': 2, '4': 1, '5': 9, '10': 'userId'}, - {'1': 'consistency', '3': 3, '4': 1, '5': 9, '9': 0, '10': 'consistency', '17': true}, - ], - '8': [ - {'1': '_consistency'}, ], }; /// Descriptor for `UnassignTaskRequest`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List unassignTaskRequestDescriptor = $convert.base64Decode( 'ChNVbmFzc2lnblRhc2tSZXF1ZXN0EhcKB3Rhc2tfaWQYASABKAlSBnRhc2tJZBIXCgd1c2VyX2' - 'lkGAIgASgJUgZ1c2VySWQSJQoLY29uc2lzdGVuY3kYAyABKAlIAFILY29uc2lzdGVuY3mIAQFC' - 'DgoMX2NvbnNpc3RlbmN5'); + 'lkGAIgASgJUgZ1c2VySWQ='); @$core.Deprecated('Use unassignTaskResponseDescriptor instead') const UnassignTaskResponse$json = { diff --git a/gen/go/libs/common/v1/conflict.pb.go b/gen/go/libs/common/v1/conflict.pb.go index abc222b05..9d92a7c35 100644 --- a/gen/go/libs/common/v1/conflict.pb.go +++ b/gen/go/libs/common/v1/conflict.pb.go @@ -34,8 +34,14 @@ type Conflict struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // might be empty, in that case we don't have the history to calculate the conflicting attributes + // when history_missing is true, this map will contain elements, that might not have been updated since you have seen them last. + // it is then on you to compare these against your view of the world + // + // The key is the json-name of the field you tried to change, subkeys are split by dots ('.'), array elements are represented by the resources id: + // e.g.: for the request: `{"description": "Conflict", "select_data": {"upsert_options": [{"id": "123", "name": "Conflict"}]}}` + // this might be the conflict: `{"conflicting_attributes": {"description": ..., "select_data.upsert_options.123.name": ...}}` ConflictingAttributes map[string]*AttributeConflict `protobuf:"bytes,1,rep,name=conflicting_attributes,json=conflictingAttributes,proto3" json:"conflicting_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + HistoryMissing bool `protobuf:"varint,2,opt,name=history_missing,json=historyMissing,proto3" json:"history_missing,omitempty"` } func (x *Conflict) Reset() { @@ -77,12 +83,25 @@ func (x *Conflict) GetConflictingAttributes() map[string]*AttributeConflict { return nil } +func (x *Conflict) GetHistoryMissing() bool { + if x != nil { + return x.HistoryMissing + } + return false +} + type AttributeConflict struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Is *anypb.Any `protobuf:"bytes,1,opt,name=is,proto3" json:"is,omitempty"` + // CAUTION: may be missing, if the is underlying value is missing (e.g., unassigned beds) + // Enums are returned as Int32s + // Arrays are encoded as AnyArrays + Is *anypb.Any `protobuf:"bytes,1,opt,name=is,proto3" json:"is,omitempty"` + // CAUTION: may be missing, if the requested value is missing (e.g., unassignment of a bed) + // Enums are returned as Int32s + // Arrays are encoded as AnyArrays Want *anypb.Any `protobuf:"bytes,2,opt,name=want,proto3" json:"want,omitempty"` } @@ -132,6 +151,55 @@ func (x *AttributeConflict) GetWant() *anypb.Any { return nil } +// there is no native Any-compatible wrapper for arrays, +// so here is one +type AnyArray struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Elements []*anypb.Any `protobuf:"bytes,1,rep,name=elements,proto3" json:"elements,omitempty"` +} + +func (x *AnyArray) Reset() { + *x = AnyArray{} + if protoimpl.UnsafeEnabled { + mi := &file_libs_common_v1_conflict_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AnyArray) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnyArray) ProtoMessage() {} + +func (x *AnyArray) ProtoReflect() protoreflect.Message { + mi := &file_libs_common_v1_conflict_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnyArray.ProtoReflect.Descriptor instead. +func (*AnyArray) Descriptor() ([]byte, []int) { + return file_libs_common_v1_conflict_proto_rawDescGZIP(), []int{2} +} + +func (x *AnyArray) GetElements() []*anypb.Any { + if x != nil { + return x.Elements + } + return nil +} + var File_libs_common_v1_conflict_proto protoreflect.FileDescriptor var file_libs_common_v1_conflict_proto_rawDesc = []byte{ @@ -139,7 +207,7 @@ var file_libs_common_v1_conflict_proto_rawDesc = []byte{ 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x6c, 0x69, 0x62, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe3, 0x01, 0x0a, 0x08, 0x43, + 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8c, 0x02, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x12, 0x6a, 0x0a, 0x16, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x2e, 0x63, @@ -147,30 +215,36 @@ var file_libs_common_v1_conflict_proto_rawDesc = []byte{ 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x15, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x1a, 0x6b, 0x0a, 0x1a, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x69, - 0x6e, 0x67, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x6c, 0x69, 0x63, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0x63, 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x6c, 0x69, 0x63, 0x74, 0x12, 0x24, 0x0a, 0x02, 0x69, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x69, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x77, - 0x61, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, - 0x04, 0x77, 0x61, 0x6e, 0x74, 0x42, 0x91, 0x01, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x6c, 0x69, - 0x62, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x43, 0x6f, - 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x12, 0x67, - 0x65, 0x6e, 0x2f, 0x6c, 0x69, 0x62, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, - 0x31, 0xa2, 0x02, 0x03, 0x4c, 0x43, 0x58, 0xaa, 0x02, 0x0e, 0x4c, 0x69, 0x62, 0x73, 0x2e, 0x43, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0e, 0x4c, 0x69, 0x62, 0x73, 0x5c, - 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1a, 0x4c, 0x69, 0x62, 0x73, - 0x5c, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x10, 0x4c, 0x69, 0x62, 0x73, 0x3a, 0x3a, 0x43, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x74, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x68, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x1a, 0x6b, 0x0a, 0x1a, + 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6c, 0x69, + 0x62, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x63, 0x0a, 0x11, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x12, 0x24, + 0x0a, 0x02, 0x69, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, + 0x52, 0x02, 0x69, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x77, 0x61, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x77, 0x61, 0x6e, 0x74, 0x22, 0x3c, + 0x0a, 0x08, 0x41, 0x6e, 0x79, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x30, 0x0a, 0x08, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, + 0x6e, 0x79, 0x52, 0x08, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x91, 0x01, 0x0a, + 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x12, 0x67, 0x65, 0x6e, 0x2f, 0x6c, 0x69, 0x62, 0x73, 0x2f, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4c, 0x43, 0x58, 0xaa, 0x02, + 0x0e, 0x4c, 0x69, 0x62, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x31, 0xca, + 0x02, 0x0e, 0x4c, 0x69, 0x62, 0x73, 0x5c, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, 0x56, 0x31, + 0xe2, 0x02, 0x1a, 0x4c, 0x69, 0x62, 0x73, 0x5c, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, 0x56, + 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x10, + 0x4c, 0x69, 0x62, 0x73, 0x3a, 0x3a, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x3a, 0x3a, 0x56, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -185,23 +259,25 @@ func file_libs_common_v1_conflict_proto_rawDescGZIP() []byte { return file_libs_common_v1_conflict_proto_rawDescData } -var file_libs_common_v1_conflict_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_libs_common_v1_conflict_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_libs_common_v1_conflict_proto_goTypes = []interface{}{ (*Conflict)(nil), // 0: libs.common.v1.Conflict (*AttributeConflict)(nil), // 1: libs.common.v1.AttributeConflict - nil, // 2: libs.common.v1.Conflict.ConflictingAttributesEntry - (*anypb.Any)(nil), // 3: google.protobuf.Any + (*AnyArray)(nil), // 2: libs.common.v1.AnyArray + nil, // 3: libs.common.v1.Conflict.ConflictingAttributesEntry + (*anypb.Any)(nil), // 4: google.protobuf.Any } var file_libs_common_v1_conflict_proto_depIdxs = []int32{ - 2, // 0: libs.common.v1.Conflict.conflicting_attributes:type_name -> libs.common.v1.Conflict.ConflictingAttributesEntry - 3, // 1: libs.common.v1.AttributeConflict.is:type_name -> google.protobuf.Any - 3, // 2: libs.common.v1.AttributeConflict.want:type_name -> google.protobuf.Any - 1, // 3: libs.common.v1.Conflict.ConflictingAttributesEntry.value:type_name -> libs.common.v1.AttributeConflict - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 3, // 0: libs.common.v1.Conflict.conflicting_attributes:type_name -> libs.common.v1.Conflict.ConflictingAttributesEntry + 4, // 1: libs.common.v1.AttributeConflict.is:type_name -> google.protobuf.Any + 4, // 2: libs.common.v1.AttributeConflict.want:type_name -> google.protobuf.Any + 4, // 3: libs.common.v1.AnyArray.elements:type_name -> google.protobuf.Any + 1, // 4: libs.common.v1.Conflict.ConflictingAttributesEntry.value:type_name -> libs.common.v1.AttributeConflict + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_libs_common_v1_conflict_proto_init() } @@ -234,6 +310,18 @@ func file_libs_common_v1_conflict_proto_init() { return nil } } + file_libs_common_v1_conflict_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AnyArray); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -241,7 +329,7 @@ func file_libs_common_v1_conflict_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_libs_common_v1_conflict_proto_rawDesc, NumEnums: 0, - NumMessages: 3, + NumMessages: 4, NumExtensions: 0, NumServices: 0, }, diff --git a/gen/go/services/property_svc/v1/export.go b/gen/go/services/property_svc/v1/export.go new file mode 100644 index 000000000..0f18f626f --- /dev/null +++ b/gen/go/services/property_svc/v1/export.go @@ -0,0 +1,6 @@ +package v1 + +// This file is handwritten and exists because the go codegen is horseshit. +// It exports hidden types needed to properly work with oneofs. + +type IsAttachPropertyValueRequest_Value = isAttachPropertyValueRequest_Value diff --git a/gen/go/services/property_svc/v1/property_value_svc.pb.go b/gen/go/services/property_svc/v1/property_value_svc.pb.go index 4b0d48a31..c588b03b8 100644 --- a/gen/go/services/property_svc/v1/property_value_svc.pb.go +++ b/gen/go/services/property_svc/v1/property_value_svc.pb.go @@ -22,6 +22,116 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type SelectValueOption struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` +} + +func (x *SelectValueOption) Reset() { + *x = SelectValueOption{} + if protoimpl.UnsafeEnabled { + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SelectValueOption) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SelectValueOption) ProtoMessage() {} + +func (x *SelectValueOption) ProtoReflect() protoreflect.Message { + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SelectValueOption.ProtoReflect.Descriptor instead. +func (*SelectValueOption) Descriptor() ([]byte, []int) { + return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{0} +} + +func (x *SelectValueOption) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *SelectValueOption) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *SelectValueOption) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +type MultiSelectValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SelectValues []*SelectValueOption `protobuf:"bytes,1,rep,name=select_values,json=selectValues,proto3" json:"select_values,omitempty"` +} + +func (x *MultiSelectValue) Reset() { + *x = MultiSelectValue{} + if protoimpl.UnsafeEnabled { + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MultiSelectValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MultiSelectValue) ProtoMessage() {} + +func (x *MultiSelectValue) ProtoReflect() protoreflect.Message { + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MultiSelectValue.ProtoReflect.Descriptor instead. +func (*MultiSelectValue) Descriptor() ([]byte, []int) { + return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{1} +} + +func (x *MultiSelectValue) GetSelectValues() []*SelectValueOption { + if x != nil { + return x.SelectValues + } + return nil +} + // AttachPropertyValueRequest type AttachPropertyValueRequest struct { state protoimpl.MessageState @@ -47,7 +157,7 @@ type AttachPropertyValueRequest struct { func (x *AttachPropertyValueRequest) Reset() { *x = AttachPropertyValueRequest{} if protoimpl.UnsafeEnabled { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[0] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -60,7 +170,7 @@ func (x *AttachPropertyValueRequest) String() string { func (*AttachPropertyValueRequest) ProtoMessage() {} func (x *AttachPropertyValueRequest) ProtoReflect() protoreflect.Message { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[0] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -73,7 +183,7 @@ func (x *AttachPropertyValueRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AttachPropertyValueRequest.ProtoReflect.Descriptor instead. func (*AttachPropertyValueRequest) Descriptor() ([]byte, []int) { - return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{0} + return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{2} } func (x *AttachPropertyValueRequest) GetSubjectId() string { @@ -212,7 +322,7 @@ type AttachPropertyValueResponse struct { func (x *AttachPropertyValueResponse) Reset() { *x = AttachPropertyValueResponse{} if protoimpl.UnsafeEnabled { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[1] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -225,7 +335,7 @@ func (x *AttachPropertyValueResponse) String() string { func (*AttachPropertyValueResponse) ProtoMessage() {} func (x *AttachPropertyValueResponse) ProtoReflect() protoreflect.Message { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[1] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -238,7 +348,7 @@ func (x *AttachPropertyValueResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AttachPropertyValueResponse.ProtoReflect.Descriptor instead. func (*AttachPropertyValueResponse) Descriptor() ([]byte, []int) { - return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{1} + return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{3} } func (x *AttachPropertyValueResponse) GetPropertyValueId() string { @@ -274,7 +384,7 @@ type TaskPropertyMatcher struct { func (x *TaskPropertyMatcher) Reset() { *x = TaskPropertyMatcher{} if protoimpl.UnsafeEnabled { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[2] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -287,7 +397,7 @@ func (x *TaskPropertyMatcher) String() string { func (*TaskPropertyMatcher) ProtoMessage() {} func (x *TaskPropertyMatcher) ProtoReflect() protoreflect.Message { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[2] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -300,7 +410,7 @@ func (x *TaskPropertyMatcher) ProtoReflect() protoreflect.Message { // Deprecated: Use TaskPropertyMatcher.ProtoReflect.Descriptor instead. func (*TaskPropertyMatcher) Descriptor() ([]byte, []int) { - return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{2} + return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{4} } func (x *TaskPropertyMatcher) GetWardId() string { @@ -329,7 +439,7 @@ type PatientPropertyMatcher struct { func (x *PatientPropertyMatcher) Reset() { *x = PatientPropertyMatcher{} if protoimpl.UnsafeEnabled { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[3] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -342,7 +452,7 @@ func (x *PatientPropertyMatcher) String() string { func (*PatientPropertyMatcher) ProtoMessage() {} func (x *PatientPropertyMatcher) ProtoReflect() protoreflect.Message { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[3] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -355,7 +465,7 @@ func (x *PatientPropertyMatcher) ProtoReflect() protoreflect.Message { // Deprecated: Use PatientPropertyMatcher.ProtoReflect.Descriptor instead. func (*PatientPropertyMatcher) Descriptor() ([]byte, []int) { - return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{3} + return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{5} } func (x *PatientPropertyMatcher) GetWardId() string { @@ -387,7 +497,7 @@ type GetAttachedPropertyValuesRequest struct { func (x *GetAttachedPropertyValuesRequest) Reset() { *x = GetAttachedPropertyValuesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[4] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -400,7 +510,7 @@ func (x *GetAttachedPropertyValuesRequest) String() string { func (*GetAttachedPropertyValuesRequest) ProtoMessage() {} func (x *GetAttachedPropertyValuesRequest) ProtoReflect() protoreflect.Message { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[4] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -413,7 +523,7 @@ func (x *GetAttachedPropertyValuesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAttachedPropertyValuesRequest.ProtoReflect.Descriptor instead. func (*GetAttachedPropertyValuesRequest) Descriptor() ([]byte, []int) { - return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{4} + return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{6} } func (m *GetAttachedPropertyValuesRequest) GetMatcher() isGetAttachedPropertyValuesRequest_Matcher { @@ -465,7 +575,7 @@ type GetAttachedPropertyValuesResponse struct { func (x *GetAttachedPropertyValuesResponse) Reset() { *x = GetAttachedPropertyValuesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[5] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -478,7 +588,7 @@ func (x *GetAttachedPropertyValuesResponse) String() string { func (*GetAttachedPropertyValuesResponse) ProtoMessage() {} func (x *GetAttachedPropertyValuesResponse) ProtoReflect() protoreflect.Message { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[5] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -491,7 +601,7 @@ func (x *GetAttachedPropertyValuesResponse) ProtoReflect() protoreflect.Message // Deprecated: Use GetAttachedPropertyValuesResponse.ProtoReflect.Descriptor instead. func (*GetAttachedPropertyValuesResponse) Descriptor() ([]byte, []int) { - return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{5} + return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{7} } func (x *GetAttachedPropertyValuesResponse) GetValues() []*GetAttachedPropertyValuesResponse_Value { @@ -513,7 +623,7 @@ type AttachPropertyValueRequest_MultiSelectValue struct { func (x *AttachPropertyValueRequest_MultiSelectValue) Reset() { *x = AttachPropertyValueRequest_MultiSelectValue{} if protoimpl.UnsafeEnabled { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[6] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -526,7 +636,7 @@ func (x *AttachPropertyValueRequest_MultiSelectValue) String() string { func (*AttachPropertyValueRequest_MultiSelectValue) ProtoMessage() {} func (x *AttachPropertyValueRequest_MultiSelectValue) ProtoReflect() protoreflect.Message { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[6] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -539,7 +649,7 @@ func (x *AttachPropertyValueRequest_MultiSelectValue) ProtoReflect() protoreflec // Deprecated: Use AttachPropertyValueRequest_MultiSelectValue.ProtoReflect.Descriptor instead. func (*AttachPropertyValueRequest_MultiSelectValue) Descriptor() ([]byte, []int) { - return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{0, 0} + return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{2, 0} } func (x *AttachPropertyValueRequest_MultiSelectValue) GetSelectValues() []string { @@ -574,7 +684,7 @@ type GetAttachedPropertyValuesResponse_Value struct { // *GetAttachedPropertyValuesResponse_Value_DateValue // *GetAttachedPropertyValuesResponse_Value_DateTimeValue // *GetAttachedPropertyValuesResponse_Value_SelectValue - // *GetAttachedPropertyValuesResponse_Value_MultiSelectValue_ + // *GetAttachedPropertyValuesResponse_Value_MultiSelectValue Value isGetAttachedPropertyValuesResponse_Value_Value `protobuf_oneof:"value"` PropertyConsistency string `protobuf:"bytes,13,opt,name=property_consistency,json=propertyConsistency,proto3" json:"property_consistency,omitempty"` ValueConsistency *string `protobuf:"bytes,14,opt,name=value_consistency,json=valueConsistency,proto3,oneof" json:"value_consistency,omitempty"` // missing, if no value available @@ -583,7 +693,7 @@ type GetAttachedPropertyValuesResponse_Value struct { func (x *GetAttachedPropertyValuesResponse_Value) Reset() { *x = GetAttachedPropertyValuesResponse_Value{} if protoimpl.UnsafeEnabled { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[7] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -596,7 +706,7 @@ func (x *GetAttachedPropertyValuesResponse_Value) String() string { func (*GetAttachedPropertyValuesResponse_Value) ProtoMessage() {} func (x *GetAttachedPropertyValuesResponse_Value) ProtoReflect() protoreflect.Message { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[7] + mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -609,7 +719,7 @@ func (x *GetAttachedPropertyValuesResponse_Value) ProtoReflect() protoreflect.Me // Deprecated: Use GetAttachedPropertyValuesResponse_Value.ProtoReflect.Descriptor instead. func (*GetAttachedPropertyValuesResponse_Value) Descriptor() ([]byte, []int) { - return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{5, 0} + return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{7, 0} } func (x *GetAttachedPropertyValuesResponse_Value) GetPropertyId() string { @@ -689,15 +799,15 @@ func (x *GetAttachedPropertyValuesResponse_Value) GetDateTimeValue() *timestampp return nil } -func (x *GetAttachedPropertyValuesResponse_Value) GetSelectValue() *GetAttachedPropertyValuesResponse_Value_SelectValueOption { +func (x *GetAttachedPropertyValuesResponse_Value) GetSelectValue() *SelectValueOption { if x, ok := x.GetValue().(*GetAttachedPropertyValuesResponse_Value_SelectValue); ok { return x.SelectValue } return nil } -func (x *GetAttachedPropertyValuesResponse_Value) GetMultiSelectValue() *GetAttachedPropertyValuesResponse_Value_MultiSelectValue { - if x, ok := x.GetValue().(*GetAttachedPropertyValuesResponse_Value_MultiSelectValue_); ok { +func (x *GetAttachedPropertyValuesResponse_Value) GetMultiSelectValue() *MultiSelectValue { + if x, ok := x.GetValue().(*GetAttachedPropertyValuesResponse_Value_MultiSelectValue); ok { return x.MultiSelectValue } return nil @@ -742,11 +852,11 @@ type GetAttachedPropertyValuesResponse_Value_DateTimeValue struct { } type GetAttachedPropertyValuesResponse_Value_SelectValue struct { - SelectValue *GetAttachedPropertyValuesResponse_Value_SelectValueOption `protobuf:"bytes,11,opt,name=select_value,json=selectValue,proto3,oneof"` // FIELD_TYPE_SELECT, id of option + SelectValue *SelectValueOption `protobuf:"bytes,11,opt,name=select_value,json=selectValue,proto3,oneof"` // FIELD_TYPE_SELECT, id of option } -type GetAttachedPropertyValuesResponse_Value_MultiSelectValue_ struct { - MultiSelectValue *GetAttachedPropertyValuesResponse_Value_MultiSelectValue `protobuf:"bytes,12,opt,name=multi_select_value,json=multiSelectValue,proto3,oneof"` +type GetAttachedPropertyValuesResponse_Value_MultiSelectValue struct { + MultiSelectValue *MultiSelectValue `protobuf:"bytes,12,opt,name=multi_select_value,json=multiSelectValue,proto3,oneof"` } func (*GetAttachedPropertyValuesResponse_Value_TextValue) isGetAttachedPropertyValuesResponse_Value_Value() { @@ -767,117 +877,7 @@ func (*GetAttachedPropertyValuesResponse_Value_DateTimeValue) isGetAttachedPrope func (*GetAttachedPropertyValuesResponse_Value_SelectValue) isGetAttachedPropertyValuesResponse_Value_Value() { } -func (*GetAttachedPropertyValuesResponse_Value_MultiSelectValue_) isGetAttachedPropertyValuesResponse_Value_Value() { -} - -type GetAttachedPropertyValuesResponse_Value_SelectValueOption struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` -} - -func (x *GetAttachedPropertyValuesResponse_Value_SelectValueOption) Reset() { - *x = GetAttachedPropertyValuesResponse_Value_SelectValueOption{} - if protoimpl.UnsafeEnabled { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetAttachedPropertyValuesResponse_Value_SelectValueOption) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAttachedPropertyValuesResponse_Value_SelectValueOption) ProtoMessage() {} - -func (x *GetAttachedPropertyValuesResponse_Value_SelectValueOption) ProtoReflect() protoreflect.Message { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetAttachedPropertyValuesResponse_Value_SelectValueOption.ProtoReflect.Descriptor instead. -func (*GetAttachedPropertyValuesResponse_Value_SelectValueOption) Descriptor() ([]byte, []int) { - return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{5, 0, 0} -} - -func (x *GetAttachedPropertyValuesResponse_Value_SelectValueOption) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *GetAttachedPropertyValuesResponse_Value_SelectValueOption) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *GetAttachedPropertyValuesResponse_Value_SelectValueOption) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -type GetAttachedPropertyValuesResponse_Value_MultiSelectValue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SelectValues []*GetAttachedPropertyValuesResponse_Value_SelectValueOption `protobuf:"bytes,1,rep,name=select_values,json=selectValues,proto3" json:"select_values,omitempty"` -} - -func (x *GetAttachedPropertyValuesResponse_Value_MultiSelectValue) Reset() { - *x = GetAttachedPropertyValuesResponse_Value_MultiSelectValue{} - if protoimpl.UnsafeEnabled { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetAttachedPropertyValuesResponse_Value_MultiSelectValue) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAttachedPropertyValuesResponse_Value_MultiSelectValue) ProtoMessage() {} - -func (x *GetAttachedPropertyValuesResponse_Value_MultiSelectValue) ProtoReflect() protoreflect.Message { - mi := &file_services_property_svc_v1_property_value_svc_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetAttachedPropertyValuesResponse_Value_MultiSelectValue.ProtoReflect.Descriptor instead. -func (*GetAttachedPropertyValuesResponse_Value_MultiSelectValue) Descriptor() ([]byte, []int) { - return file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP(), []int{5, 0, 1} -} - -func (x *GetAttachedPropertyValuesResponse_Value_MultiSelectValue) GetSelectValues() []*GetAttachedPropertyValuesResponse_Value_SelectValueOption { - if x != nil { - return x.SelectValues - } - return nil +func (*GetAttachedPropertyValuesResponse_Value_MultiSelectValue) isGetAttachedPropertyValuesResponse_Value_Value() { } var File_services_property_svc_v1_property_value_svc_proto protoreflect.FileDescriptor @@ -894,137 +894,144 @@ var file_services_property_svc_v1_property_value_svc_proto_rawDesc = []byte{ 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x6c, 0x69, 0x62, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x91, 0x05, 0x0a, 0x1a, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x50, 0x72, - 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, - 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, - 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x74, 0x65, 0x78, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, - 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x64, 0x61, 0x74, - 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, - 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, - 0x09, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, 0x0a, 0x0f, 0x64, 0x61, - 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, - 0x00, 0x52, 0x0d, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x75, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x73, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, + 0x6f, 0x74, 0x6f, 0x22, 0x59, 0x0a, 0x11, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x64, + 0x0a, 0x10, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x50, 0x0a, 0x0d, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, + 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x22, 0x91, 0x05, 0x0a, 0x1a, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x50, + 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, + 0x79, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x74, 0x65, 0x78, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, + 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, + 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x64, 0x61, + 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, + 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x65, 0x48, 0x00, + 0x52, 0x09, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, 0x0a, 0x0f, 0x64, + 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x48, 0x00, 0x52, 0x0d, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x75, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, + 0x74, 0x61, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x10, 0x6d, 0x75, 0x6c, + 0x74, 0x69, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, + 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x01, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, + 0x79, 0x88, 0x01, 0x01, 0x1a, 0x69, 0x0a, 0x10, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x30, 0x0a, + 0x14, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, + 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x6f, 0x6e, + 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xb3, 0x01, 0x0a, 0x1b, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x10, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, 0x0b, - 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x01, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, - 0x88, 0x01, 0x01, 0x1a, 0x69, 0x0a, 0x10, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, - 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x07, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x6f, 0x6e, 0x73, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xb3, 0x01, 0x0a, 0x1b, 0x41, 0x74, 0x74, 0x61, - 0x63, 0x68, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x65, - 0x72, 0x74, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x48, - 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x88, 0x01, 0x01, 0x12, 0x20, - 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, - 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x22, 0x69, 0x0a, - 0x13, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x07, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x77, 0x61, 0x72, 0x64, 0x49, 0x64, 0x88, - 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x88, 0x01, 0x01, - 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x42, 0x0a, 0x0a, 0x08, - 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x22, 0x75, 0x0a, 0x16, 0x50, 0x61, 0x74, 0x69, - 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x07, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x77, 0x61, 0x72, 0x64, 0x49, 0x64, 0x88, 0x01, 0x01, - 0x12, 0x22, 0x0a, 0x0a, 0x70, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x09, 0x70, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, - 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x70, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x22, - 0xde, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, - 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x52, 0x0a, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, - 0x74, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x61, 0x73, - 0x6b, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x5b, 0x0a, 0x0f, 0x70, 0x61, 0x74, 0x69, - 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x30, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x70, + 0x65, 0x72, 0x74, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, + 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x88, 0x01, 0x01, 0x12, + 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, + 0x79, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x22, 0x69, + 0x0a, 0x13, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x07, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x77, 0x61, 0x72, 0x64, 0x49, 0x64, + 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x88, 0x01, + 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x42, 0x0a, 0x0a, + 0x08, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x22, 0x75, 0x0a, 0x16, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, - 0x22, 0xb4, 0x09, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, + 0x68, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x07, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x77, 0x61, 0x72, 0x64, 0x49, 0x64, 0x88, 0x01, + 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x70, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x09, 0x70, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, + 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, + 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x70, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 0x22, 0xde, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x1a, 0xb3, 0x08, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, - 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x0a, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x0b, 0x69, - 0x73, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0a, 0x69, 0x73, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0a, - 0x74, 0x65, 0x78, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x09, 0x74, 0x65, 0x78, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, - 0x0c, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x52, 0x0a, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x6d, 0x61, + 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, + 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x61, + 0x73, 0x6b, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x5b, 0x0a, 0x0f, 0x70, 0x61, 0x74, + 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, + 0x74, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x4d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x72, 0x22, 0xf9, 0x06, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, + 0x64, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x09, 0x64, 0x61, 0x74, 0x65, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, 0x0a, 0x0f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x0d, 0x64, 0x61, 0x74, - 0x65, 0x54, 0x69, 0x6d, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x78, 0x0a, 0x0c, 0x73, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x53, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, - 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x73, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x52, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x1a, 0xf8, 0x05, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, + 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x49, 0x64, 0x12, 0x42, 0x0a, + 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x0b, + 0x69, 0x73, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0a, 0x69, 0x73, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x1f, 0x0a, + 0x0a, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x09, 0x74, 0x65, 0x78, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, + 0x0a, 0x0c, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x09, 0x64, 0x61, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, 0x0a, 0x0f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x0d, 0x64, 0x61, + 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x50, 0x0a, 0x0c, 0x73, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, + 0x52, 0x0b, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x5a, 0x0a, + 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, + 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x10, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x31, 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, @@ -1032,58 +1039,44 @@ var file_services_property_svc_v1_property_value_svc_proto_rawDesc = []byte{ 0x79, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x30, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x88, 0x01, 0x01, 0x1a, 0x59, - 0x0a, 0x11, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x8c, 0x01, 0x0a, 0x10, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x78, - 0x0a, 0x0d, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x53, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x73, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x32, 0xb6, 0x02, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x84, 0x01, 0x0a, 0x13, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x70, 0x65, - 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, - 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, + 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x88, 0x01, 0x01, 0x42, 0x07, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x32, 0xb6, 0x02, + 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x84, 0x01, 0x0a, 0x13, 0x41, 0x74, 0x74, 0x61, 0x63, + 0x68, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, - 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x96, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x41, - 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x3a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x3b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x42, 0xd1, 0x01, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, - 0x31, 0x42, 0x15, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x53, 0x76, 0x63, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1c, 0x67, 0x65, 0x6e, 0x2f, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, - 0x79, 0x2d, 0x73, 0x76, 0x63, 0x2f, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x53, 0x50, 0x58, 0xaa, 0x02, - 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, - 0x74, 0x79, 0x53, 0x76, 0x63, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x96, 0x01, + 0x0a, 0x19, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, 0x6f, + 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x3a, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, + 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, + 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x73, 0x76, 0x63, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x50, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xd1, 0x01, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, + 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x42, 0x15, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, + 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x76, 0x63, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x1c, 0x67, 0x65, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2d, 0x73, 0x76, 0x63, 0x2f, 0x76, 0x31, 0xa2, 0x02, + 0x03, 0x53, 0x50, 0x58, 0xaa, 0x02, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x53, 0x76, 0x63, 0x2e, 0x56, 0x31, 0xca, 0x02, + 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, + 0x74, 0x79, 0x53, 0x76, 0x63, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x23, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x53, 0x76, 0x63, 0x5c, - 0x56, 0x31, 0xe2, 0x02, 0x23, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x50, 0x72, - 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x53, 0x76, 0x63, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x19, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x3a, 0x3a, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x53, 0x76, 0x63, - 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x19, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3a, 0x3a, 0x50, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x79, 0x53, 0x76, 0x63, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1100,39 +1093,39 @@ func file_services_property_svc_v1_property_value_svc_proto_rawDescGZIP() []byte var file_services_property_svc_v1_property_value_svc_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_services_property_svc_v1_property_value_svc_proto_goTypes = []interface{}{ - (*AttachPropertyValueRequest)(nil), // 0: services.property_svc.v1.AttachPropertyValueRequest - (*AttachPropertyValueResponse)(nil), // 1: services.property_svc.v1.AttachPropertyValueResponse - (*TaskPropertyMatcher)(nil), // 2: services.property_svc.v1.TaskPropertyMatcher - (*PatientPropertyMatcher)(nil), // 3: services.property_svc.v1.PatientPropertyMatcher - (*GetAttachedPropertyValuesRequest)(nil), // 4: services.property_svc.v1.GetAttachedPropertyValuesRequest - (*GetAttachedPropertyValuesResponse)(nil), // 5: services.property_svc.v1.GetAttachedPropertyValuesResponse - (*AttachPropertyValueRequest_MultiSelectValue)(nil), // 6: services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue - (*GetAttachedPropertyValuesResponse_Value)(nil), // 7: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value - (*GetAttachedPropertyValuesResponse_Value_SelectValueOption)(nil), // 8: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption - (*GetAttachedPropertyValuesResponse_Value_MultiSelectValue)(nil), // 9: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue + (*SelectValueOption)(nil), // 0: services.property_svc.v1.SelectValueOption + (*MultiSelectValue)(nil), // 1: services.property_svc.v1.MultiSelectValue + (*AttachPropertyValueRequest)(nil), // 2: services.property_svc.v1.AttachPropertyValueRequest + (*AttachPropertyValueResponse)(nil), // 3: services.property_svc.v1.AttachPropertyValueResponse + (*TaskPropertyMatcher)(nil), // 4: services.property_svc.v1.TaskPropertyMatcher + (*PatientPropertyMatcher)(nil), // 5: services.property_svc.v1.PatientPropertyMatcher + (*GetAttachedPropertyValuesRequest)(nil), // 6: services.property_svc.v1.GetAttachedPropertyValuesRequest + (*GetAttachedPropertyValuesResponse)(nil), // 7: services.property_svc.v1.GetAttachedPropertyValuesResponse + (*AttachPropertyValueRequest_MultiSelectValue)(nil), // 8: services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue + (*GetAttachedPropertyValuesResponse_Value)(nil), // 9: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value (*Date)(nil), // 10: services.property_svc.v1.Date (*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp (*v1.Conflict)(nil), // 12: libs.common.v1.Conflict (FieldType)(0), // 13: services.property_svc.v1.FieldType } var file_services_property_svc_v1_property_value_svc_proto_depIdxs = []int32{ - 10, // 0: services.property_svc.v1.AttachPropertyValueRequest.date_value:type_name -> services.property_svc.v1.Date - 11, // 1: services.property_svc.v1.AttachPropertyValueRequest.date_time_value:type_name -> google.protobuf.Timestamp - 6, // 2: services.property_svc.v1.AttachPropertyValueRequest.multi_select_value:type_name -> services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue - 12, // 3: services.property_svc.v1.AttachPropertyValueResponse.conflict:type_name -> libs.common.v1.Conflict - 2, // 4: services.property_svc.v1.GetAttachedPropertyValuesRequest.task_matcher:type_name -> services.property_svc.v1.TaskPropertyMatcher - 3, // 5: services.property_svc.v1.GetAttachedPropertyValuesRequest.patient_matcher:type_name -> services.property_svc.v1.PatientPropertyMatcher - 7, // 6: services.property_svc.v1.GetAttachedPropertyValuesResponse.values:type_name -> services.property_svc.v1.GetAttachedPropertyValuesResponse.Value - 13, // 7: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.field_type:type_name -> services.property_svc.v1.FieldType - 10, // 8: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.date_value:type_name -> services.property_svc.v1.Date - 11, // 9: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.date_time_value:type_name -> google.protobuf.Timestamp - 8, // 10: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.select_value:type_name -> services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption - 9, // 11: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.multi_select_value:type_name -> services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue - 8, // 12: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.select_values:type_name -> services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption - 0, // 13: services.property_svc.v1.PropertyValueService.AttachPropertyValue:input_type -> services.property_svc.v1.AttachPropertyValueRequest - 4, // 14: services.property_svc.v1.PropertyValueService.GetAttachedPropertyValues:input_type -> services.property_svc.v1.GetAttachedPropertyValuesRequest - 1, // 15: services.property_svc.v1.PropertyValueService.AttachPropertyValue:output_type -> services.property_svc.v1.AttachPropertyValueResponse - 5, // 16: services.property_svc.v1.PropertyValueService.GetAttachedPropertyValues:output_type -> services.property_svc.v1.GetAttachedPropertyValuesResponse + 0, // 0: services.property_svc.v1.MultiSelectValue.select_values:type_name -> services.property_svc.v1.SelectValueOption + 10, // 1: services.property_svc.v1.AttachPropertyValueRequest.date_value:type_name -> services.property_svc.v1.Date + 11, // 2: services.property_svc.v1.AttachPropertyValueRequest.date_time_value:type_name -> google.protobuf.Timestamp + 8, // 3: services.property_svc.v1.AttachPropertyValueRequest.multi_select_value:type_name -> services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue + 12, // 4: services.property_svc.v1.AttachPropertyValueResponse.conflict:type_name -> libs.common.v1.Conflict + 4, // 5: services.property_svc.v1.GetAttachedPropertyValuesRequest.task_matcher:type_name -> services.property_svc.v1.TaskPropertyMatcher + 5, // 6: services.property_svc.v1.GetAttachedPropertyValuesRequest.patient_matcher:type_name -> services.property_svc.v1.PatientPropertyMatcher + 9, // 7: services.property_svc.v1.GetAttachedPropertyValuesResponse.values:type_name -> services.property_svc.v1.GetAttachedPropertyValuesResponse.Value + 13, // 8: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.field_type:type_name -> services.property_svc.v1.FieldType + 10, // 9: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.date_value:type_name -> services.property_svc.v1.Date + 11, // 10: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.date_time_value:type_name -> google.protobuf.Timestamp + 0, // 11: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.select_value:type_name -> services.property_svc.v1.SelectValueOption + 1, // 12: services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.multi_select_value:type_name -> services.property_svc.v1.MultiSelectValue + 2, // 13: services.property_svc.v1.PropertyValueService.AttachPropertyValue:input_type -> services.property_svc.v1.AttachPropertyValueRequest + 6, // 14: services.property_svc.v1.PropertyValueService.GetAttachedPropertyValues:input_type -> services.property_svc.v1.GetAttachedPropertyValuesRequest + 3, // 15: services.property_svc.v1.PropertyValueService.AttachPropertyValue:output_type -> services.property_svc.v1.AttachPropertyValueResponse + 7, // 16: services.property_svc.v1.PropertyValueService.GetAttachedPropertyValues:output_type -> services.property_svc.v1.GetAttachedPropertyValuesResponse 15, // [15:17] is the sub-list for method output_type 13, // [13:15] is the sub-list for method input_type 13, // [13:13] is the sub-list for extension type_name @@ -1148,7 +1141,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { file_services_property_svc_v1_types_proto_init() if !protoimpl.UnsafeEnabled { file_services_property_svc_v1_property_value_svc_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AttachPropertyValueRequest); i { + switch v := v.(*SelectValueOption); i { case 0: return &v.state case 1: @@ -1160,7 +1153,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { } } file_services_property_svc_v1_property_value_svc_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AttachPropertyValueResponse); i { + switch v := v.(*MultiSelectValue); i { case 0: return &v.state case 1: @@ -1172,7 +1165,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { } } file_services_property_svc_v1_property_value_svc_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TaskPropertyMatcher); i { + switch v := v.(*AttachPropertyValueRequest); i { case 0: return &v.state case 1: @@ -1184,7 +1177,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { } } file_services_property_svc_v1_property_value_svc_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PatientPropertyMatcher); i { + switch v := v.(*AttachPropertyValueResponse); i { case 0: return &v.state case 1: @@ -1196,7 +1189,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { } } file_services_property_svc_v1_property_value_svc_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetAttachedPropertyValuesRequest); i { + switch v := v.(*TaskPropertyMatcher); i { case 0: return &v.state case 1: @@ -1208,7 +1201,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { } } file_services_property_svc_v1_property_value_svc_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetAttachedPropertyValuesResponse); i { + switch v := v.(*PatientPropertyMatcher); i { case 0: return &v.state case 1: @@ -1220,7 +1213,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { } } file_services_property_svc_v1_property_value_svc_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AttachPropertyValueRequest_MultiSelectValue); i { + switch v := v.(*GetAttachedPropertyValuesRequest); i { case 0: return &v.state case 1: @@ -1232,7 +1225,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { } } file_services_property_svc_v1_property_value_svc_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetAttachedPropertyValuesResponse_Value); i { + switch v := v.(*GetAttachedPropertyValuesResponse); i { case 0: return &v.state case 1: @@ -1244,7 +1237,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { } } file_services_property_svc_v1_property_value_svc_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetAttachedPropertyValuesResponse_Value_SelectValueOption); i { + switch v := v.(*AttachPropertyValueRequest_MultiSelectValue); i { case 0: return &v.state case 1: @@ -1256,7 +1249,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { } } file_services_property_svc_v1_property_value_svc_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetAttachedPropertyValuesResponse_Value_MultiSelectValue); i { + switch v := v.(*GetAttachedPropertyValuesResponse_Value); i { case 0: return &v.state case 1: @@ -1268,7 +1261,7 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { } } } - file_services_property_svc_v1_property_value_svc_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_services_property_svc_v1_property_value_svc_proto_msgTypes[2].OneofWrappers = []interface{}{ (*AttachPropertyValueRequest_TextValue)(nil), (*AttachPropertyValueRequest_NumberValue)(nil), (*AttachPropertyValueRequest_BoolValue)(nil), @@ -1277,21 +1270,21 @@ func file_services_property_svc_v1_property_value_svc_proto_init() { (*AttachPropertyValueRequest_SelectValue)(nil), (*AttachPropertyValueRequest_MultiSelectValue_)(nil), } - file_services_property_svc_v1_property_value_svc_proto_msgTypes[1].OneofWrappers = []interface{}{} - file_services_property_svc_v1_property_value_svc_proto_msgTypes[2].OneofWrappers = []interface{}{} file_services_property_svc_v1_property_value_svc_proto_msgTypes[3].OneofWrappers = []interface{}{} - file_services_property_svc_v1_property_value_svc_proto_msgTypes[4].OneofWrappers = []interface{}{ + file_services_property_svc_v1_property_value_svc_proto_msgTypes[4].OneofWrappers = []interface{}{} + file_services_property_svc_v1_property_value_svc_proto_msgTypes[5].OneofWrappers = []interface{}{} + file_services_property_svc_v1_property_value_svc_proto_msgTypes[6].OneofWrappers = []interface{}{ (*GetAttachedPropertyValuesRequest_TaskMatcher)(nil), (*GetAttachedPropertyValuesRequest_PatientMatcher)(nil), } - file_services_property_svc_v1_property_value_svc_proto_msgTypes[7].OneofWrappers = []interface{}{ + file_services_property_svc_v1_property_value_svc_proto_msgTypes[9].OneofWrappers = []interface{}{ (*GetAttachedPropertyValuesResponse_Value_TextValue)(nil), (*GetAttachedPropertyValuesResponse_Value_NumberValue)(nil), (*GetAttachedPropertyValuesResponse_Value_BoolValue)(nil), (*GetAttachedPropertyValuesResponse_Value_DateValue)(nil), (*GetAttachedPropertyValuesResponse_Value_DateTimeValue)(nil), (*GetAttachedPropertyValuesResponse_Value_SelectValue)(nil), - (*GetAttachedPropertyValuesResponse_Value_MultiSelectValue_)(nil), + (*GetAttachedPropertyValuesResponse_Value_MultiSelectValue)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/gen/go/services/property_svc/v1/types.pb.go b/gen/go/services/property_svc/v1/types.pb.go index 519df131e..48a7f41dc 100644 --- a/gen/go/services/property_svc/v1/types.pb.go +++ b/gen/go/services/property_svc/v1/types.pb.go @@ -140,7 +140,7 @@ type Date struct { unknownFields protoimpl.UnknownFields // information more precise than date information shall be disregarded by clients - Date *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=date,proto3" json:"date,omitempty"` + Date *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=date,proto3" json:"date,omitempty" validate:"required"` // @gotags: validate:"required" } func (x *Date) Reset() { diff --git a/gen/go/services/tasks_svc/v1/task_svc.pb.go b/gen/go/services/tasks_svc/v1/task_svc.pb.go index 2680e4240..2ff796661 100644 --- a/gen/go/services/tasks_svc/v1/task_svc.pb.go +++ b/gen/go/services/tasks_svc/v1/task_svc.pb.go @@ -924,9 +924,8 @@ type UnassignTaskRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - TaskId string `protobuf:"bytes,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty" validate:"uuid4"` // @gotags: validate:"uuid4" - UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty" validate:"uuid4"` // @gotags: validate:"uuid4" - Consistency *string `protobuf:"bytes,3,opt,name=consistency,proto3,oneof" json:"consistency,omitempty"` // no conflict detection, if not provided + TaskId string `protobuf:"bytes,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty" validate:"uuid4"` // @gotags: validate:"uuid4" + UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty" validate:"uuid4"` // @gotags: validate:"uuid4" } func (x *UnassignTaskRequest) Reset() { @@ -975,13 +974,6 @@ func (x *UnassignTaskRequest) GetUserId() string { return "" } -func (x *UnassignTaskRequest) GetConsistency() string { - if x != nil && x.Consistency != nil { - return *x.Consistency - } - return "" -} - type UnassignTaskResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2836,191 +2828,188 @@ var file_services_tasks_svc_v1_task_svc_proto_rawDesc = []byte{ 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x0b, 0x0a, 0x09, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x22, 0x7e, 0x0a, 0x13, 0x55, 0x6e, 0x61, + 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x22, 0x47, 0x0a, 0x13, 0x55, 0x6e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x6f, - 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x80, 0x01, 0x0a, 0x14, 0x55, 0x6e, - 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x48, 0x00, - 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, - 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x42, - 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x22, 0xbf, 0x01, 0x0a, - 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x4d, - 0x0a, 0x07, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x33, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, - 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x75, 0x62, - 0x74, 0x61, 0x73, 0x6b, 0x52, 0x07, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x1a, 0x3f, 0x0a, - 0x07, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x04, - 0x64, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x64, 0x6f, - 0x6e, 0x65, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x64, 0x6f, 0x6e, 0x65, 0x22, 0x61, - 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x74, 0x61, - 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, - 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x63, - 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0f, 0x74, 0x61, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, - 0x79, 0x22, 0xb1, 0x02, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, - 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, - 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, - 0x6b, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, - 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, - 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x07, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, - 0x6b, 0x12, 0x2e, 0x0a, 0x10, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0f, 0x74, - 0x61, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x88, 0x01, - 0x01, 0x1a, 0x4d, 0x0a, 0x07, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x12, 0x17, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x88, 0x01, 0x01, 0x42, 0x07, - 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x64, 0x6f, 0x6e, 0x65, - 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x8a, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x18, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x48, 0x00, 0x52, 0x08, 0x63, - 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x61, - 0x73, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x61, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, - 0x63, 0x74, 0x22, 0x4e, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, - 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, - 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, - 0x6b, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, - 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, - 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, 0x0a, 0x18, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x75, 0x65, 0x44, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, - 0x22, 0x3d, 0x0a, 0x19, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x75, - 0x65, 0x44, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, - 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22, - 0x23, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, - 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc2, 0x0b, 0x0a, 0x0b, 0x54, - 0x61, 0x73, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x0a, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x49, 0x64, 0x22, 0x80, 0x01, 0x0a, 0x14, 0x55, 0x6e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, + 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x63, + 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x6c, 0x69, 0x62, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x66, 0x6c, + 0x69, 0x63, 0x74, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, + 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x6f, 0x6e, + 0x66, 0x6c, 0x69, 0x63, 0x74, 0x22, 0xbf, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, + 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x74, 0x61, + 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, - 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x63, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x28, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, - 0x25, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x07, 0x73, + 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x1a, 0x3f, 0x0a, 0x07, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, + 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x88, 0x01, 0x01, 0x42, 0x07, + 0x0a, 0x05, 0x5f, 0x64, 0x6f, 0x6e, 0x65, 0x22, 0x61, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, + 0x29, 0x0a, 0x10, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x61, 0x73, 0x6b, 0x43, + 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xb1, 0x02, 0x0a, 0x14, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x07, 0x73, + 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, + 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, + 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, + 0x6b, 0x52, 0x07, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x12, 0x2e, 0x0a, 0x10, 0x74, 0x61, + 0x73, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0f, 0x74, 0x61, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x73, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x88, 0x01, 0x01, 0x1a, 0x4d, 0x0a, 0x07, 0x53, 0x75, + 0x62, 0x74, 0x61, 0x73, 0x6b, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x17, + 0x0a, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x04, + 0x64, 0x6f, 0x6e, 0x65, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x64, 0x6f, 0x6e, 0x65, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x74, 0x61, + 0x73, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x8a, + 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x66, + 0x6c, 0x69, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6c, 0x69, 0x62, + 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, + 0x6c, 0x69, 0x63, 0x74, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, + 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x73, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, + 0x61, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x0b, + 0x0a, 0x09, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x22, 0x4e, 0x0a, 0x14, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, + 0x73, 0x6b, 0x44, 0x75, 0x65, 0x44, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0x3d, 0x0a, 0x19, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x75, 0x65, 0x44, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, + 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x23, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x14, 0x0a, + 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x32, 0xc2, 0x0b, 0x0a, 0x0b, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, + 0x6b, 0x12, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, + 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x63, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, + 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, + 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, + 0x07, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x25, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x78, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x42, 0x79, 0x50, 0x61, - 0x74, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x2f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x42, 0x79, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x42, 0x79, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xa2, 0x01, 0x0a, 0x1f, 0x47, - 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x42, 0x79, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, - 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3d, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x78, 0x0a, 0x11, 0x47, 0x65, 0x74, + 0x54, 0x61, 0x73, 0x6b, 0x73, 0x42, 0x79, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x2f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x42, - 0x79, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, + 0x79, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x30, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, + 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, + 0x42, 0x79, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0xa2, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, + 0x42, 0x79, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, + 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x42, 0x79, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, + 0x74, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x42, 0x79, 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, + 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x75, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, + 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x2e, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, + 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, + 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x63, 0x0a, 0x0a, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x28, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, + 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x69, 0x0a, 0x0c, 0x55, 0x6e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, + 0x54, 0x61, 0x73, 0x6b, 0x12, 0x2a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x61, + 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, + 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x61, 0x73, 0x73, 0x69, 0x67, + 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x6c, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, + 0x12, 0x2b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, + 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, + 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x42, 0x79, - 0x50, 0x61, 0x74, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x75, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x61, - 0x73, 0x6b, 0x73, 0x12, 0x2e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, - 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, - 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, - 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, - 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x63, 0x0a, 0x0a, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, - 0x54, 0x61, 0x73, 0x6b, 0x12, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, - 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, - 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, + 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, + 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6c, 0x0a, + 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x12, 0x2b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, - 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x69, 0x0a, 0x0c, 0x55, - 0x6e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x2a, 0x2e, 0x73, 0x65, + 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, + 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, 0x6b, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x6e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6c, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x12, 0x2b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, - 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x6c, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x62, 0x74, 0x61, 0x73, 0x6b, 0x12, 0x2b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, - 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x6c, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, - 0x61, 0x73, 0x6b, 0x12, 0x2b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, - 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, - 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, - 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x78, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x75, - 0x65, 0x44, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x75, 0x65, 0x44, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x75, 0x65, 0x44, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x63, 0x0a, 0x0a, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, - 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, - 0xb6, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x54, - 0x61, 0x73, 0x6b, 0x53, 0x76, 0x63, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x19, 0x67, - 0x65, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, 0x61, 0x73, 0x6b, - 0x73, 0x2d, 0x73, 0x76, 0x63, 0x2f, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x53, 0x54, 0x58, 0xaa, 0x02, - 0x14, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x53, - 0x76, 0x63, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x14, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x5c, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x53, 0x76, 0x63, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x20, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x53, 0x76, 0x63, - 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3a, 0x3a, 0x54, 0x61, 0x73, 0x6b, - 0x73, 0x53, 0x76, 0x63, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6c, 0x0a, 0x0d, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x12, 0x2b, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, + 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, + 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x74, 0x61, 0x73, 0x6b, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x78, 0x0a, 0x11, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x75, 0x65, 0x44, 0x61, 0x74, 0x65, 0x12, 0x2f, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, + 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x73, + 0x6b, 0x44, 0x75, 0x65, 0x44, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x30, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, + 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, + 0x73, 0x6b, 0x44, 0x75, 0x65, 0x44, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x63, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x73, + 0x6b, 0x12, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, + 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, 0x73, 0x76, 0x63, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xb6, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x5f, + 0x73, 0x76, 0x63, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x76, 0x63, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x19, 0x67, 0x65, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2d, 0x73, 0x76, 0x63, 0x2f, 0x76, + 0x31, 0xa2, 0x02, 0x03, 0x53, 0x54, 0x58, 0xaa, 0x02, 0x14, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x53, 0x76, 0x63, 0x2e, 0x56, 0x31, 0xca, 0x02, + 0x14, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x53, + 0x76, 0x63, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x5c, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x53, 0x76, 0x63, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x3a, 0x3a, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x53, 0x76, 0x63, 0x3a, 0x3a, 0x56, + 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3616,7 +3605,6 @@ func file_services_tasks_svc_v1_task_svc_proto_init() { file_services_tasks_svc_v1_task_svc_proto_msgTypes[5].OneofWrappers = []interface{}{} file_services_tasks_svc_v1_task_svc_proto_msgTypes[12].OneofWrappers = []interface{}{} file_services_tasks_svc_v1_task_svc_proto_msgTypes[13].OneofWrappers = []interface{}{} - file_services_tasks_svc_v1_task_svc_proto_msgTypes[14].OneofWrappers = []interface{}{} file_services_tasks_svc_v1_task_svc_proto_msgTypes[15].OneofWrappers = []interface{}{} file_services_tasks_svc_v1_task_svc_proto_msgTypes[18].OneofWrappers = []interface{}{} file_services_tasks_svc_v1_task_svc_proto_msgTypes[19].OneofWrappers = []interface{}{} diff --git a/gen/ts/libs/common/v1/conflict_pb.d.ts b/gen/ts/libs/common/v1/conflict_pb.d.ts index 8c850b6ac..baad5aecb 100644 --- a/gen/ts/libs/common/v1/conflict_pb.d.ts +++ b/gen/ts/libs/common/v1/conflict_pb.d.ts @@ -7,6 +7,9 @@ export class Conflict extends jspb.Message { getConflictingAttributesMap(): jspb.Map; clearConflictingAttributesMap(): Conflict; + getHistoryMissing(): boolean; + setHistoryMissing(value: boolean): Conflict; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): Conflict.AsObject; static toObject(includeInstance: boolean, msg: Conflict): Conflict.AsObject; @@ -18,6 +21,7 @@ export class Conflict extends jspb.Message { export namespace Conflict { export type AsObject = { conflictingAttributesMap: Array<[string, AttributeConflict.AsObject]>, + historyMissing: boolean, } } @@ -47,3 +51,23 @@ export namespace AttributeConflict { } } +export class AnyArray extends jspb.Message { + getElementsList(): Array; + setElementsList(value: Array): AnyArray; + clearElementsList(): AnyArray; + addElements(value?: google_protobuf_any_pb.Any, index?: number): google_protobuf_any_pb.Any; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): AnyArray.AsObject; + static toObject(includeInstance: boolean, msg: AnyArray): AnyArray.AsObject; + static serializeBinaryToWriter(message: AnyArray, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): AnyArray; + static deserializeBinaryFromReader(message: AnyArray, reader: jspb.BinaryReader): AnyArray; +} + +export namespace AnyArray { + export type AsObject = { + elementsList: Array, + } +} + diff --git a/gen/ts/libs/common/v1/conflict_pb.js b/gen/ts/libs/common/v1/conflict_pb.js index c6aa8144a..495b0911e 100644 --- a/gen/ts/libs/common/v1/conflict_pb.js +++ b/gen/ts/libs/common/v1/conflict_pb.js @@ -23,6 +23,7 @@ var global = var google_protobuf_any_pb = require('google-protobuf/google/protobuf/any_pb.js'); goog.object.extend(proto, google_protobuf_any_pb); +goog.exportSymbol('proto.libs.common.v1.AnyArray', null, global); goog.exportSymbol('proto.libs.common.v1.AttributeConflict', null, global); goog.exportSymbol('proto.libs.common.v1.Conflict', null, global); /** @@ -67,6 +68,27 @@ if (goog.DEBUG && !COMPILED) { */ proto.libs.common.v1.AttributeConflict.displayName = 'proto.libs.common.v1.AttributeConflict'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.libs.common.v1.AnyArray = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.libs.common.v1.AnyArray.repeatedFields_, null); +}; +goog.inherits(proto.libs.common.v1.AnyArray, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.libs.common.v1.AnyArray.displayName = 'proto.libs.common.v1.AnyArray'; +} @@ -99,7 +121,8 @@ proto.libs.common.v1.Conflict.prototype.toObject = function(opt_includeInstance) */ proto.libs.common.v1.Conflict.toObject = function(includeInstance, msg) { var f, obj = { - conflictingAttributesMap: (f = msg.getConflictingAttributesMap()) ? f.toObject(includeInstance, proto.libs.common.v1.AttributeConflict.toObject) : [] + conflictingAttributesMap: (f = msg.getConflictingAttributesMap()) ? f.toObject(includeInstance, proto.libs.common.v1.AttributeConflict.toObject) : [], + historyMissing: jspb.Message.getBooleanFieldWithDefault(msg, 2, false) }; if (includeInstance) { @@ -142,6 +165,10 @@ proto.libs.common.v1.Conflict.deserializeBinaryFromReader = function(msg, reader jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readString, jspb.BinaryReader.prototype.readMessage, proto.libs.common.v1.AttributeConflict.deserializeBinaryFromReader, "", new proto.libs.common.v1.AttributeConflict()); }); break; + case 2: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setHistoryMissing(value); + break; default: reader.skipField(); break; @@ -175,6 +202,13 @@ proto.libs.common.v1.Conflict.serializeBinaryToWriter = function(message, writer if (f && f.getLength() > 0) { f.serializeBinary(1, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeMessage, proto.libs.common.v1.AttributeConflict.serializeBinaryToWriter); } + f = message.getHistoryMissing(); + if (f) { + writer.writeBool( + 2, + f + ); + } }; @@ -201,6 +235,24 @@ proto.libs.common.v1.Conflict.prototype.clearConflictingAttributesMap = function }; +/** + * optional bool history_missing = 2; + * @return {boolean} + */ +proto.libs.common.v1.Conflict.prototype.getHistoryMissing = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.libs.common.v1.Conflict} returns this + */ +proto.libs.common.v1.Conflict.prototype.setHistoryMissing = function(value) { + return jspb.Message.setProto3BooleanField(this, 2, value); +}; + + @@ -403,4 +455,164 @@ proto.libs.common.v1.AttributeConflict.prototype.hasWant = function() { }; + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.libs.common.v1.AnyArray.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.libs.common.v1.AnyArray.prototype.toObject = function(opt_includeInstance) { + return proto.libs.common.v1.AnyArray.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.libs.common.v1.AnyArray} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.libs.common.v1.AnyArray.toObject = function(includeInstance, msg) { + var f, obj = { + elementsList: jspb.Message.toObjectList(msg.getElementsList(), + google_protobuf_any_pb.Any.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.libs.common.v1.AnyArray} + */ +proto.libs.common.v1.AnyArray.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.libs.common.v1.AnyArray; + return proto.libs.common.v1.AnyArray.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.libs.common.v1.AnyArray} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.libs.common.v1.AnyArray} + */ +proto.libs.common.v1.AnyArray.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new google_protobuf_any_pb.Any; + reader.readMessage(value,google_protobuf_any_pb.Any.deserializeBinaryFromReader); + msg.addElements(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.libs.common.v1.AnyArray.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.libs.common.v1.AnyArray.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.libs.common.v1.AnyArray} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.libs.common.v1.AnyArray.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getElementsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + google_protobuf_any_pb.Any.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated google.protobuf.Any elements = 1; + * @return {!Array} + */ +proto.libs.common.v1.AnyArray.prototype.getElementsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, google_protobuf_any_pb.Any, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.libs.common.v1.AnyArray} returns this +*/ +proto.libs.common.v1.AnyArray.prototype.setElementsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.google.protobuf.Any=} opt_value + * @param {number=} opt_index + * @return {!proto.google.protobuf.Any} + */ +proto.libs.common.v1.AnyArray.prototype.addElements = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.google.protobuf.Any, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.libs.common.v1.AnyArray} returns this + */ +proto.libs.common.v1.AnyArray.prototype.clearElementsList = function() { + return this.setElementsList([]); +}; + + goog.object.extend(exports, proto.libs.common.v1); diff --git a/gen/ts/services/property_svc/v1/property_value_svc_pb.d.ts b/gen/ts/services/property_svc/v1/property_value_svc_pb.d.ts index 373589c48..6b9ae98ae 100644 --- a/gen/ts/services/property_svc/v1/property_value_svc_pb.d.ts +++ b/gen/ts/services/property_svc/v1/property_value_svc_pb.d.ts @@ -5,6 +5,52 @@ import * as google_protobuf_timestamp_pb from 'google-protobuf/google/protobuf/t import * as libs_common_v1_conflict_pb from '../../../libs/common/v1/conflict_pb'; // proto import: "libs/common/v1/conflict.proto" +export class SelectValueOption extends jspb.Message { + getId(): string; + setId(value: string): SelectValueOption; + + getName(): string; + setName(value: string): SelectValueOption; + + getDescription(): string; + setDescription(value: string): SelectValueOption; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): SelectValueOption.AsObject; + static toObject(includeInstance: boolean, msg: SelectValueOption): SelectValueOption.AsObject; + static serializeBinaryToWriter(message: SelectValueOption, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): SelectValueOption; + static deserializeBinaryFromReader(message: SelectValueOption, reader: jspb.BinaryReader): SelectValueOption; +} + +export namespace SelectValueOption { + export type AsObject = { + id: string, + name: string, + description: string, + } +} + +export class MultiSelectValue extends jspb.Message { + getSelectValuesList(): Array; + setSelectValuesList(value: Array): MultiSelectValue; + clearSelectValuesList(): MultiSelectValue; + addSelectValues(value?: SelectValueOption, index?: number): SelectValueOption; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): MultiSelectValue.AsObject; + static toObject(includeInstance: boolean, msg: MultiSelectValue): MultiSelectValue.AsObject; + static serializeBinaryToWriter(message: MultiSelectValue, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): MultiSelectValue; + static deserializeBinaryFromReader(message: MultiSelectValue, reader: jspb.BinaryReader): MultiSelectValue; +} + +export namespace MultiSelectValue { + export type AsObject = { + selectValuesList: Array, + } +} + export class AttachPropertyValueRequest extends jspb.Message { getSubjectId(): string; setSubjectId(value: string): AttachPropertyValueRequest; @@ -307,13 +353,13 @@ export namespace GetAttachedPropertyValuesResponse { hasDateTimeValue(): boolean; clearDateTimeValue(): Value; - getSelectValue(): GetAttachedPropertyValuesResponse.Value.SelectValueOption | undefined; - setSelectValue(value?: GetAttachedPropertyValuesResponse.Value.SelectValueOption): Value; + getSelectValue(): SelectValueOption | undefined; + setSelectValue(value?: SelectValueOption): Value; hasSelectValue(): boolean; clearSelectValue(): Value; - getMultiSelectValue(): GetAttachedPropertyValuesResponse.Value.MultiSelectValue | undefined; - setMultiSelectValue(value?: GetAttachedPropertyValuesResponse.Value.MultiSelectValue): Value; + getMultiSelectValue(): MultiSelectValue | undefined; + setMultiSelectValue(value?: MultiSelectValue): Value; hasMultiSelectValue(): boolean; clearMultiSelectValue(): Value; @@ -347,60 +393,12 @@ export namespace GetAttachedPropertyValuesResponse { boolValue: boolean, dateValue?: services_property_svc_v1_types_pb.Date.AsObject, dateTimeValue?: google_protobuf_timestamp_pb.Timestamp.AsObject, - selectValue?: GetAttachedPropertyValuesResponse.Value.SelectValueOption.AsObject, - multiSelectValue?: GetAttachedPropertyValuesResponse.Value.MultiSelectValue.AsObject, + selectValue?: SelectValueOption.AsObject, + multiSelectValue?: MultiSelectValue.AsObject, propertyConsistency: string, valueConsistency?: string, } - export class SelectValueOption extends jspb.Message { - getId(): string; - setId(value: string): SelectValueOption; - - getName(): string; - setName(value: string): SelectValueOption; - - getDescription(): string; - setDescription(value: string): SelectValueOption; - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): SelectValueOption.AsObject; - static toObject(includeInstance: boolean, msg: SelectValueOption): SelectValueOption.AsObject; - static serializeBinaryToWriter(message: SelectValueOption, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): SelectValueOption; - static deserializeBinaryFromReader(message: SelectValueOption, reader: jspb.BinaryReader): SelectValueOption; - } - - export namespace SelectValueOption { - export type AsObject = { - id: string, - name: string, - description: string, - } - } - - - export class MultiSelectValue extends jspb.Message { - getSelectValuesList(): Array; - setSelectValuesList(value: Array): MultiSelectValue; - clearSelectValuesList(): MultiSelectValue; - addSelectValues(value?: GetAttachedPropertyValuesResponse.Value.SelectValueOption, index?: number): GetAttachedPropertyValuesResponse.Value.SelectValueOption; - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): MultiSelectValue.AsObject; - static toObject(includeInstance: boolean, msg: MultiSelectValue): MultiSelectValue.AsObject; - static serializeBinaryToWriter(message: MultiSelectValue, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): MultiSelectValue; - static deserializeBinaryFromReader(message: MultiSelectValue, reader: jspb.BinaryReader): MultiSelectValue; - } - - export namespace MultiSelectValue { - export type AsObject = { - selectValuesList: Array, - } - } - - export enum ValueCase { VALUE_NOT_SET = 0, TEXT_VALUE = 6, diff --git a/gen/ts/services/property_svc/v1/property_value_svc_pb.js b/gen/ts/services/property_svc/v1/property_value_svc_pb.js index 469399ba5..21e796b49 100644 --- a/gen/ts/services/property_svc/v1/property_value_svc_pb.js +++ b/gen/ts/services/property_svc/v1/property_value_svc_pb.js @@ -35,10 +35,10 @@ goog.exportSymbol('proto.services.property_svc.v1.GetAttachedPropertyValuesReque goog.exportSymbol('proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.MatcherCase', null, global); goog.exportSymbol('proto.services.property_svc.v1.GetAttachedPropertyValuesResponse', null, global); goog.exportSymbol('proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value', null, global); -goog.exportSymbol('proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue', null, global); -goog.exportSymbol('proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption', null, global); goog.exportSymbol('proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.ValueCase', null, global); +goog.exportSymbol('proto.services.property_svc.v1.MultiSelectValue', null, global); goog.exportSymbol('proto.services.property_svc.v1.PatientPropertyMatcher', null, global); +goog.exportSymbol('proto.services.property_svc.v1.SelectValueOption', null, global); goog.exportSymbol('proto.services.property_svc.v1.TaskPropertyMatcher', null, global); /** * Generated by JsPbCodeGenerator. @@ -50,16 +50,16 @@ goog.exportSymbol('proto.services.property_svc.v1.TaskPropertyMatcher', null, gl * @extends {jspb.Message} * @constructor */ -proto.services.property_svc.v1.AttachPropertyValueRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_); +proto.services.property_svc.v1.SelectValueOption = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.services.property_svc.v1.AttachPropertyValueRequest, jspb.Message); +goog.inherits(proto.services.property_svc.v1.SelectValueOption, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.services.property_svc.v1.AttachPropertyValueRequest.displayName = 'proto.services.property_svc.v1.AttachPropertyValueRequest'; + proto.services.property_svc.v1.SelectValueOption.displayName = 'proto.services.property_svc.v1.SelectValueOption'; } /** * Generated by JsPbCodeGenerator. @@ -71,16 +71,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.repeatedFields_, null); +proto.services.property_svc.v1.MultiSelectValue = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.services.property_svc.v1.MultiSelectValue.repeatedFields_, null); }; -goog.inherits(proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue, jspb.Message); +goog.inherits(proto.services.property_svc.v1.MultiSelectValue, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.displayName = 'proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue'; + proto.services.property_svc.v1.MultiSelectValue.displayName = 'proto.services.property_svc.v1.MultiSelectValue'; } /** * Generated by JsPbCodeGenerator. @@ -92,16 +92,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.services.property_svc.v1.AttachPropertyValueResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); +proto.services.property_svc.v1.AttachPropertyValueRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_); }; -goog.inherits(proto.services.property_svc.v1.AttachPropertyValueResponse, jspb.Message); +goog.inherits(proto.services.property_svc.v1.AttachPropertyValueRequest, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.services.property_svc.v1.AttachPropertyValueResponse.displayName = 'proto.services.property_svc.v1.AttachPropertyValueResponse'; + proto.services.property_svc.v1.AttachPropertyValueRequest.displayName = 'proto.services.property_svc.v1.AttachPropertyValueRequest'; } /** * Generated by JsPbCodeGenerator. @@ -113,16 +113,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.services.property_svc.v1.TaskPropertyMatcher = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.repeatedFields_, null); }; -goog.inherits(proto.services.property_svc.v1.TaskPropertyMatcher, jspb.Message); +goog.inherits(proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.services.property_svc.v1.TaskPropertyMatcher.displayName = 'proto.services.property_svc.v1.TaskPropertyMatcher'; + proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.displayName = 'proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue'; } /** * Generated by JsPbCodeGenerator. @@ -134,16 +134,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.services.property_svc.v1.PatientPropertyMatcher = function(opt_data) { +proto.services.property_svc.v1.AttachPropertyValueResponse = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.services.property_svc.v1.PatientPropertyMatcher, jspb.Message); +goog.inherits(proto.services.property_svc.v1.AttachPropertyValueResponse, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.services.property_svc.v1.PatientPropertyMatcher.displayName = 'proto.services.property_svc.v1.PatientPropertyMatcher'; + proto.services.property_svc.v1.AttachPropertyValueResponse.displayName = 'proto.services.property_svc.v1.AttachPropertyValueResponse'; } /** * Generated by JsPbCodeGenerator. @@ -155,16 +155,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.oneofGroups_); +proto.services.property_svc.v1.TaskPropertyMatcher = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.services.property_svc.v1.GetAttachedPropertyValuesRequest, jspb.Message); +goog.inherits(proto.services.property_svc.v1.TaskPropertyMatcher, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.displayName = 'proto.services.property_svc.v1.GetAttachedPropertyValuesRequest'; + proto.services.property_svc.v1.TaskPropertyMatcher.displayName = 'proto.services.property_svc.v1.TaskPropertyMatcher'; } /** * Generated by JsPbCodeGenerator. @@ -176,16 +176,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.repeatedFields_, null); +proto.services.property_svc.v1.PatientPropertyMatcher = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.services.property_svc.v1.GetAttachedPropertyValuesResponse, jspb.Message); +goog.inherits(proto.services.property_svc.v1.PatientPropertyMatcher, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.displayName = 'proto.services.property_svc.v1.GetAttachedPropertyValuesResponse'; + proto.services.property_svc.v1.PatientPropertyMatcher.displayName = 'proto.services.property_svc.v1.PatientPropertyMatcher'; } /** * Generated by JsPbCodeGenerator. @@ -197,16 +197,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.oneofGroups_); +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.oneofGroups_); }; -goog.inherits(proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value, jspb.Message); +goog.inherits(proto.services.property_svc.v1.GetAttachedPropertyValuesRequest, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.displayName = 'proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value'; + proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.displayName = 'proto.services.property_svc.v1.GetAttachedPropertyValuesRequest'; } /** * Generated by JsPbCodeGenerator. @@ -218,16 +218,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.repeatedFields_, null); }; -goog.inherits(proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption, jspb.Message); +goog.inherits(proto.services.property_svc.v1.GetAttachedPropertyValuesResponse, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.displayName = 'proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption'; + proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.displayName = 'proto.services.property_svc.v1.GetAttachedPropertyValuesResponse'; } /** * Generated by JsPbCodeGenerator. @@ -239,49 +239,18 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.repeatedFields_, null); +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.oneofGroups_); }; -goog.inherits(proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue, jspb.Message); +goog.inherits(proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.displayName = 'proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue'; + proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.displayName = 'proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value'; } -/** - * Oneof group definitions for this message. Each group defines the field - * numbers belonging to that group. When of these fields' value is set, all - * other fields in the group are cleared. During deserialization, if multiple - * fields are encountered for a group, only the last value seen will be kept. - * @private {!Array>} - * @const - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_ = [[3,4,5,6,7,8,9]]; - -/** - * @enum {number} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.ValueCase = { - VALUE_NOT_SET: 0, - TEXT_VALUE: 3, - NUMBER_VALUE: 4, - BOOL_VALUE: 5, - DATE_VALUE: 6, - DATE_TIME_VALUE: 7, - SELECT_VALUE: 8, - MULTI_SELECT_VALUE: 9 -}; - -/** - * @return {proto.services.property_svc.v1.AttachPropertyValueRequest.ValueCase} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getValueCase = function() { - return /** @type {proto.services.property_svc.v1.AttachPropertyValueRequest.ValueCase} */(jspb.Message.computeOneofCase(this, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0])); -}; - if (jspb.Message.GENERATE_TO_OBJECT) { @@ -297,8 +266,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.toObject = function(opt_includeInstance) { - return proto.services.property_svc.v1.AttachPropertyValueRequest.toObject(opt_includeInstance, this); +proto.services.property_svc.v1.SelectValueOption.prototype.toObject = function(opt_includeInstance) { + return proto.services.property_svc.v1.SelectValueOption.toObject(opt_includeInstance, this); }; @@ -307,22 +276,15 @@ proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.toObject = f * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest} msg The msg instance to transform. + * @param {!proto.services.property_svc.v1.SelectValueOption} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.AttachPropertyValueRequest.toObject = function(includeInstance, msg) { +proto.services.property_svc.v1.SelectValueOption.toObject = function(includeInstance, msg) { var f, obj = { - subjectId: jspb.Message.getFieldWithDefault(msg, 1, ""), - propertyId: jspb.Message.getFieldWithDefault(msg, 2, ""), - textValue: jspb.Message.getFieldWithDefault(msg, 3, ""), - numberValue: jspb.Message.getFloatingPointFieldWithDefault(msg, 4, 0.0), - boolValue: jspb.Message.getBooleanFieldWithDefault(msg, 5, false), - dateValue: (f = msg.getDateValue()) && services_property_svc_v1_types_pb.Date.toObject(includeInstance, f), - dateTimeValue: (f = msg.getDateTimeValue()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f), - selectValue: jspb.Message.getFieldWithDefault(msg, 8, ""), - multiSelectValue: (f = msg.getMultiSelectValue()) && proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.toObject(includeInstance, f), - consistency: jspb.Message.getFieldWithDefault(msg, 10, "") + id: jspb.Message.getFieldWithDefault(msg, 1, ""), + name: jspb.Message.getFieldWithDefault(msg, 2, ""), + description: jspb.Message.getFieldWithDefault(msg, 3, "") }; if (includeInstance) { @@ -336,23 +298,23 @@ proto.services.property_svc.v1.AttachPropertyValueRequest.toObject = function(in /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} + * @return {!proto.services.property_svc.v1.SelectValueOption} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.deserializeBinary = function(bytes) { +proto.services.property_svc.v1.SelectValueOption.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.services.property_svc.v1.AttachPropertyValueRequest; - return proto.services.property_svc.v1.AttachPropertyValueRequest.deserializeBinaryFromReader(msg, reader); + var msg = new proto.services.property_svc.v1.SelectValueOption; + return proto.services.property_svc.v1.SelectValueOption.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest} msg The message object to deserialize into. + * @param {!proto.services.property_svc.v1.SelectValueOption} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} + * @return {!proto.services.property_svc.v1.SelectValueOption} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.deserializeBinaryFromReader = function(msg, reader) { +proto.services.property_svc.v1.SelectValueOption.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -361,46 +323,15 @@ proto.services.property_svc.v1.AttachPropertyValueRequest.deserializeBinaryFromR switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); - msg.setSubjectId(value); + msg.setId(value); break; case 2: var value = /** @type {string} */ (reader.readString()); - msg.setPropertyId(value); + msg.setName(value); break; case 3: var value = /** @type {string} */ (reader.readString()); - msg.setTextValue(value); - break; - case 4: - var value = /** @type {number} */ (reader.readDouble()); - msg.setNumberValue(value); - break; - case 5: - var value = /** @type {boolean} */ (reader.readBool()); - msg.setBoolValue(value); - break; - case 6: - var value = new services_property_svc_v1_types_pb.Date; - reader.readMessage(value,services_property_svc_v1_types_pb.Date.deserializeBinaryFromReader); - msg.setDateValue(value); - break; - case 7: - var value = new google_protobuf_timestamp_pb.Timestamp; - reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); - msg.setDateTimeValue(value); - break; - case 8: - var value = /** @type {string} */ (reader.readString()); - msg.setSelectValue(value); - break; - case 9: - var value = new proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue; - reader.readMessage(value,proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.deserializeBinaryFromReader); - msg.setMultiSelectValue(value); - break; - case 10: - var value = /** @type {string} */ (reader.readString()); - msg.setConsistency(value); + msg.setDescription(value); break; default: reader.skipField(); @@ -415,9 +346,9 @@ proto.services.property_svc.v1.AttachPropertyValueRequest.deserializeBinaryFromR * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.serializeBinary = function() { +proto.services.property_svc.v1.SelectValueOption.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.services.property_svc.v1.AttachPropertyValueRequest.serializeBinaryToWriter(this, writer); + proto.services.property_svc.v1.SelectValueOption.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -425,113 +356,115 @@ proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.serializeBin /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest} message + * @param {!proto.services.property_svc.v1.SelectValueOption} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.AttachPropertyValueRequest.serializeBinaryToWriter = function(message, writer) { +proto.services.property_svc.v1.SelectValueOption.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getSubjectId(); + f = message.getId(); if (f.length > 0) { writer.writeString( 1, f ); } - f = message.getPropertyId(); + f = message.getName(); if (f.length > 0) { writer.writeString( 2, f ); } - f = /** @type {string} */ (jspb.Message.getField(message, 3)); - if (f != null) { + f = message.getDescription(); + if (f.length > 0) { writer.writeString( 3, f ); } - f = /** @type {number} */ (jspb.Message.getField(message, 4)); - if (f != null) { - writer.writeDouble( - 4, - f - ); - } - f = /** @type {boolean} */ (jspb.Message.getField(message, 5)); - if (f != null) { - writer.writeBool( - 5, - f - ); - } - f = message.getDateValue(); - if (f != null) { - writer.writeMessage( - 6, - f, - services_property_svc_v1_types_pb.Date.serializeBinaryToWriter - ); - } - f = message.getDateTimeValue(); - if (f != null) { - writer.writeMessage( - 7, - f, - google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter - ); - } - f = /** @type {string} */ (jspb.Message.getField(message, 8)); - if (f != null) { - writer.writeString( - 8, - f - ); - } - f = message.getMultiSelectValue(); - if (f != null) { - writer.writeMessage( - 9, - f, - proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.serializeBinaryToWriter - ); - } - f = /** @type {string} */ (jspb.Message.getField(message, 10)); - if (f != null) { - writer.writeString( - 10, - f - ); - } }; +/** + * optional string id = 1; + * @return {string} + */ +proto.services.property_svc.v1.SelectValueOption.prototype.getId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + /** - * List of repeated fields within this message type. - * @private {!Array} - * @const + * @param {string} value + * @return {!proto.services.property_svc.v1.SelectValueOption} returns this */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.repeatedFields_ = [1,2]; +proto.services.property_svc.v1.SelectValueOption.prototype.setId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; +/** + * optional string name = 2; + * @return {string} + */ +proto.services.property_svc.v1.SelectValueOption.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + -if (jspb.Message.GENERATE_TO_OBJECT) { /** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} + * @param {string} value + * @return {!proto.services.property_svc.v1.SelectValueOption} returns this */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.toObject = function(opt_includeInstance) { - return proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.toObject(opt_includeInstance, this); +proto.services.property_svc.v1.SelectValueOption.prototype.setName = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional string description = 3; + * @return {string} + */ +proto.services.property_svc.v1.SelectValueOption.prototype.getDescription = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.services.property_svc.v1.SelectValueOption} returns this + */ +proto.services.property_svc.v1.SelectValueOption.prototype.setDescription = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.services.property_svc.v1.MultiSelectValue.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.services.property_svc.v1.MultiSelectValue.prototype.toObject = function(opt_includeInstance) { + return proto.services.property_svc.v1.MultiSelectValue.toObject(opt_includeInstance, this); }; @@ -540,14 +473,14 @@ proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.proto * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} msg The msg instance to transform. + * @param {!proto.services.property_svc.v1.MultiSelectValue} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.toObject = function(includeInstance, msg) { +proto.services.property_svc.v1.MultiSelectValue.toObject = function(includeInstance, msg) { var f, obj = { - selectValuesList: (f = jspb.Message.getRepeatedField(msg, 1)) == null ? undefined : f, - removeSelectValuesList: (f = jspb.Message.getRepeatedField(msg, 2)) == null ? undefined : f + selectValuesList: jspb.Message.toObjectList(msg.getSelectValuesList(), + proto.services.property_svc.v1.SelectValueOption.toObject, includeInstance) }; if (includeInstance) { @@ -561,23 +494,23 @@ proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.toObj /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} + * @return {!proto.services.property_svc.v1.MultiSelectValue} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.deserializeBinary = function(bytes) { +proto.services.property_svc.v1.MultiSelectValue.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue; - return proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.deserializeBinaryFromReader(msg, reader); + var msg = new proto.services.property_svc.v1.MultiSelectValue; + return proto.services.property_svc.v1.MultiSelectValue.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} msg The message object to deserialize into. + * @param {!proto.services.property_svc.v1.MultiSelectValue} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} + * @return {!proto.services.property_svc.v1.MultiSelectValue} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.deserializeBinaryFromReader = function(msg, reader) { +proto.services.property_svc.v1.MultiSelectValue.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -585,13 +518,10 @@ proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.deser var field = reader.getFieldNumber(); switch (field) { case 1: - var value = /** @type {string} */ (reader.readString()); + var value = new proto.services.property_svc.v1.SelectValueOption; + reader.readMessage(value,proto.services.property_svc.v1.SelectValueOption.deserializeBinaryFromReader); msg.addSelectValues(value); break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.addRemoveSelectValues(value); - break; default: reader.skipField(); break; @@ -605,9 +535,9 @@ proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.deser * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.serializeBinary = function() { +proto.services.property_svc.v1.MultiSelectValue.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.serializeBinaryToWriter(this, writer); + proto.services.property_svc.v1.MultiSelectValue.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -615,530 +545,229 @@ proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.proto /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} message + * @param {!proto.services.property_svc.v1.MultiSelectValue} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.serializeBinaryToWriter = function(message, writer) { +proto.services.property_svc.v1.MultiSelectValue.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getSelectValuesList(); if (f.length > 0) { - writer.writeRepeatedString( + writer.writeRepeatedMessage( 1, - f - ); - } - f = message.getRemoveSelectValuesList(); - if (f.length > 0) { - writer.writeRepeatedString( - 2, - f + f, + proto.services.property_svc.v1.SelectValueOption.serializeBinaryToWriter ); } }; /** - * repeated string select_values = 1; - * @return {!Array} + * repeated SelectValueOption select_values = 1; + * @return {!Array} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.getSelectValuesList = function() { - return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 1)); +proto.services.property_svc.v1.MultiSelectValue.prototype.getSelectValuesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.services.property_svc.v1.SelectValueOption, 1)); }; /** - * @param {!Array} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.setSelectValuesList = function(value) { - return jspb.Message.setField(this, 1, value || []); + * @param {!Array} value + * @return {!proto.services.property_svc.v1.MultiSelectValue} returns this +*/ +proto.services.property_svc.v1.MultiSelectValue.prototype.setSelectValuesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); }; /** - * @param {string} value + * @param {!proto.services.property_svc.v1.SelectValueOption=} opt_value * @param {number=} opt_index - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + * @return {!proto.services.property_svc.v1.SelectValueOption} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.addSelectValues = function(value, opt_index) { - return jspb.Message.addToRepeatedField(this, 1, value, opt_index); +proto.services.property_svc.v1.MultiSelectValue.prototype.addSelectValues = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.services.property_svc.v1.SelectValueOption, opt_index); }; /** * Clears the list making it empty but non-null. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + * @return {!proto.services.property_svc.v1.MultiSelectValue} returns this */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.clearSelectValuesList = function() { +proto.services.property_svc.v1.MultiSelectValue.prototype.clearSelectValuesList = function() { return this.setSelectValuesList([]); }; + /** - * repeated string remove_select_values = 2; - * @return {!Array} + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.getRemoveSelectValuesList = function() { - return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 2)); -}; - +proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_ = [[3,4,5,6,7,8,9]]; /** - * @param {!Array} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + * @enum {number} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.setRemoveSelectValuesList = function(value) { - return jspb.Message.setField(this, 2, value || []); +proto.services.property_svc.v1.AttachPropertyValueRequest.ValueCase = { + VALUE_NOT_SET: 0, + TEXT_VALUE: 3, + NUMBER_VALUE: 4, + BOOL_VALUE: 5, + DATE_VALUE: 6, + DATE_TIME_VALUE: 7, + SELECT_VALUE: 8, + MULTI_SELECT_VALUE: 9 }; - /** - * @param {string} value - * @param {number=} opt_index - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + * @return {proto.services.property_svc.v1.AttachPropertyValueRequest.ValueCase} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.addRemoveSelectValues = function(value, opt_index) { - return jspb.Message.addToRepeatedField(this, 2, value, opt_index); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getValueCase = function() { + return /** @type {proto.services.property_svc.v1.AttachPropertyValueRequest.ValueCase} */(jspb.Message.computeOneofCase(this, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0])); }; + +if (jspb.Message.GENERATE_TO_OBJECT) { /** - * Clears the list making it empty but non-null. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.clearRemoveSelectValuesList = function() { - return this.setRemoveSelectValuesList([]); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.toObject = function(opt_includeInstance) { + return proto.services.property_svc.v1.AttachPropertyValueRequest.toObject(opt_includeInstance, this); }; /** - * optional string subject_id = 1; - * @return {string} + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getSubjectId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +proto.services.property_svc.v1.AttachPropertyValueRequest.toObject = function(includeInstance, msg) { + var f, obj = { + subjectId: jspb.Message.getFieldWithDefault(msg, 1, ""), + propertyId: jspb.Message.getFieldWithDefault(msg, 2, ""), + textValue: jspb.Message.getFieldWithDefault(msg, 3, ""), + numberValue: jspb.Message.getFloatingPointFieldWithDefault(msg, 4, 0.0), + boolValue: jspb.Message.getBooleanFieldWithDefault(msg, 5, false), + dateValue: (f = msg.getDateValue()) && services_property_svc_v1_types_pb.Date.toObject(includeInstance, f), + dateTimeValue: (f = msg.getDateTimeValue()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f), + selectValue: jspb.Message.getFieldWithDefault(msg, 8, ""), + multiSelectValue: (f = msg.getMultiSelectValue()) && proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.toObject(includeInstance, f), + consistency: jspb.Message.getFieldWithDefault(msg, 10, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; }; +} /** - * @param {string} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setSubjectId = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); +proto.services.property_svc.v1.AttachPropertyValueRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.services.property_svc.v1.AttachPropertyValueRequest; + return proto.services.property_svc.v1.AttachPropertyValueRequest.deserializeBinaryFromReader(msg, reader); }; /** - * optional string property_id = 2; - * @return {string} + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getPropertyId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +proto.services.property_svc.v1.AttachPropertyValueRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setSubjectId(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setPropertyId(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setTextValue(value); + break; + case 4: + var value = /** @type {number} */ (reader.readDouble()); + msg.setNumberValue(value); + break; + case 5: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setBoolValue(value); + break; + case 6: + var value = new services_property_svc_v1_types_pb.Date; + reader.readMessage(value,services_property_svc_v1_types_pb.Date.deserializeBinaryFromReader); + msg.setDateValue(value); + break; + case 7: + var value = new google_protobuf_timestamp_pb.Timestamp; + reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); + msg.setDateTimeValue(value); + break; + case 8: + var value = /** @type {string} */ (reader.readString()); + msg.setSelectValue(value); + break; + case 9: + var value = new proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue; + reader.readMessage(value,proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.deserializeBinaryFromReader); + msg.setMultiSelectValue(value); + break; + case 10: + var value = /** @type {string} */ (reader.readString()); + msg.setConsistency(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; }; /** - * @param {string} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setPropertyId = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - -/** - * optional string text_value = 3; - * @return {string} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getTextValue = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setTextValue = function(value) { - return jspb.Message.setOneofField(this, 3, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearTextValue = function() { - return jspb.Message.setOneofField(this, 3, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasTextValue = function() { - return jspb.Message.getField(this, 3) != null; -}; - - -/** - * optional double number_value = 4; - * @return {number} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getNumberValue = function() { - return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 4, 0.0)); -}; - - -/** - * @param {number} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setNumberValue = function(value) { - return jspb.Message.setOneofField(this, 4, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearNumberValue = function() { - return jspb.Message.setOneofField(this, 4, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasNumberValue = function() { - return jspb.Message.getField(this, 4) != null; -}; - - -/** - * optional bool bool_value = 5; - * @return {boolean} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getBoolValue = function() { - return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false)); -}; - - -/** - * @param {boolean} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setBoolValue = function(value) { - return jspb.Message.setOneofField(this, 5, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearBoolValue = function() { - return jspb.Message.setOneofField(this, 5, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasBoolValue = function() { - return jspb.Message.getField(this, 5) != null; -}; - - -/** - * optional Date date_value = 6; - * @return {?proto.services.property_svc.v1.Date} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getDateValue = function() { - return /** @type{?proto.services.property_svc.v1.Date} */ ( - jspb.Message.getWrapperField(this, services_property_svc_v1_types_pb.Date, 6)); -}; - - -/** - * @param {?proto.services.property_svc.v1.Date|undefined} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this -*/ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setDateValue = function(value) { - return jspb.Message.setOneofWrapperField(this, 6, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearDateValue = function() { - return this.setDateValue(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasDateValue = function() { - return jspb.Message.getField(this, 6) != null; -}; - - -/** - * optional google.protobuf.Timestamp date_time_value = 7; - * @return {?proto.google.protobuf.Timestamp} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getDateTimeValue = function() { - return /** @type{?proto.google.protobuf.Timestamp} */ ( - jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 7)); -}; - - -/** - * @param {?proto.google.protobuf.Timestamp|undefined} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this -*/ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setDateTimeValue = function(value) { - return jspb.Message.setOneofWrapperField(this, 7, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearDateTimeValue = function() { - return this.setDateTimeValue(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasDateTimeValue = function() { - return jspb.Message.getField(this, 7) != null; -}; - - -/** - * optional string select_value = 8; - * @return {string} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getSelectValue = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 8, "")); -}; - - -/** - * @param {string} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setSelectValue = function(value) { - return jspb.Message.setOneofField(this, 8, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearSelectValue = function() { - return jspb.Message.setOneofField(this, 8, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasSelectValue = function() { - return jspb.Message.getField(this, 8) != null; -}; - - -/** - * optional MultiSelectValue multi_select_value = 9; - * @return {?proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getMultiSelectValue = function() { - return /** @type{?proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} */ ( - jspb.Message.getWrapperField(this, proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue, 9)); -}; - - -/** - * @param {?proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue|undefined} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this -*/ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setMultiSelectValue = function(value) { - return jspb.Message.setOneofWrapperField(this, 9, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearMultiSelectValue = function() { - return this.setMultiSelectValue(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasMultiSelectValue = function() { - return jspb.Message.getField(this, 9) != null; -}; - - -/** - * optional string consistency = 10; - * @return {string} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getConsistency = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 10, "")); -}; - - -/** - * @param {string} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setConsistency = function(value) { - return jspb.Message.setField(this, 10, value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearConsistency = function() { - return jspb.Message.setField(this, 10, undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasConsistency = function() { - return jspb.Message.getField(this, 10) != null; -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.toObject = function(opt_includeInstance) { - return proto.services.property_svc.v1.AttachPropertyValueResponse.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.services.property_svc.v1.AttachPropertyValueResponse} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.toObject = function(includeInstance, msg) { - var f, obj = { - propertyValueId: jspb.Message.getFieldWithDefault(msg, 1, ""), - conflict: (f = msg.getConflict()) && libs_common_v1_conflict_pb.Conflict.toObject(includeInstance, f), - consistency: jspb.Message.getFieldWithDefault(msg, 3, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.services.property_svc.v1.AttachPropertyValueResponse; - return proto.services.property_svc.v1.AttachPropertyValueResponse.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.services.property_svc.v1.AttachPropertyValueResponse} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setPropertyValueId(value); - break; - case 2: - var value = new libs_common_v1_conflict_pb.Conflict; - reader.readMessage(value,libs_common_v1_conflict_pb.Conflict.deserializeBinaryFromReader); - msg.setConflict(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setConsistency(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.serializeBinary = function() { +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.services.property_svc.v1.AttachPropertyValueResponse.serializeBinaryToWriter(this, writer); + proto.services.property_svc.v1.AttachPropertyValueRequest.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -1146,110 +775,95 @@ proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.serializeBi /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.services.property_svc.v1.AttachPropertyValueResponse} message + * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.AttachPropertyValueResponse.serializeBinaryToWriter = function(message, writer) { +proto.services.property_svc.v1.AttachPropertyValueRequest.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getPropertyValueId(); + f = message.getSubjectId(); if (f.length > 0) { writer.writeString( 1, f ); } - f = message.getConflict(); + f = message.getPropertyId(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 3)); + if (f != null) { + writer.writeString( + 3, + f + ); + } + f = /** @type {number} */ (jspb.Message.getField(message, 4)); + if (f != null) { + writer.writeDouble( + 4, + f + ); + } + f = /** @type {boolean} */ (jspb.Message.getField(message, 5)); + if (f != null) { + writer.writeBool( + 5, + f + ); + } + f = message.getDateValue(); if (f != null) { writer.writeMessage( - 2, + 6, f, - libs_common_v1_conflict_pb.Conflict.serializeBinaryToWriter + services_property_svc_v1_types_pb.Date.serializeBinaryToWriter ); } - f = message.getConsistency(); - if (f.length > 0) { + f = message.getDateTimeValue(); + if (f != null) { + writer.writeMessage( + 7, + f, + google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 8)); + if (f != null) { writer.writeString( - 3, + 8, + f + ); + } + f = message.getMultiSelectValue(); + if (f != null) { + writer.writeMessage( + 9, + f, + proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.serializeBinaryToWriter + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 10)); + if (f != null) { + writer.writeString( + 10, f ); } }; -/** - * optional string property_value_id = 1; - * @return {string} - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.getPropertyValueId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.setPropertyValueId = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - -/** - * optional libs.common.v1.Conflict conflict = 2; - * @return {?proto.libs.common.v1.Conflict} - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.getConflict = function() { - return /** @type{?proto.libs.common.v1.Conflict} */ ( - jspb.Message.getWrapperField(this, libs_common_v1_conflict_pb.Conflict, 2)); -}; - - -/** - * @param {?proto.libs.common.v1.Conflict|undefined} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} returns this -*/ -proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.setConflict = function(value) { - return jspb.Message.setWrapperField(this, 2, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.clearConflict = function() { - return this.setConflict(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.hasConflict = function() { - return jspb.Message.getField(this, 2) != null; -}; - - -/** - * optional string consistency = 3; - * @return {string} - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.getConsistency = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - /** - * @param {string} value - * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} returns this - */ -proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.setConsistency = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.repeatedFields_ = [1,2]; @@ -1266,8 +880,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.services.property_svc.v1.TaskPropertyMatcher.prototype.toObject = function(opt_includeInstance) { - return proto.services.property_svc.v1.TaskPropertyMatcher.toObject(opt_includeInstance, this); +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.toObject = function(opt_includeInstance) { + return proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.toObject(opt_includeInstance, this); }; @@ -1276,14 +890,14 @@ proto.services.property_svc.v1.TaskPropertyMatcher.prototype.toObject = function * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.services.property_svc.v1.TaskPropertyMatcher} msg The msg instance to transform. + * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.TaskPropertyMatcher.toObject = function(includeInstance, msg) { +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.toObject = function(includeInstance, msg) { var f, obj = { - wardId: jspb.Message.getFieldWithDefault(msg, 1, ""), - taskId: jspb.Message.getFieldWithDefault(msg, 2, "") + selectValuesList: (f = jspb.Message.getRepeatedField(msg, 1)) == null ? undefined : f, + removeSelectValuesList: (f = jspb.Message.getRepeatedField(msg, 2)) == null ? undefined : f }; if (includeInstance) { @@ -1297,23 +911,23 @@ proto.services.property_svc.v1.TaskPropertyMatcher.toObject = function(includeIn /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} */ -proto.services.property_svc.v1.TaskPropertyMatcher.deserializeBinary = function(bytes) { +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.services.property_svc.v1.TaskPropertyMatcher; - return proto.services.property_svc.v1.TaskPropertyMatcher.deserializeBinaryFromReader(msg, reader); + var msg = new proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue; + return proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.services.property_svc.v1.TaskPropertyMatcher} msg The message object to deserialize into. + * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} */ -proto.services.property_svc.v1.TaskPropertyMatcher.deserializeBinaryFromReader = function(msg, reader) { +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -1322,11 +936,11 @@ proto.services.property_svc.v1.TaskPropertyMatcher.deserializeBinaryFromReader = switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); - msg.setWardId(value); + msg.addSelectValues(value); break; case 2: var value = /** @type {string} */ (reader.readString()); - msg.setTaskId(value); + msg.addRemoveSelectValues(value); break; default: reader.skipField(); @@ -1341,9 +955,9 @@ proto.services.property_svc.v1.TaskPropertyMatcher.deserializeBinaryFromReader = * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.services.property_svc.v1.TaskPropertyMatcher.prototype.serializeBinary = function() { +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.services.property_svc.v1.TaskPropertyMatcher.serializeBinaryToWriter(this, writer); + proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -1351,22 +965,22 @@ proto.services.property_svc.v1.TaskPropertyMatcher.prototype.serializeBinary = f /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.services.property_svc.v1.TaskPropertyMatcher} message + * @param {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.TaskPropertyMatcher.serializeBinaryToWriter = function(message, writer) { +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = /** @type {string} */ (jspb.Message.getField(message, 1)); - if (f != null) { - writer.writeString( + f = message.getSelectValuesList(); + if (f.length > 0) { + writer.writeRepeatedString( 1, f ); } - f = /** @type {string} */ (jspb.Message.getField(message, 2)); - if (f != null) { - writer.writeString( + f = message.getRemoveSelectValuesList(); + if (f.length > 0) { + writer.writeRepeatedString( 2, f ); @@ -1375,29 +989,139 @@ proto.services.property_svc.v1.TaskPropertyMatcher.serializeBinaryToWriter = fun /** - * optional string ward_id = 1; + * repeated string select_values = 1; + * @return {!Array} + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.getSelectValuesList = function() { + return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.setSelectValuesList = function(value) { + return jspb.Message.setField(this, 1, value || []); +}; + + +/** + * @param {string} value + * @param {number=} opt_index + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.addSelectValues = function(value, opt_index) { + return jspb.Message.addToRepeatedField(this, 1, value, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.clearSelectValuesList = function() { + return this.setSelectValuesList([]); +}; + + +/** + * repeated string remove_select_values = 2; + * @return {!Array} + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.getRemoveSelectValuesList = function() { + return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 2)); +}; + + +/** + * @param {!Array} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.setRemoveSelectValuesList = function(value) { + return jspb.Message.setField(this, 2, value || []); +}; + + +/** + * @param {string} value + * @param {number=} opt_index + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.addRemoveSelectValues = function(value, opt_index) { + return jspb.Message.addToRepeatedField(this, 2, value, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} returns this + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue.prototype.clearRemoveSelectValuesList = function() { + return this.setRemoveSelectValuesList([]); +}; + + +/** + * optional string subject_id = 1; * @return {string} */ -proto.services.property_svc.v1.TaskPropertyMatcher.prototype.getWardId = function() { +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getSubjectId = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** * @param {string} value - * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} returns this + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.TaskPropertyMatcher.prototype.setWardId = function(value) { - return jspb.Message.setField(this, 1, value); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setSubjectId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string property_id = 2; + * @return {string} + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getPropertyId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setPropertyId = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional string text_value = 3; + * @return {string} + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getTextValue = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setTextValue = function(value) { + return jspb.Message.setOneofField(this, 3, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); }; /** * Clears the field making it undefined. - * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} returns this + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.TaskPropertyMatcher.prototype.clearWardId = function() { - return jspb.Message.setField(this, 1, undefined); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearTextValue = function() { + return jspb.Message.setOneofField(this, 3, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], undefined); }; @@ -1405,35 +1129,35 @@ proto.services.property_svc.v1.TaskPropertyMatcher.prototype.clearWardId = funct * Returns whether this field is set. * @return {boolean} */ -proto.services.property_svc.v1.TaskPropertyMatcher.prototype.hasWardId = function() { - return jspb.Message.getField(this, 1) != null; +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasTextValue = function() { + return jspb.Message.getField(this, 3) != null; }; /** - * optional string task_id = 2; - * @return {string} + * optional double number_value = 4; + * @return {number} */ -proto.services.property_svc.v1.TaskPropertyMatcher.prototype.getTaskId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getNumberValue = function() { + return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 4, 0.0)); }; /** - * @param {string} value - * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} returns this + * @param {number} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.TaskPropertyMatcher.prototype.setTaskId = function(value) { - return jspb.Message.setField(this, 2, value); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setNumberValue = function(value) { + return jspb.Message.setOneofField(this, 4, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); }; /** * Clears the field making it undefined. - * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} returns this + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.TaskPropertyMatcher.prototype.clearTaskId = function() { - return jspb.Message.setField(this, 2, undefined); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearNumberValue = function() { + return jspb.Message.setOneofField(this, 4, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], undefined); }; @@ -1441,159 +1165,145 @@ proto.services.property_svc.v1.TaskPropertyMatcher.prototype.clearTaskId = funct * Returns whether this field is set. * @return {boolean} */ -proto.services.property_svc.v1.TaskPropertyMatcher.prototype.hasTaskId = function() { - return jspb.Message.getField(this, 2) != null; +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasNumberValue = function() { + return jspb.Message.getField(this, 4) != null; +}; + + +/** + * optional bool bool_value = 5; + * @return {boolean} + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getBoolValue = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setBoolValue = function(value) { + return jspb.Message.setOneofField(this, 5, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearBoolValue = function() { + return jspb.Message.setOneofField(this, 5, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasBoolValue = function() { + return jspb.Message.getField(this, 5) != null; +}; + + +/** + * optional Date date_value = 6; + * @return {?proto.services.property_svc.v1.Date} + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getDateValue = function() { + return /** @type{?proto.services.property_svc.v1.Date} */ ( + jspb.Message.getWrapperField(this, services_property_svc_v1_types_pb.Date, 6)); }; +/** + * @param {?proto.services.property_svc.v1.Date|undefined} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this +*/ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setDateValue = function(value) { + return jspb.Message.setOneofWrapperField(this, 6, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); +}; - -if (jspb.Message.GENERATE_TO_OBJECT) { /** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} + * Clears the message field making it undefined. + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.PatientPropertyMatcher.prototype.toObject = function(opt_includeInstance) { - return proto.services.property_svc.v1.PatientPropertyMatcher.toObject(opt_includeInstance, this); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearDateValue = function() { + return this.setDateValue(undefined); }; /** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.services.property_svc.v1.PatientPropertyMatcher} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages + * Returns whether this field is set. + * @return {boolean} */ -proto.services.property_svc.v1.PatientPropertyMatcher.toObject = function(includeInstance, msg) { - var f, obj = { - wardId: jspb.Message.getFieldWithDefault(msg, 1, ""), - patientId: jspb.Message.getFieldWithDefault(msg, 2, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasDateValue = function() { + return jspb.Message.getField(this, 6) != null; }; -} /** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} + * optional google.protobuf.Timestamp date_time_value = 7; + * @return {?proto.google.protobuf.Timestamp} */ -proto.services.property_svc.v1.PatientPropertyMatcher.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.services.property_svc.v1.PatientPropertyMatcher; - return proto.services.property_svc.v1.PatientPropertyMatcher.deserializeBinaryFromReader(msg, reader); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getDateTimeValue = function() { + return /** @type{?proto.google.protobuf.Timestamp} */ ( + jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 7)); }; /** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.services.property_svc.v1.PatientPropertyMatcher} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} - */ -proto.services.property_svc.v1.PatientPropertyMatcher.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setWardId(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setPatientId(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; + * @param {?proto.google.protobuf.Timestamp|undefined} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this +*/ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setDateTimeValue = function(value) { + return jspb.Message.setOneofWrapperField(this, 7, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); }; /** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} + * Clears the message field making it undefined. + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.PatientPropertyMatcher.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.services.property_svc.v1.PatientPropertyMatcher.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearDateTimeValue = function() { + return this.setDateTimeValue(undefined); }; /** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.services.property_svc.v1.PatientPropertyMatcher} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages + * Returns whether this field is set. + * @return {boolean} */ -proto.services.property_svc.v1.PatientPropertyMatcher.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = /** @type {string} */ (jspb.Message.getField(message, 1)); - if (f != null) { - writer.writeString( - 1, - f - ); - } - f = /** @type {string} */ (jspb.Message.getField(message, 2)); - if (f != null) { - writer.writeString( - 2, - f - ); - } +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasDateTimeValue = function() { + return jspb.Message.getField(this, 7) != null; }; /** - * optional string ward_id = 1; + * optional string select_value = 8; * @return {string} */ -proto.services.property_svc.v1.PatientPropertyMatcher.prototype.getWardId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getSelectValue = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 8, "")); }; /** * @param {string} value - * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} returns this + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.PatientPropertyMatcher.prototype.setWardId = function(value) { - return jspb.Message.setField(this, 1, value); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setSelectValue = function(value) { + return jspb.Message.setOneofField(this, 8, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); }; /** * Clears the field making it undefined. - * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} returns this + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.PatientPropertyMatcher.prototype.clearWardId = function() { - return jspb.Message.setField(this, 1, undefined); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearSelectValue = function() { + return jspb.Message.setOneofField(this, 8, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], undefined); }; @@ -1601,35 +1311,36 @@ proto.services.property_svc.v1.PatientPropertyMatcher.prototype.clearWardId = fu * Returns whether this field is set. * @return {boolean} */ -proto.services.property_svc.v1.PatientPropertyMatcher.prototype.hasWardId = function() { - return jspb.Message.getField(this, 1) != null; +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasSelectValue = function() { + return jspb.Message.getField(this, 8) != null; }; /** - * optional string patient_id = 2; - * @return {string} + * optional MultiSelectValue multi_select_value = 9; + * @return {?proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} */ -proto.services.property_svc.v1.PatientPropertyMatcher.prototype.getPatientId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getMultiSelectValue = function() { + return /** @type{?proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue} */ ( + jspb.Message.getWrapperField(this, proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue, 9)); }; /** - * @param {string} value - * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} returns this - */ -proto.services.property_svc.v1.PatientPropertyMatcher.prototype.setPatientId = function(value) { - return jspb.Message.setField(this, 2, value); + * @param {?proto.services.property_svc.v1.AttachPropertyValueRequest.MultiSelectValue|undefined} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this +*/ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setMultiSelectValue = function(value) { + return jspb.Message.setOneofWrapperField(this, 9, proto.services.property_svc.v1.AttachPropertyValueRequest.oneofGroups_[0], value); }; /** - * Clears the field making it undefined. - * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} returns this + * Clears the message field making it undefined. + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.PatientPropertyMatcher.prototype.clearPatientId = function() { - return jspb.Message.setField(this, 2, undefined); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearMultiSelectValue = function() { + return this.setMultiSelectValue(undefined); }; @@ -1637,40 +1348,50 @@ proto.services.property_svc.v1.PatientPropertyMatcher.prototype.clearPatientId = * Returns whether this field is set. * @return {boolean} */ -proto.services.property_svc.v1.PatientPropertyMatcher.prototype.hasPatientId = function() { - return jspb.Message.getField(this, 2) != null; +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasMultiSelectValue = function() { + return jspb.Message.getField(this, 9) != null; }; +/** + * optional string consistency = 10; + * @return {string} + */ +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.getConsistency = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 10, "")); +}; + /** - * Oneof group definitions for this message. Each group defines the field - * numbers belonging to that group. When of these fields' value is set, all - * other fields in the group are cleared. During deserialization, if multiple - * fields are encountered for a group, only the last value seen will be kept. - * @private {!Array>} - * @const + * @param {string} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.oneofGroups_ = [[1,2]]; +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.setConsistency = function(value) { + return jspb.Message.setField(this, 10, value); +}; + /** - * @enum {number} + * Clears the field making it undefined. + * @return {!proto.services.property_svc.v1.AttachPropertyValueRequest} returns this */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.MatcherCase = { - MATCHER_NOT_SET: 0, - TASK_MATCHER: 1, - PATIENT_MATCHER: 2 +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.clearConsistency = function() { + return jspb.Message.setField(this, 10, undefined); }; + /** - * @return {proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.MatcherCase} + * Returns whether this field is set. + * @return {boolean} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.getMatcherCase = function() { - return /** @type {proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.MatcherCase} */(jspb.Message.computeOneofCase(this, proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.oneofGroups_[0])); +proto.services.property_svc.v1.AttachPropertyValueRequest.prototype.hasConsistency = function() { + return jspb.Message.getField(this, 10) != null; }; + + if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto. @@ -1684,8 +1405,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.toObject = function(opt_includeInstance) { - return proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.toObject(opt_includeInstance, this); +proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.toObject = function(opt_includeInstance) { + return proto.services.property_svc.v1.AttachPropertyValueResponse.toObject(opt_includeInstance, this); }; @@ -1694,14 +1415,15 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.toObje * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} msg The msg instance to transform. + * @param {!proto.services.property_svc.v1.AttachPropertyValueResponse} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.toObject = function(includeInstance, msg) { +proto.services.property_svc.v1.AttachPropertyValueResponse.toObject = function(includeInstance, msg) { var f, obj = { - taskMatcher: (f = msg.getTaskMatcher()) && proto.services.property_svc.v1.TaskPropertyMatcher.toObject(includeInstance, f), - patientMatcher: (f = msg.getPatientMatcher()) && proto.services.property_svc.v1.PatientPropertyMatcher.toObject(includeInstance, f) + propertyValueId: jspb.Message.getFieldWithDefault(msg, 1, ""), + conflict: (f = msg.getConflict()) && libs_common_v1_conflict_pb.Conflict.toObject(includeInstance, f), + consistency: jspb.Message.getFieldWithDefault(msg, 3, "") }; if (includeInstance) { @@ -1715,23 +1437,23 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.toObject = funct /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} + * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.deserializeBinary = function(bytes) { +proto.services.property_svc.v1.AttachPropertyValueResponse.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.services.property_svc.v1.GetAttachedPropertyValuesRequest; - return proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.deserializeBinaryFromReader(msg, reader); + var msg = new proto.services.property_svc.v1.AttachPropertyValueResponse; + return proto.services.property_svc.v1.AttachPropertyValueResponse.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} msg The message object to deserialize into. + * @param {!proto.services.property_svc.v1.AttachPropertyValueResponse} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} + * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.deserializeBinaryFromReader = function(msg, reader) { +proto.services.property_svc.v1.AttachPropertyValueResponse.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -1739,14 +1461,17 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.deserializeBinar var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.services.property_svc.v1.TaskPropertyMatcher; - reader.readMessage(value,proto.services.property_svc.v1.TaskPropertyMatcher.deserializeBinaryFromReader); - msg.setTaskMatcher(value); + var value = /** @type {string} */ (reader.readString()); + msg.setPropertyValueId(value); break; case 2: - var value = new proto.services.property_svc.v1.PatientPropertyMatcher; - reader.readMessage(value,proto.services.property_svc.v1.PatientPropertyMatcher.deserializeBinaryFromReader); - msg.setPatientMatcher(value); + var value = new libs_common_v1_conflict_pb.Conflict; + reader.readMessage(value,libs_common_v1_conflict_pb.Conflict.deserializeBinaryFromReader); + msg.setConflict(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setConsistency(value); break; default: reader.skipField(); @@ -1761,9 +1486,9 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.deserializeBinar * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.serializeBinary = function() { +proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.serializeBinaryToWriter(this, writer); + proto.services.property_svc.v1.AttachPropertyValueResponse.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -1771,93 +1496,80 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.serial /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} message + * @param {!proto.services.property_svc.v1.AttachPropertyValueResponse} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.serializeBinaryToWriter = function(message, writer) { +proto.services.property_svc.v1.AttachPropertyValueResponse.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getTaskMatcher(); - if (f != null) { - writer.writeMessage( + f = message.getPropertyValueId(); + if (f.length > 0) { + writer.writeString( 1, - f, - proto.services.property_svc.v1.TaskPropertyMatcher.serializeBinaryToWriter + f ); } - f = message.getPatientMatcher(); + f = message.getConflict(); if (f != null) { writer.writeMessage( 2, f, - proto.services.property_svc.v1.PatientPropertyMatcher.serializeBinaryToWriter + libs_common_v1_conflict_pb.Conflict.serializeBinaryToWriter + ); + } + f = message.getConsistency(); + if (f.length > 0) { + writer.writeString( + 3, + f ); } }; /** - * optional TaskPropertyMatcher task_matcher = 1; - * @return {?proto.services.property_svc.v1.TaskPropertyMatcher} - */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.getTaskMatcher = function() { - return /** @type{?proto.services.property_svc.v1.TaskPropertyMatcher} */ ( - jspb.Message.getWrapperField(this, proto.services.property_svc.v1.TaskPropertyMatcher, 1)); -}; - - -/** - * @param {?proto.services.property_svc.v1.TaskPropertyMatcher|undefined} value - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} returns this -*/ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.setTaskMatcher = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} returns this + * optional string property_value_id = 1; + * @return {string} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.clearTaskMatcher = function() { - return this.setTaskMatcher(undefined); +proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.getPropertyValueId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** - * Returns whether this field is set. - * @return {boolean} + * @param {string} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} returns this */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.hasTaskMatcher = function() { - return jspb.Message.getField(this, 1) != null; +proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.setPropertyValueId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); }; /** - * optional PatientPropertyMatcher patient_matcher = 2; - * @return {?proto.services.property_svc.v1.PatientPropertyMatcher} + * optional libs.common.v1.Conflict conflict = 2; + * @return {?proto.libs.common.v1.Conflict} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.getPatientMatcher = function() { - return /** @type{?proto.services.property_svc.v1.PatientPropertyMatcher} */ ( - jspb.Message.getWrapperField(this, proto.services.property_svc.v1.PatientPropertyMatcher, 2)); +proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.getConflict = function() { + return /** @type{?proto.libs.common.v1.Conflict} */ ( + jspb.Message.getWrapperField(this, libs_common_v1_conflict_pb.Conflict, 2)); }; /** - * @param {?proto.services.property_svc.v1.PatientPropertyMatcher|undefined} value - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} returns this + * @param {?proto.libs.common.v1.Conflict|undefined} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} returns this */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.setPatientMatcher = function(value) { - return jspb.Message.setOneofWrapperField(this, 2, proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.oneofGroups_[0], value); +proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.setConflict = function(value) { + return jspb.Message.setWrapperField(this, 2, value); }; /** * Clears the message field making it undefined. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} returns this + * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} returns this */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.clearPatientMatcher = function() { - return this.setPatientMatcher(undefined); +proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.clearConflict = function() { + return this.setConflict(undefined); }; @@ -1865,18 +1577,29 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.clearP * Returns whether this field is set. * @return {boolean} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.hasPatientMatcher = function() { +proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.hasConflict = function() { return jspb.Message.getField(this, 2) != null; }; +/** + * optional string consistency = 3; + * @return {string} + */ +proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.getConsistency = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + /** - * List of repeated fields within this message type. - * @private {!Array} - * @const + * @param {string} value + * @return {!proto.services.property_svc.v1.AttachPropertyValueResponse} returns this */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.repeatedFields_ = [1]; +proto.services.property_svc.v1.AttachPropertyValueResponse.prototype.setConsistency = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + @@ -1893,8 +1616,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.prototype.toObject = function(opt_includeInstance) { - return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.toObject(opt_includeInstance, this); +proto.services.property_svc.v1.TaskPropertyMatcher.prototype.toObject = function(opt_includeInstance) { + return proto.services.property_svc.v1.TaskPropertyMatcher.toObject(opt_includeInstance, this); }; @@ -1903,14 +1626,14 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.prototype.toObj * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse} msg The msg instance to transform. + * @param {!proto.services.property_svc.v1.TaskPropertyMatcher} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.toObject = function(includeInstance, msg) { +proto.services.property_svc.v1.TaskPropertyMatcher.toObject = function(includeInstance, msg) { var f, obj = { - valuesList: jspb.Message.toObjectList(msg.getValuesList(), - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.toObject, includeInstance) + wardId: jspb.Message.getFieldWithDefault(msg, 1, ""), + taskId: jspb.Message.getFieldWithDefault(msg, 2, "") }; if (includeInstance) { @@ -1924,23 +1647,23 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.toObject = func /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse} + * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.deserializeBinary = function(bytes) { +proto.services.property_svc.v1.TaskPropertyMatcher.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse; - return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.deserializeBinaryFromReader(msg, reader); + var msg = new proto.services.property_svc.v1.TaskPropertyMatcher; + return proto.services.property_svc.v1.TaskPropertyMatcher.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse} msg The message object to deserialize into. + * @param {!proto.services.property_svc.v1.TaskPropertyMatcher} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse} + * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.deserializeBinaryFromReader = function(msg, reader) { +proto.services.property_svc.v1.TaskPropertyMatcher.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -1948,9 +1671,12 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.deserializeBina var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value; - reader.readMessage(value,proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.deserializeBinaryFromReader); - msg.addValues(value); + var value = /** @type {string} */ (reader.readString()); + msg.setWardId(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setTaskId(value); break; default: reader.skipField(); @@ -1965,9 +1691,9 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.deserializeBina * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.prototype.serializeBinary = function() { +proto.services.property_svc.v1.TaskPropertyMatcher.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.serializeBinaryToWriter(this, writer); + proto.services.property_svc.v1.TaskPropertyMatcher.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -1975,57 +1701,104 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.prototype.seria /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse} message + * @param {!proto.services.property_svc.v1.TaskPropertyMatcher} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.serializeBinaryToWriter = function(message, writer) { +proto.services.property_svc.v1.TaskPropertyMatcher.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getValuesList(); - if (f.length > 0) { - writer.writeRepeatedMessage( + f = /** @type {string} */ (jspb.Message.getField(message, 1)); + if (f != null) { + writer.writeString( 1, - f, - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.serializeBinaryToWriter + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 2)); + if (f != null) { + writer.writeString( + 2, + f ); } }; +/** + * optional string ward_id = 1; + * @return {string} + */ +proto.services.property_svc.v1.TaskPropertyMatcher.prototype.getWardId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + /** - * Oneof group definitions for this message. Each group defines the field - * numbers belonging to that group. When of these fields' value is set, all - * other fields in the group are cleared. During deserialization, if multiple - * fields are encountered for a group, only the last value seen will be kept. - * @private {!Array>} - * @const + * @param {string} value + * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} returns this */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.oneofGroups_ = [[6,7,8,9,10,11,12]]; +proto.services.property_svc.v1.TaskPropertyMatcher.prototype.setWardId = function(value) { + return jspb.Message.setField(this, 1, value); +}; + /** - * @enum {number} + * Clears the field making it undefined. + * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} returns this */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.ValueCase = { - VALUE_NOT_SET: 0, - TEXT_VALUE: 6, - NUMBER_VALUE: 7, - BOOL_VALUE: 8, - DATE_VALUE: 9, - DATE_TIME_VALUE: 10, - SELECT_VALUE: 11, - MULTI_SELECT_VALUE: 12 +proto.services.property_svc.v1.TaskPropertyMatcher.prototype.clearWardId = function() { + return jspb.Message.setField(this, 1, undefined); }; + /** - * @return {proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.ValueCase} + * Returns whether this field is set. + * @return {boolean} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype.getValueCase = function() { - return /** @type {proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.ValueCase} */(jspb.Message.computeOneofCase(this, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.oneofGroups_[0])); +proto.services.property_svc.v1.TaskPropertyMatcher.prototype.hasWardId = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional string task_id = 2; + * @return {string} + */ +proto.services.property_svc.v1.TaskPropertyMatcher.prototype.getTaskId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} returns this + */ +proto.services.property_svc.v1.TaskPropertyMatcher.prototype.setTaskId = function(value) { + return jspb.Message.setField(this, 2, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.services.property_svc.v1.TaskPropertyMatcher} returns this + */ +proto.services.property_svc.v1.TaskPropertyMatcher.prototype.clearTaskId = function() { + return jspb.Message.setField(this, 2, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.services.property_svc.v1.TaskPropertyMatcher.prototype.hasTaskId = function() { + return jspb.Message.getField(this, 2) != null; }; + + if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto. @@ -2039,8 +1812,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype.toObject = function(opt_includeInstance) { - return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.toObject(opt_includeInstance, this); +proto.services.property_svc.v1.PatientPropertyMatcher.prototype.toObject = function(opt_includeInstance) { + return proto.services.property_svc.v1.PatientPropertyMatcher.toObject(opt_includeInstance, this); }; @@ -2049,26 +1822,14 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} msg The msg instance to transform. + * @param {!proto.services.property_svc.v1.PatientPropertyMatcher} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.toObject = function(includeInstance, msg) { +proto.services.property_svc.v1.PatientPropertyMatcher.toObject = function(includeInstance, msg) { var f, obj = { - propertyId: jspb.Message.getFieldWithDefault(msg, 1, ""), - fieldType: jspb.Message.getFieldWithDefault(msg, 2, 0), - name: jspb.Message.getFieldWithDefault(msg, 3, ""), - description: jspb.Message.getFieldWithDefault(msg, 4, ""), - isArchived: jspb.Message.getBooleanFieldWithDefault(msg, 5, false), - textValue: jspb.Message.getFieldWithDefault(msg, 6, ""), - numberValue: jspb.Message.getFloatingPointFieldWithDefault(msg, 7, 0.0), - boolValue: jspb.Message.getBooleanFieldWithDefault(msg, 8, false), - dateValue: (f = msg.getDateValue()) && services_property_svc_v1_types_pb.Date.toObject(includeInstance, f), - dateTimeValue: (f = msg.getDateTimeValue()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f), - selectValue: (f = msg.getSelectValue()) && proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.toObject(includeInstance, f), - multiSelectValue: (f = msg.getMultiSelectValue()) && proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.toObject(includeInstance, f), - propertyConsistency: jspb.Message.getFieldWithDefault(msg, 13, ""), - valueConsistency: jspb.Message.getFieldWithDefault(msg, 14, "") + wardId: jspb.Message.getFieldWithDefault(msg, 1, ""), + patientId: jspb.Message.getFieldWithDefault(msg, 2, "") }; if (includeInstance) { @@ -2082,23 +1843,23 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.toObject /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} + * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.deserializeBinary = function(bytes) { +proto.services.property_svc.v1.PatientPropertyMatcher.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value; - return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.deserializeBinaryFromReader(msg, reader); + var msg = new proto.services.property_svc.v1.PatientPropertyMatcher; + return proto.services.property_svc.v1.PatientPropertyMatcher.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} msg The message object to deserialize into. + * @param {!proto.services.property_svc.v1.PatientPropertyMatcher} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} + * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.deserializeBinaryFromReader = function(msg, reader) { +proto.services.property_svc.v1.PatientPropertyMatcher.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -2107,63 +1868,11 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.deseriali switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); - msg.setPropertyId(value); + msg.setWardId(value); break; case 2: - var value = /** @type {!proto.services.property_svc.v1.FieldType} */ (reader.readEnum()); - msg.setFieldType(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setName(value); - break; - case 4: - var value = /** @type {string} */ (reader.readString()); - msg.setDescription(value); - break; - case 5: - var value = /** @type {boolean} */ (reader.readBool()); - msg.setIsArchived(value); - break; - case 6: - var value = /** @type {string} */ (reader.readString()); - msg.setTextValue(value); - break; - case 7: - var value = /** @type {number} */ (reader.readDouble()); - msg.setNumberValue(value); - break; - case 8: - var value = /** @type {boolean} */ (reader.readBool()); - msg.setBoolValue(value); - break; - case 9: - var value = new services_property_svc_v1_types_pb.Date; - reader.readMessage(value,services_property_svc_v1_types_pb.Date.deserializeBinaryFromReader); - msg.setDateValue(value); - break; - case 10: - var value = new google_protobuf_timestamp_pb.Timestamp; - reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); - msg.setDateTimeValue(value); - break; - case 11: - var value = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption; - reader.readMessage(value,proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.deserializeBinaryFromReader); - msg.setSelectValue(value); - break; - case 12: - var value = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue; - reader.readMessage(value,proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.deserializeBinaryFromReader); - msg.setMultiSelectValue(value); - break; - case 13: var value = /** @type {string} */ (reader.readString()); - msg.setPropertyConsistency(value); - break; - case 14: - var value = /** @type {string} */ (reader.readString()); - msg.setValueConsistency(value); + msg.setPatientId(value); break; default: reader.skipField(); @@ -2178,9 +1887,9 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.deseriali * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype.serializeBinary = function() { +proto.services.property_svc.v1.PatientPropertyMatcher.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.serializeBinaryToWriter(this, writer); + proto.services.property_svc.v1.PatientPropertyMatcher.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -2188,117 +1897,127 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} message + * @param {!proto.services.property_svc.v1.PatientPropertyMatcher} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.serializeBinaryToWriter = function(message, writer) { +proto.services.property_svc.v1.PatientPropertyMatcher.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getPropertyId(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } - f = message.getFieldType(); - if (f !== 0.0) { - writer.writeEnum( - 2, - f - ); - } - f = message.getName(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } - f = /** @type {string} */ (jspb.Message.getField(message, 4)); - if (f != null) { - writer.writeString( - 4, - f - ); - } - f = message.getIsArchived(); - if (f) { - writer.writeBool( - 5, - f - ); - } - f = /** @type {string} */ (jspb.Message.getField(message, 6)); - if (f != null) { - writer.writeString( - 6, - f - ); - } - f = /** @type {number} */ (jspb.Message.getField(message, 7)); - if (f != null) { - writer.writeDouble( - 7, - f - ); - } - f = /** @type {boolean} */ (jspb.Message.getField(message, 8)); - if (f != null) { - writer.writeBool( - 8, - f - ); - } - f = message.getDateValue(); - if (f != null) { - writer.writeMessage( - 9, - f, - services_property_svc_v1_types_pb.Date.serializeBinaryToWriter - ); - } - f = message.getDateTimeValue(); - if (f != null) { - writer.writeMessage( - 10, - f, - google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter - ); - } - f = message.getSelectValue(); - if (f != null) { - writer.writeMessage( - 11, - f, - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.serializeBinaryToWriter - ); - } - f = message.getMultiSelectValue(); + f = /** @type {string} */ (jspb.Message.getField(message, 1)); if (f != null) { - writer.writeMessage( - 12, - f, - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.serializeBinaryToWriter - ); - } - f = message.getPropertyConsistency(); - if (f.length > 0) { writer.writeString( - 13, + 1, f ); } - f = /** @type {string} */ (jspb.Message.getField(message, 14)); + f = /** @type {string} */ (jspb.Message.getField(message, 2)); if (f != null) { writer.writeString( - 14, + 2, f ); } }; +/** + * optional string ward_id = 1; + * @return {string} + */ +proto.services.property_svc.v1.PatientPropertyMatcher.prototype.getWardId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} returns this + */ +proto.services.property_svc.v1.PatientPropertyMatcher.prototype.setWardId = function(value) { + return jspb.Message.setField(this, 1, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} returns this + */ +proto.services.property_svc.v1.PatientPropertyMatcher.prototype.clearWardId = function() { + return jspb.Message.setField(this, 1, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.services.property_svc.v1.PatientPropertyMatcher.prototype.hasWardId = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional string patient_id = 2; + * @return {string} + */ +proto.services.property_svc.v1.PatientPropertyMatcher.prototype.getPatientId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} returns this + */ +proto.services.property_svc.v1.PatientPropertyMatcher.prototype.setPatientId = function(value) { + return jspb.Message.setField(this, 2, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.services.property_svc.v1.PatientPropertyMatcher} returns this + */ +proto.services.property_svc.v1.PatientPropertyMatcher.prototype.clearPatientId = function() { + return jspb.Message.setField(this, 2, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.services.property_svc.v1.PatientPropertyMatcher.prototype.hasPatientId = function() { + return jspb.Message.getField(this, 2) != null; +}; + + + +/** + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.oneofGroups_ = [[1,2]]; + +/** + * @enum {number} + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.MatcherCase = { + MATCHER_NOT_SET: 0, + TASK_MATCHER: 1, + PATIENT_MATCHER: 2 +}; + +/** + * @return {proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.MatcherCase} + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.getMatcherCase = function() { + return /** @type {proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.MatcherCase} */(jspb.Message.computeOneofCase(this, proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.oneofGroups_[0])); +}; @@ -2315,8 +2034,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.prototype.toObject = function(opt_includeInstance) { - return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.toObject(opt_includeInstance, this); +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.toObject = function(opt_includeInstance) { + return proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.toObject(opt_includeInstance, this); }; @@ -2325,15 +2044,14 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectVal * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} msg The msg instance to transform. + * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.toObject = function(includeInstance, msg) { +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.toObject = function(includeInstance, msg) { var f, obj = { - id: jspb.Message.getFieldWithDefault(msg, 1, ""), - name: jspb.Message.getFieldWithDefault(msg, 2, ""), - description: jspb.Message.getFieldWithDefault(msg, 3, "") + taskMatcher: (f = msg.getTaskMatcher()) && proto.services.property_svc.v1.TaskPropertyMatcher.toObject(includeInstance, f), + patientMatcher: (f = msg.getPatientMatcher()) && proto.services.property_svc.v1.PatientPropertyMatcher.toObject(includeInstance, f) }; if (includeInstance) { @@ -2347,23 +2065,23 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectVal /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} + * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.deserializeBinary = function(bytes) { +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption; - return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.deserializeBinaryFromReader(msg, reader); + var msg = new proto.services.property_svc.v1.GetAttachedPropertyValuesRequest; + return proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} msg The message object to deserialize into. + * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} + * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.deserializeBinaryFromReader = function(msg, reader) { +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -2371,16 +2089,14 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectVal var field = reader.getFieldNumber(); switch (field) { case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setId(value); + var value = new proto.services.property_svc.v1.TaskPropertyMatcher; + reader.readMessage(value,proto.services.property_svc.v1.TaskPropertyMatcher.deserializeBinaryFromReader); + msg.setTaskMatcher(value); break; case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setName(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setDescription(value); + var value = new proto.services.property_svc.v1.PatientPropertyMatcher; + reader.readMessage(value,proto.services.property_svc.v1.PatientPropertyMatcher.deserializeBinaryFromReader); + msg.setPatientMatcher(value); break; default: reader.skipField(); @@ -2395,9 +2111,9 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectVal * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.prototype.serializeBinary = function() { +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.serializeBinaryToWriter(this, writer); + proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -2405,97 +2121,258 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectVal /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} message + * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.serializeBinaryToWriter = function(message, writer) { +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getId(); - if (f.length > 0) { - writer.writeString( + f = message.getTaskMatcher(); + if (f != null) { + writer.writeMessage( 1, - f + f, + proto.services.property_svc.v1.TaskPropertyMatcher.serializeBinaryToWriter ); } - f = message.getName(); - if (f.length > 0) { - writer.writeString( + f = message.getPatientMatcher(); + if (f != null) { + writer.writeMessage( 2, - f + f, + proto.services.property_svc.v1.PatientPropertyMatcher.serializeBinaryToWriter ); } - f = message.getDescription(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); +}; + + +/** + * optional TaskPropertyMatcher task_matcher = 1; + * @return {?proto.services.property_svc.v1.TaskPropertyMatcher} + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.getTaskMatcher = function() { + return /** @type{?proto.services.property_svc.v1.TaskPropertyMatcher} */ ( + jspb.Message.getWrapperField(this, proto.services.property_svc.v1.TaskPropertyMatcher, 1)); +}; + + +/** + * @param {?proto.services.property_svc.v1.TaskPropertyMatcher|undefined} value + * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} returns this +*/ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.setTaskMatcher = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} returns this + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.clearTaskMatcher = function() { + return this.setTaskMatcher(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.hasTaskMatcher = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional PatientPropertyMatcher patient_matcher = 2; + * @return {?proto.services.property_svc.v1.PatientPropertyMatcher} + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.getPatientMatcher = function() { + return /** @type{?proto.services.property_svc.v1.PatientPropertyMatcher} */ ( + jspb.Message.getWrapperField(this, proto.services.property_svc.v1.PatientPropertyMatcher, 2)); +}; + + +/** + * @param {?proto.services.property_svc.v1.PatientPropertyMatcher|undefined} value + * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} returns this +*/ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.setPatientMatcher = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesRequest} returns this + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.clearPatientMatcher = function() { + return this.setPatientMatcher(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesRequest.prototype.hasPatientMatcher = function() { + return jspb.Message.getField(this, 2) != null; +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.prototype.toObject = function(opt_includeInstance) { + return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.toObject = function(includeInstance, msg) { + var f, obj = { + valuesList: jspb.Message.toObjectList(msg.getValuesList(), + proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; } + return obj; }; +} /** - * optional string id = 1; - * @return {string} + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.prototype.getId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse; + return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.deserializeBinaryFromReader(msg, reader); }; /** - * @param {string} value - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} returns this + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.prototype.setId = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value; + reader.readMessage(value,proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.deserializeBinaryFromReader); + msg.addValues(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; }; /** - * optional string name = 2; - * @return {string} + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.prototype.getName = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); }; /** - * @param {string} value - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} returns this + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.prototype.setName = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getValuesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.serializeBinaryToWriter + ); + } }; + /** - * optional string description = 3; - * @return {string} + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.prototype.getDescription = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.oneofGroups_ = [[6,7,8,9,10,11,12]]; /** - * @param {string} value - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} returns this + * @enum {number} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.prototype.setDescription = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.ValueCase = { + VALUE_NOT_SET: 0, + TEXT_VALUE: 6, + NUMBER_VALUE: 7, + BOOL_VALUE: 8, + DATE_VALUE: 9, + DATE_TIME_VALUE: 10, + SELECT_VALUE: 11, + MULTI_SELECT_VALUE: 12 }; - - /** - * List of repeated fields within this message type. - * @private {!Array} - * @const + * @return {proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.ValueCase} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.repeatedFields_ = [1]; +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype.getValueCase = function() { + return /** @type {proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.ValueCase} */(jspb.Message.computeOneofCase(this, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.oneofGroups_[0])); +}; @@ -2512,8 +2389,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.prototype.toObject = function(opt_includeInstance) { - return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.toObject(opt_includeInstance, this); +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype.toObject = function(opt_includeInstance) { + return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.toObject(opt_includeInstance, this); }; @@ -2522,14 +2399,26 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSele * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue} msg The msg instance to transform. + * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.toObject = function(includeInstance, msg) { +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.toObject = function(includeInstance, msg) { var f, obj = { - selectValuesList: jspb.Message.toObjectList(msg.getSelectValuesList(), - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.toObject, includeInstance) + propertyId: jspb.Message.getFieldWithDefault(msg, 1, ""), + fieldType: jspb.Message.getFieldWithDefault(msg, 2, 0), + name: jspb.Message.getFieldWithDefault(msg, 3, ""), + description: jspb.Message.getFieldWithDefault(msg, 4, ""), + isArchived: jspb.Message.getBooleanFieldWithDefault(msg, 5, false), + textValue: jspb.Message.getFieldWithDefault(msg, 6, ""), + numberValue: jspb.Message.getFloatingPointFieldWithDefault(msg, 7, 0.0), + boolValue: jspb.Message.getBooleanFieldWithDefault(msg, 8, false), + dateValue: (f = msg.getDateValue()) && services_property_svc_v1_types_pb.Date.toObject(includeInstance, f), + dateTimeValue: (f = msg.getDateTimeValue()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f), + selectValue: (f = msg.getSelectValue()) && proto.services.property_svc.v1.SelectValueOption.toObject(includeInstance, f), + multiSelectValue: (f = msg.getMultiSelectValue()) && proto.services.property_svc.v1.MultiSelectValue.toObject(includeInstance, f), + propertyConsistency: jspb.Message.getFieldWithDefault(msg, 13, ""), + valueConsistency: jspb.Message.getFieldWithDefault(msg, 14, "") }; if (includeInstance) { @@ -2543,23 +2432,23 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSele /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue} + * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.deserializeBinary = function(bytes) { +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue; - return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.deserializeBinaryFromReader(msg, reader); + var msg = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value; + return proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue} msg The message object to deserialize into. + * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue} + * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.deserializeBinaryFromReader = function(msg, reader) { +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -2567,9 +2456,64 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSele var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption; - reader.readMessage(value,proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.deserializeBinaryFromReader); - msg.addSelectValues(value); + var value = /** @type {string} */ (reader.readString()); + msg.setPropertyId(value); + break; + case 2: + var value = /** @type {!proto.services.property_svc.v1.FieldType} */ (reader.readEnum()); + msg.setFieldType(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setDescription(value); + break; + case 5: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setIsArchived(value); + break; + case 6: + var value = /** @type {string} */ (reader.readString()); + msg.setTextValue(value); + break; + case 7: + var value = /** @type {number} */ (reader.readDouble()); + msg.setNumberValue(value); + break; + case 8: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setBoolValue(value); + break; + case 9: + var value = new services_property_svc_v1_types_pb.Date; + reader.readMessage(value,services_property_svc_v1_types_pb.Date.deserializeBinaryFromReader); + msg.setDateValue(value); + break; + case 10: + var value = new google_protobuf_timestamp_pb.Timestamp; + reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); + msg.setDateTimeValue(value); + break; + case 11: + var value = new proto.services.property_svc.v1.SelectValueOption; + reader.readMessage(value,proto.services.property_svc.v1.SelectValueOption.deserializeBinaryFromReader); + msg.setSelectValue(value); + break; + case 12: + var value = new proto.services.property_svc.v1.MultiSelectValue; + reader.readMessage(value,proto.services.property_svc.v1.MultiSelectValue.deserializeBinaryFromReader); + msg.setMultiSelectValue(value); + break; + case 13: + var value = /** @type {string} */ (reader.readString()); + msg.setPropertyConsistency(value); + break; + case 14: + var value = /** @type {string} */ (reader.readString()); + msg.setValueConsistency(value); break; default: reader.skipField(); @@ -2584,9 +2528,9 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSele * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.prototype.serializeBinary = function() { +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.serializeBinaryToWriter(this, writer); + proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -2594,58 +2538,114 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSele /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue} message + * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.serializeBinaryToWriter = function(message, writer) { +proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getSelectValuesList(); + f = message.getPropertyId(); if (f.length > 0) { - writer.writeRepeatedMessage( + writer.writeString( 1, + f + ); + } + f = message.getFieldType(); + if (f !== 0.0) { + writer.writeEnum( + 2, + f + ); + } + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 4)); + if (f != null) { + writer.writeString( + 4, + f + ); + } + f = message.getIsArchived(); + if (f) { + writer.writeBool( + 5, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 6)); + if (f != null) { + writer.writeString( + 6, + f + ); + } + f = /** @type {number} */ (jspb.Message.getField(message, 7)); + if (f != null) { + writer.writeDouble( + 7, + f + ); + } + f = /** @type {boolean} */ (jspb.Message.getField(message, 8)); + if (f != null) { + writer.writeBool( + 8, + f + ); + } + f = message.getDateValue(); + if (f != null) { + writer.writeMessage( + 9, f, - proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption.serializeBinaryToWriter + services_property_svc_v1_types_pb.Date.serializeBinaryToWriter + ); + } + f = message.getDateTimeValue(); + if (f != null) { + writer.writeMessage( + 10, + f, + google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter + ); + } + f = message.getSelectValue(); + if (f != null) { + writer.writeMessage( + 11, + f, + proto.services.property_svc.v1.SelectValueOption.serializeBinaryToWriter + ); + } + f = message.getMultiSelectValue(); + if (f != null) { + writer.writeMessage( + 12, + f, + proto.services.property_svc.v1.MultiSelectValue.serializeBinaryToWriter + ); + } + f = message.getPropertyConsistency(); + if (f.length > 0) { + writer.writeString( + 13, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 14)); + if (f != null) { + writer.writeString( + 14, + f ); } -}; - - -/** - * repeated SelectValueOption select_values = 1; - * @return {!Array} - */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.prototype.getSelectValuesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption, 1)); -}; - - -/** - * @param {!Array} value - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue} returns this -*/ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.prototype.setSelectValuesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 1, value); -}; - - -/** - * @param {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption=} opt_value - * @param {number=} opt_index - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} - */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.prototype.addSelectValues = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue} returns this - */ -proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue.prototype.clearSelectValuesList = function() { - return this.setSelectValuesList([]); }; @@ -2941,16 +2941,16 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype /** * optional SelectValueOption select_value = 11; - * @return {?proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} + * @return {?proto.services.property_svc.v1.SelectValueOption} */ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype.getSelectValue = function() { - return /** @type{?proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption} */ ( - jspb.Message.getWrapperField(this, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption, 11)); + return /** @type{?proto.services.property_svc.v1.SelectValueOption} */ ( + jspb.Message.getWrapperField(this, proto.services.property_svc.v1.SelectValueOption, 11)); }; /** - * @param {?proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.SelectValueOption|undefined} value + * @param {?proto.services.property_svc.v1.SelectValueOption|undefined} value * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} returns this */ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype.setSelectValue = function(value) { @@ -2978,16 +2978,16 @@ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype /** * optional MultiSelectValue multi_select_value = 12; - * @return {?proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue} + * @return {?proto.services.property_svc.v1.MultiSelectValue} */ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype.getMultiSelectValue = function() { - return /** @type{?proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue} */ ( - jspb.Message.getWrapperField(this, proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue, 12)); + return /** @type{?proto.services.property_svc.v1.MultiSelectValue} */ ( + jspb.Message.getWrapperField(this, proto.services.property_svc.v1.MultiSelectValue, 12)); }; /** - * @param {?proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.MultiSelectValue|undefined} value + * @param {?proto.services.property_svc.v1.MultiSelectValue|undefined} value * @return {!proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value} returns this */ proto.services.property_svc.v1.GetAttachedPropertyValuesResponse.Value.prototype.setMultiSelectValue = function(value) { diff --git a/gen/ts/services/tasks_svc/v1/task_svc_pb.d.ts b/gen/ts/services/tasks_svc/v1/task_svc_pb.d.ts index 1bc57835c..5a09543cd 100644 --- a/gen/ts/services/tasks_svc/v1/task_svc_pb.d.ts +++ b/gen/ts/services/tasks_svc/v1/task_svc_pb.d.ts @@ -951,11 +951,6 @@ export class UnassignTaskRequest extends jspb.Message { getUserId(): string; setUserId(value: string): UnassignTaskRequest; - getConsistency(): string; - setConsistency(value: string): UnassignTaskRequest; - hasConsistency(): boolean; - clearConsistency(): UnassignTaskRequest; - serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): UnassignTaskRequest.AsObject; static toObject(includeInstance: boolean, msg: UnassignTaskRequest): UnassignTaskRequest.AsObject; @@ -968,12 +963,6 @@ export namespace UnassignTaskRequest { export type AsObject = { taskId: string, userId: string, - consistency?: string, - } - - export enum ConsistencyCase { - _CONSISTENCY_NOT_SET = 0, - CONSISTENCY = 3, } } diff --git a/gen/ts/services/tasks_svc/v1/task_svc_pb.js b/gen/ts/services/tasks_svc/v1/task_svc_pb.js index 1e19b6154..255ecdcd6 100644 --- a/gen/ts/services/tasks_svc/v1/task_svc_pb.js +++ b/gen/ts/services/tasks_svc/v1/task_svc_pb.js @@ -7219,8 +7219,7 @@ proto.services.tasks_svc.v1.UnassignTaskRequest.prototype.toObject = function(op proto.services.tasks_svc.v1.UnassignTaskRequest.toObject = function(includeInstance, msg) { var f, obj = { taskId: jspb.Message.getFieldWithDefault(msg, 1, ""), - userId: jspb.Message.getFieldWithDefault(msg, 2, ""), - consistency: jspb.Message.getFieldWithDefault(msg, 3, "") + userId: jspb.Message.getFieldWithDefault(msg, 2, "") }; if (includeInstance) { @@ -7265,10 +7264,6 @@ proto.services.tasks_svc.v1.UnassignTaskRequest.deserializeBinaryFromReader = fu var value = /** @type {string} */ (reader.readString()); msg.setUserId(value); break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setConsistency(value); - break; default: reader.skipField(); break; @@ -7312,13 +7307,6 @@ proto.services.tasks_svc.v1.UnassignTaskRequest.serializeBinaryToWriter = functi f ); } - f = /** @type {string} */ (jspb.Message.getField(message, 3)); - if (f != null) { - writer.writeString( - 3, - f - ); - } }; @@ -7358,42 +7346,6 @@ proto.services.tasks_svc.v1.UnassignTaskRequest.prototype.setUserId = function(v }; -/** - * optional string consistency = 3; - * @return {string} - */ -proto.services.tasks_svc.v1.UnassignTaskRequest.prototype.getConsistency = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.services.tasks_svc.v1.UnassignTaskRequest} returns this - */ -proto.services.tasks_svc.v1.UnassignTaskRequest.prototype.setConsistency = function(value) { - return jspb.Message.setField(this, 3, value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.services.tasks_svc.v1.UnassignTaskRequest} returns this - */ -proto.services.tasks_svc.v1.UnassignTaskRequest.prototype.clearConsistency = function() { - return jspb.Message.setField(this, 3, undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.services.tasks_svc.v1.UnassignTaskRequest.prototype.hasConsistency = function() { - return jspb.Message.getField(this, 3) != null; -}; - - diff --git a/libs/common/conflict.go b/libs/common/conflict.go new file mode 100644 index 000000000..c35f68c73 --- /dev/null +++ b/libs/common/conflict.go @@ -0,0 +1,6 @@ +package common + +type Conflict[T any] struct { + Is T + Was T +} diff --git a/libs/common/consistency.go b/libs/common/consistency.go index dd312ec8d..6da1ebed7 100644 --- a/libs/common/consistency.go +++ b/libs/common/consistency.go @@ -1,9 +1,23 @@ package common -import "strconv" +import ( + "hwutil" + "strconv" +) type ConsistencyToken uint64 func (c ConsistencyToken) String() string { return strconv.FormatUint(uint64(c), 10) } + +func ParseConsistency(consistencyStr *string) (consistency *ConsistencyToken, success bool) { + if consistencyStr == nil { + return nil, true + } + if c, err := strconv.ParseUint(*consistencyStr, 10, 64); err != nil { + return nil, false + } else { + return hwutil.PtrTo(ConsistencyToken(c)), true + } +} diff --git a/libs/common/errors.go b/libs/common/errors.go new file mode 100644 index 000000000..84033f689 --- /dev/null +++ b/libs/common/errors.go @@ -0,0 +1,34 @@ +package common + +import ( + "context" + "hwlocale" + + "common/hwerr" + + "common/locale" + + "google.golang.org/genproto/googleapis/rpc/errdetails" + "google.golang.org/grpc/codes" +) + +// SingleInvalidFieldError builds a NewStatusError +func SingleInvalidFieldError(ctx context.Context, field, msg string, locale hwlocale.Locale) error { + return hwerr.NewStatusError(ctx, + codes.InvalidArgument, + msg, + locale, + &errdetails.BadRequest{ + FieldViolations: []*errdetails.BadRequest_FieldViolation{ + { + Field: field, + Description: hwlocale.Localize(ctx, locale), + }, + }, + }, + ) +} + +func UnparsableConsistencyError(ctx context.Context, field string) error { + return SingleInvalidFieldError(ctx, field, "consistency not parsable", locale.InvalidFieldError(ctx)) +} diff --git a/libs/hwauthz/commonPerm/userOrg.go b/libs/hwauthz/commonPerm/userOrg.go new file mode 100644 index 000000000..3973e2985 --- /dev/null +++ b/libs/hwauthz/commonPerm/userOrg.go @@ -0,0 +1,34 @@ +package commonPerm + +import ( + "common/auth" + "context" + + "github.com/google/uuid" +) + +type User uuid.UUID + +func (t User) Type() string { return "user" } +func (t User) ID() string { return uuid.UUID(t).String() } + +func UserFromCtx(ctx context.Context) (User, error) { + userID, err := auth.GetUserID(ctx) + if err != nil { + return User{}, err + } + return User(userID), nil +} + +type Organization uuid.UUID + +func (p Organization) Type() string { return "organization" } +func (p Organization) ID() string { return uuid.UUID(p).String() } + +func OrganizationFromCtx(ctx context.Context) (Organization, error) { + organizationID, err := auth.GetOrganizationID(ctx) + if err != nil { + return Organization{}, err + } + return Organization(organizationID), nil +} diff --git a/libs/hwes/aggregate_store.go b/libs/hwes/aggregate_store.go index 3115cdb55..e492ed4ac 100644 --- a/libs/hwes/aggregate_store.go +++ b/libs/hwes/aggregate_store.go @@ -11,6 +11,9 @@ type AggregateStore interface { // Load populates the aggregate to the recent version of the persisted events Load(ctx context.Context, aggregate Aggregate) error + // LoadN populates the aggregate by N-many persisted events + LoadN(ctx context.Context, aggregate Aggregate, N uint64) error + // Save persists all uncommitted events of the aggregate, returns consistency token Save(ctx context.Context, aggregate Aggregate) (common.ConsistencyToken, error) diff --git a/libs/hwes/event.go b/libs/hwes/event.go index ac095424f..b9f9bdc6d 100644 --- a/libs/hwes/event.go +++ b/libs/hwes/event.go @@ -172,7 +172,6 @@ func NewEventFromRecordedEvent(esdbEvent *esdb.RecordedEvent) (Event, error) { if err == nil { event.CommitterUserID = &eventCommitterUserID } - eventOrganizationID, err := uuid.Parse(md.OrganizationID) if err == nil { event.OrganizationID = &eventOrganizationID @@ -314,6 +313,9 @@ func (e *Event) GetZerologDict() *zerolog.Event { if e.CommitterUserID != nil { dict.Str("committerUserID", e.CommitterUserID.String()) } + if e.OrganizationID != nil { + dict.Str("organizaionID", e.OrganizationID.String()) + } return dict } diff --git a/libs/hwes/eventstoredb/aggregate_store.go b/libs/hwes/eventstoredb/aggregate_store.go index 942429fc7..f85710d94 100644 --- a/libs/hwes/eventstoredb/aggregate_store.go +++ b/libs/hwes/eventstoredb/aggregate_store.go @@ -99,44 +99,62 @@ func (as *AggregateStore) doSave( // Implements AggregateStore interface -func (as *AggregateStore) Load(ctx context.Context, aggregate hwes.Aggregate) error { - stream, err := as.es.ReadStream( - ctx, - aggregate.GetTypeID(), - esdb.ReadStreamOptions{}, - math.MaxUint64, // MaxUint64 for "all" events - ) +func (a *AggregateStore) LoadN(ctx context.Context, aggregate hwes.Aggregate, n uint64) error { + if n == 0 { + return nil + } + + // start from the beginning, unless we have already processed events + var from esdb.StreamPosition = esdb.Start{} + aE := aggregate.GetAppliedEvents() + if len(aE) != 0 { + // We cant just use the aggreagate's Version here, as we are unable to + // discriminate aggregates where the first event was processed already (version = 0) + // from those aggregates where no event was processed yet (version = 0 by default) + from = esdb.Revision(aE[len(aE)-1].Version + 1) + } + + // open a read stream + stream, err := a.es.ReadStream(ctx, aggregate.GetTypeID(), esdb.ReadStreamOptions{ + Direction: esdb.Forwards, + From: from, + }, n) if err != nil { - return fmt.Errorf("AggregateStore.Load: could not open stream: %w", err) + return fmt.Errorf("AggregateStore.LoadN: could not open stream: %w", err) } defer stream.Close() + // stream events in for { esdbEvent, err := stream.Recv() if errors.Is(err, io.EOF) { - // exit condition for for-loop + // all events were handled! break } else if err != nil { - return fmt.Errorf("AggregateStore.Load: could not read from stream: %w", err) + return fmt.Errorf("AggregateStore.LoadN: could not read from stream: %w", err) } event, err := hwes.NewEventFromRecordedEvent(esdbEvent.Event) if err != nil { - return fmt.Errorf("AggregateStore.Load: %w", err) + return fmt.Errorf("AggregateStore.LoadN: %w", err) } if err := aggregate.Progress(event); err != nil { - return fmt.Errorf("AggregateStore.Load: Progress failed: %w", err) + return fmt.Errorf("AggregateStore.LoadN: Progress failed: %w", err) } } if aggregate.IsDeleted() { - return errors.New("AggregateStore.Load: aggregate has been marked as deleted") + return errors.New("AggregateStore.LoadN: aggregate has been marked as deleted") } return nil } +func (a *AggregateStore) Load(ctx context.Context, aggregate hwes.Aggregate) error { + return a.LoadN(ctx, aggregate, math.MaxUint64) // MaxUint64 -> all events +} + func (as *AggregateStore) Save(ctx context.Context, aggregate hwes.Aggregate) (common.ConsistencyToken, error) { // We can switch out the getExpectedRevision strategy for testing optimistic concurrency. // It is not intended to switch the strategy in production. diff --git a/libs/hwes/eventstoredb/integration_test.go b/libs/hwes/eventstoredb/integration_test.go new file mode 100644 index 000000000..4820c2804 --- /dev/null +++ b/libs/hwes/eventstoredb/integration_test.go @@ -0,0 +1,91 @@ +package eventstoredb + +import ( + "context" + "fmt" + "hwtesting" + "os" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/google/uuid" + zlog "github.com/rs/zerolog/log" + "github.com/stretchr/testify/assert" + "hwes" +) + +var endpoint string + +func TestMain(m *testing.M) { + ctx, cancel := context.WithCancel(context.Background()) + + zlog.Info().Msg("starting containers") + endpoints, teardownContainers := hwtesting.StartContainers(ctx, hwtesting.Eventstore) + + endpoint = fmt.Sprintf("esdb://%s:%s@%s?tls=false", + hwtesting.EsUser, hwtesting.EsPassword, endpoints.Get(hwtesting.Eventstore)) + + exit := m.Run() + + teardownContainers() + cancel() + os.Exit(exit) +} + +func TestLoadN(t *testing.T) { + zlog.Info().Str("endpoint", endpoint).Msg(t.Name()) + client := SetupEventStore(endpoint) + as := NewAggregateStore(client) + ctx := context.Background() + + id := uuid.New() + eventType := t.Name() + + sendAggregate := hwes.NewAggregateBase(hwes.AggregateType(eventType), id) + sendAggregate.RegisterEventListener(eventType, func(evt hwes.Event) error { return nil }) + + for range 4 { + event, _ := hwes.NewEvent(sendAggregate, eventType, hwes.WithContext(ctx)) + require.NoError(t, sendAggregate.Apply(event)) + } + + _, err := as.Save(ctx, sendAggregate) + require.NoError(t, err) + + time.Sleep(time.Millisecond * 100) + + rxAggregate := hwes.NewAggregateBase(hwes.AggregateType(eventType), id) + rxAggregate.RegisterEventListener(eventType, func(evt hwes.Event) error { return nil }) + assert.Empty(t, sendAggregate.GetAppliedEvents()) + + // LoadN 0 does nothing + err = as.LoadN(ctx, rxAggregate, 0) + require.NoError(t, err) + assert.Empty(t, rxAggregate.GetAppliedEvents()) + + // LoadN 1 loads the first event + err = as.LoadN(ctx, rxAggregate, 1) + require.NoError(t, err) + assert.Len(t, rxAggregate.GetAppliedEvents(), 1) + assert.Equal(t, uint64(0), rxAggregate.GetAppliedEvents()[0].Version) + + // LoadN 1 loads another event + err = as.LoadN(ctx, rxAggregate, 1) + require.NoError(t, err) + assert.Len(t, rxAggregate.GetAppliedEvents(), 2) + assert.Equal(t, uint64(1), rxAggregate.GetAppliedEvents()[1].Version) + + // LoadN 2 loads the rest + err = as.LoadN(ctx, rxAggregate, 2) + require.NoError(t, err) + assert.Len(t, rxAggregate.GetAppliedEvents(), 4) + assert.Equal(t, uint64(2), rxAggregate.GetAppliedEvents()[2].Version) + assert.Equal(t, uint64(3), rxAggregate.GetAppliedEvents()[3].Version) + + // LoadN 1 now does nothing anymore + err = as.LoadN(ctx, rxAggregate, 1) + require.NoError(t, err) + assert.Len(t, rxAggregate.GetAppliedEvents(), 4) +} diff --git a/libs/hwes/go.mod b/libs/hwes/go.mod index 9722239d6..ca3f09e68 100644 --- a/libs/hwes/go.mod +++ b/libs/hwes/go.mod @@ -4,7 +4,9 @@ go 1.23 replace ( common => ../common + hwauthz => ../hwauthz hwlocale => ../hwlocale + hwtesting => ../hwtesting hwutil => ../hwutil telemetry => ../telemetry ) @@ -15,44 +17,94 @@ require ( github.com/google/uuid v1.6.0 github.com/rs/zerolog v1.33.0 github.com/stretchr/testify v1.9.0 + hwtesting v0.0.0 hwutil v0.0.0 telemetry v0.0.0 ) require ( - github.com/BurntSushi/toml v1.4.0 // indirect + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect + github.com/Mariscal6/testcontainers-spicedb-go v0.1.0 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/authzed/authzed-go v0.15.0 // indirect + github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/coreos/go-oidc v2.2.1+incompatible // indirect + github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/dapr/dapr v1.14.2 // indirect github.com/dapr/go-sdk v1.11.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v27.2.0+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect github.com/fatih/structs v1.1.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.22.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-migrate/migrate/v4 v4.18.1 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/joho/godotenv v1.5.1 // indirect + github.com/jzelinskie/stringz v0.0.3 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nicksnyder/go-i18n/v2 v2.4.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/openzipkin/zipkin-go v0.4.3 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/pquerna/cachecontrol v0.1.0 // indirect github.com/prometheus/client_golang v1.20.3 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect + github.com/samber/lo v1.47.0 // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/testcontainers/testcontainers-go v0.33.0 // indirect + github.com/testcontainers/testcontainers-go/modules/postgres v0.33.0 // indirect + github.com/testcontainers/testcontainers-go/modules/redis v0.33.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect go.opentelemetry.io/otel v1.30.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 // indirect @@ -62,6 +114,7 @@ require ( go.opentelemetry.io/otel/sdk v1.30.0 // indirect go.opentelemetry.io/otel/trace v1.30.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/atomic v1.10.0 // indirect golang.org/x/crypto v0.27.0 // indirect golang.org/x/net v0.29.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect @@ -73,5 +126,6 @@ require ( google.golang.org/protobuf v1.34.2 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + hwauthz v0.0.0 // indirect hwlocale v0.0.0 // indirect ) diff --git a/libs/hwes/go.sum b/libs/hwes/go.sum index 7044691ca..962782aaa 100644 --- a/libs/hwes/go.sum +++ b/libs/hwes/go.sum @@ -1,55 +1,84 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/EventStore/EventStore-Client-Go/v4 v4.1.0 h1:P1dYxz+ReXJd7MAPSgZ5MvZltWoJWN3L/2p99yNKkic= github.com/EventStore/EventStore-Client-Go/v4 v4.1.0/go.mod h1:w2z38mcQWUCrN8PzQoS5ZkiC1a2MN6EuSE5CFVBOmfQ= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= -github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/Mariscal6/testcontainers-spicedb-go v0.1.0 h1:3R0ADWngw92Ri83esfukM38eK5E4D80058VHwftY1Ds= +github.com/Mariscal6/testcontainers-spicedb-go v0.1.0/go.mod h1:ix0Mqepw7XaLDLTlYlIE2inKxZIykSe0I2J2/ZN9o4Q= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/authzed/authzed-go v0.15.0 h1:O6G1sZYOKPzxr9zqHPtpQ2gsBZMzQTtO2Nh91K7Ocho= +github.com/authzed/authzed-go v0.15.0/go.mod h1:T0Gte6lDkMKgI9qsnuRCWlBoZDAYVYEBJ579MEX7I2I= +github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b h1:wbh8IK+aMLTCey9sZasO7b6BWLAJnHHvb79fvWCXwxw= +github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b/go.mod h1:s3qC7V7XIbiNWERv7Lfljy/Lx25/V1Qlexb0WJuA8uQ= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= +github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= -github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/dapr/dapr v1.14.2 h1:FCeBtDz7k/ZbmWbd/SfFqrnmzHHC/hmUkGdf9z0fimM= github.com/dapr/dapr v1.14.2/go.mod h1:55ilcTqOGrWoBPYn/Cdj+8RSEWrnvfpwTF5V9mBsSDo= github.com/dapr/go-sdk v1.11.0 h1:clANpOQd6MsfvSa6snaX8MVk6eRx26Vsj5GxGdQ6mpE= github.com/dapr/go-sdk v1.11.0/go.mod h1:btZ/tX8eYnx0fg3HiJUku8J5QBRXHsp3kAB1BUiTxXY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v25.0.5+incompatible h1:UmQydMduGkrD5nQde1mecF/YnSbTOaPeFIeP5C4W+DE= -github.com/docker/docker v25.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dhui/dktest v0.4.3 h1:wquqUxAFdcUgabAVLvSCOKOlag5cIZuaOjYIBOWdsR0= +github.com/dhui/dktest v0.4.3/go.mod h1:zNK8IwktWzQRm6I/l2Wjp7MakiyaFWv4G1hjmodmMTs= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= +github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM= +github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -65,33 +94,73 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-migrate/migrate/v4 v4.18.1 h1:JML/k+t4tpHCpQTCAD62Nu43NUFzHY4CV3uAuvHGC+Y= +github.com/golang-migrate/migrate/v4 v4.18.1/go.mod h1:HAX6m3sQgcdO81tdjn5exv20+3Kb13cmGli1hrD6hks= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e h1:XmA6L9IPRdUr28a+SK/oMchGgQy159wvzXA5tJ7l+40= github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e/go.mod h1:AFIo+02s+12CEg8Gzz9kzhCbmbq6JcKNrhHffCGA9z4= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/jzelinskie/stringz v0.0.3 h1:0GhG3lVMYrYtIvRbxvQI6zqRTT1P1xyQlpa0FhfUXas= +github.com/jzelinskie/stringz v0.0.3/go.mod h1:hHYbgxJuNLRw91CmpuFsYEOyQqpDVFg8pvEh23vy4P0= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -102,12 +171,16 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -120,10 +193,14 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -133,6 +210,7 @@ github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8 github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= @@ -144,28 +222,49 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= +github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/testcontainers/testcontainers-go v0.30.0 h1:jmn/XS22q4YRrcMwWg0pAwlClzs/abopbsBzrepyc4E= -github.com/testcontainers/testcontainers-go v0.30.0/go.mod h1:K+kHNGiM5zjklKjgTtcrEetF3uhWbMUyqAQoyoh8Pf0= +github.com/testcontainers/testcontainers-go v0.33.0 h1:zJS9PfXYT5O0ZFXM2xxXfk4J5UMw/kRiISng037Gxdw= +github.com/testcontainers/testcontainers-go v0.33.0/go.mod h1:W80YpTa8D5C3Yy16icheD01UTDu+LmXIA2Keo+jWtT8= +github.com/testcontainers/testcontainers-go/modules/postgres v0.33.0 h1:c+Gt+XLJjqFAejgX4hSpnHIpC9eAhvgI/TFWL/PbrFI= +github.com/testcontainers/testcontainers-go/modules/postgres v0.33.0/go.mod h1:I4DazHBoWDyf69ByOIyt3OdNjefiUx372459txOpQ3o= +github.com/testcontainers/testcontainers-go/modules/redis v0.33.0 h1:S/QvMOwpr00MM2aWH+krzP73Erlp/Ug0dr2rkgZYI5s= +github.com/testcontainers/testcontainers-go/modules/redis v0.33.0/go.mod h1:gudb3+6uZ9SsAysOVoLs7nazbjGlkHegBW8nqPXvDMI= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4= @@ -184,44 +283,120 @@ go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8d go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/libs/hwes/integration_test.go b/libs/hwes/integration_test.go index 72df89a75..a67e6ab1f 100644 --- a/libs/hwes/integration_test.go +++ b/libs/hwes/integration_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/google/uuid" + "github.com/stretchr/testify/assert" "hwes" "hwes/test" ) @@ -142,13 +143,8 @@ func TestIntegration(t *testing.T) { t.Fatal(err) } - if loadedUserAggregate.User.ID != id { - t.Fatal("invalid id") - } - - if loadedUserAggregate.User.Username != "testine.test" { - t.Fatal("invalid username") - } + assert.Equal(t, id, loadedUserAggregate.User.ID) + assert.Equal(t, "testine.test", loadedUserAggregate.User.Username) } func TestAggregateBase_RegisterEventListener_HandleEvent(t *testing.T) { diff --git a/libs/hwes/test/memory_aggregate_store.go b/libs/hwes/test/memory_aggregate_store.go index 49784af1c..5ec9f59cc 100644 --- a/libs/hwes/test/memory_aggregate_store.go +++ b/libs/hwes/test/memory_aggregate_store.go @@ -3,6 +3,7 @@ package test import ( "common" "context" + "math" "testing" "github.com/stretchr/testify/assert" @@ -19,10 +20,23 @@ func NewAggregateStore() *AggregateStore { return &AggregateStore{streams: make(map[string][]hwes.Event)} } -func (a *AggregateStore) Load(ctx context.Context, aggregate hwes.Aggregate) error { +func (a *AggregateStore) LoadN(_ context.Context, aggregate hwes.Aggregate, n uint64) error { events := a.streams[aggregate.GetTypeID()] - for _, event := range events { + skipUpTo := uint64(0) + aE := aggregate.GetAppliedEvents() + if len(aE) != 0 { + skipUpTo = aE[len(aE)-1].Version + 1 + } + + for i, event := range events { + if uint64(i) < skipUpTo { //nolint:gosec + continue + } + + if uint64(i) >= n { //nolint:gosec + break + } if err := aggregate.Progress(event); err != nil { return err } @@ -31,6 +45,10 @@ func (a *AggregateStore) Load(ctx context.Context, aggregate hwes.Aggregate) err return nil } +func (a *AggregateStore) Load(ctx context.Context, aggregate hwes.Aggregate) error { + return a.LoadN(ctx, aggregate, math.MaxUint64) +} + func (a *AggregateStore) Save(ctx context.Context, aggregate hwes.Aggregate) (common.ConsistencyToken, error) { uncommittedEventsLen := len(aggregate.GetUncommittedEvents()) if uncommittedEventsLen == 0 { diff --git a/libs/hwgrpc/conflict.go b/libs/hwgrpc/conflict.go new file mode 100644 index 000000000..a4673b717 --- /dev/null +++ b/libs/hwgrpc/conflict.go @@ -0,0 +1,36 @@ +package hwgrpc + +import ( + "fmt" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" +) + +import commonpb "gen/libs/common/v1" + +// AttributeConflict is a constructor for commonpb.AttributeConflicts +func AttributeConflict(is, want proto.Message) (*commonpb.AttributeConflict, error) { + var err error + + var wantAny *anypb.Any + if want != nil { + wantAny, err = anypb.New(want) + if err != nil { + return nil, fmt.Errorf("AttributeConflict could not marshal want: %w", err) + } + } + + var isAny *anypb.Any + if is != nil { + isAny, err = anypb.New(is) + if err != nil { + return nil, fmt.Errorf("AttributeConflict could not marshal is: %w", err) + } + } + + return &commonpb.AttributeConflict{ + Is: isAny, + Want: wantAny, + }, nil +} diff --git a/libs/hwgrpc/go.mod b/libs/hwgrpc/go.mod new file mode 100644 index 000000000..a58430dda --- /dev/null +++ b/libs/hwgrpc/go.mod @@ -0,0 +1,9 @@ +module hwgrpc + +go 1.23 + +replace gen => ../../gen/go + +require gen v0.0.0 + +require google.golang.org/protobuf v1.32.0 diff --git a/libs/hwgrpc/go.sum b/libs/hwgrpc/go.sum new file mode 100644 index 000000000..5361bc77f --- /dev/null +++ b/libs/hwgrpc/go.sum @@ -0,0 +1,6 @@ +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/libs/hwtesting/grpc.go b/libs/hwtesting/grpc.go index f4cd7a669..643248528 100644 --- a/libs/hwtesting/grpc.go +++ b/libs/hwtesting/grpc.go @@ -39,23 +39,32 @@ const ( FakeTokenOrganization = "3b25c6f5-4705-4074-9fc6-a50c28eba406" //nolint:gosec ) -func GetFakeTokenCredentials(subOverride string) InsecureBearerToken { +func GetFakeTokenCredentials(subOverride, orgOverride string) InsecureBearerToken { + sub := FakeTokenUser + if subOverride != "" { + sub = subOverride + } + + org := "3b25c6f5-4705-4074-9fc6-a50c28eba406" + if orgOverride != "" { + org = orgOverride + } + // README's fake token m := map[string]interface{}{ - "sub": FakeTokenUser, - "email": "testine.test@helpwave.de", - "name": "Testine Test", - "preferred_username": "testine.test", + "sub": sub, + "email": "max.mustermann@helpwave.de", + "email_verified": true, + "name": "Max Mustermann", + "preferred_username": "max.mustermann", + "given_name": "Max", + "family_name": "Mustermann", "organization": map[string]interface{}{ - "id": FakeTokenOrganization, + "id": org, "name": "helpwave test", }, } - if subOverride != "" { - m["sub"] = subOverride - } - bytes, err := json.Marshal(m) if err != nil { panic(fmt.Errorf("GetFakeTokenCredentials failed: %w", err)) @@ -65,10 +74,10 @@ func GetFakeTokenCredentials(subOverride string) InsecureBearerToken { return InsecureBearerToken(dist) } -func GetGrpcConn(subOverride string) *grpc.ClientConn { +func GetGrpcConn(subOverride, orgOverride string) *grpc.ClientConn { conn, err := grpc.NewClient( common.ResolveAddrFromEnv(), - grpc.WithPerRPCCredentials(GetFakeTokenCredentials(subOverride)), + grpc.WithPerRPCCredentials(GetFakeTokenCredentials(subOverride, orgOverride)), grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { diff --git a/libs/hwutil/arrays.go b/libs/hwutil/arrays.go index fa94d3375..817fc434c 100644 --- a/libs/hwutil/arrays.go +++ b/libs/hwutil/arrays.go @@ -181,3 +181,46 @@ func OrEmptySlice[T any](as []T) []T { return make([]T, 0) } + +func Without[T comparable](original, itemsToRemove []T) []T { + // Create a map for quick lookup of items to remove + toRemove := make(map[T]bool) + for _, item := range itemsToRemove { + toRemove[item] = true + } + + var result []T + for _, item := range original { + if _, exists := toRemove[item]; !exists { + result = append(result, item) + } + } + + return result +} + +// SameItems yields true, iff a and b have the same elements (order may vary!) +func SameItems[T comparable](a, b []T) bool { + if len(a) != len(b) { + return false + } + + A := make(map[T]bool) + for _, item := range a { + A[item] = true + } + + B := make(map[T]bool) + for _, item := range b { + B[item] = true + } + + // Compare the maps + for key, in := range A { + if B[key] != in { + return false + } + } + + return true +} diff --git a/libs/hwutil/maps.go b/libs/hwutil/maps.go new file mode 100644 index 000000000..37cd69728 --- /dev/null +++ b/libs/hwutil/maps.go @@ -0,0 +1,15 @@ +package hwutil + +func Keys[K comparable, V any](mymap map[K]V) []K { + // stolen from https://stackoverflow.com/a/27848197 + + keys := make([]K, len(mymap)) + + i := 0 + for k := range mymap { + keys[i] = k + i++ + } + + return keys +} diff --git a/libs/hwutil/maps_test.go b/libs/hwutil/maps_test.go new file mode 100644 index 000000000..9e5969bde --- /dev/null +++ b/libs/hwutil/maps_test.go @@ -0,0 +1,19 @@ +package hwutil + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestKeys(t *testing.T) { + in := map[string]string{ + "A": "A", + "B": "A", + "C": "B", + } + out := []string{"A", "B", "C"} + + assert.Subset(t, out, Keys(in)) + assert.Len(t, Keys(in), len(out)) +} diff --git a/proto/libs/common/v1/conflict.proto b/proto/libs/common/v1/conflict.proto index 47baed387..a2c423aa8 100644 --- a/proto/libs/common/v1/conflict.proto +++ b/proto/libs/common/v1/conflict.proto @@ -14,11 +14,29 @@ option go_package = "gen/libs/common/v1"; // If WAS == IS, or WANT and IS are merge-able (e.g., requested action changes "name", and another action has changed "age"), no conflict arises. // Warning: If a previous action has deleted the resource, an error is raised, and no conflict returned. message Conflict { - // might be empty, in that case we don't have the history to calculate the conflicting attributes + // when history_missing is true, this map will contain elements, that might not have been updated since you have seen them last. + // it is then on you to compare these against your view of the world + // + // The key is the json-name of the field you tried to change, subkeys are split by dots ('.'), array elements are represented by the resources id: + // e.g.: for the request: `{"description": "Conflict", "select_data": {"upsert_options": [{"id": "123", "name": "Conflict"}]}}` + // this might be the conflict: `{"conflicting_attributes": {"description": ..., "select_data.upsert_options.123.name": ...}}` map conflicting_attributes = 1; + bool history_missing = 2; } message AttributeConflict { + // CAUTION: may be missing, if the is underlying value is missing (e.g., unassigned beds) + // Enums are returned as Int32s + // Arrays are encoded as AnyArrays google.protobuf.Any is = 1; + // CAUTION: may be missing, if the requested value is missing (e.g., unassignment of a bed) + // Enums are returned as Int32s + // Arrays are encoded as AnyArrays google.protobuf.Any want = 2; } + +// there is no native Any-compatible wrapper for arrays, +// so here is one +message AnyArray { + repeated google.protobuf.Any elements = 1; +} diff --git a/proto/services/property_svc/v1/property_value_svc.proto b/proto/services/property_svc/v1/property_value_svc.proto index b48226412..4cfb0f1de 100644 --- a/proto/services/property_svc/v1/property_value_svc.proto +++ b/proto/services/property_svc/v1/property_value_svc.proto @@ -8,6 +8,16 @@ import "libs/common/v1/conflict.proto"; option go_package = "gen/services/property-svc/v1"; +message SelectValueOption { + string id = 1; + string name = 2; + string description = 3; +} + +message MultiSelectValue { + repeated SelectValueOption select_values = 1; +} + // // AttachPropertyValueRequest // @@ -93,15 +103,7 @@ message GetAttachedPropertyValuesResponse { string property_consistency = 13; optional string value_consistency = 14; // missing, if no value available - message SelectValueOption { - string id = 1; - string name = 2; - string description = 3; - } - message MultiSelectValue { - repeated SelectValueOption select_values = 1; - } } repeated Value values = 1; diff --git a/proto/services/property_svc/v1/types.proto b/proto/services/property_svc/v1/types.proto index 94295c30b..e1e9b35db 100644 --- a/proto/services/property_svc/v1/types.proto +++ b/proto/services/property_svc/v1/types.proto @@ -8,7 +8,7 @@ import "google/protobuf/timestamp.proto"; message Date { // information more precise than date information shall be disregarded by clients - google.protobuf.Timestamp date = 1; + google.protobuf.Timestamp date = 1; // @gotags: validate:"required" } enum SubjectType { diff --git a/proto/services/tasks_svc/v1/task_svc.proto b/proto/services/tasks_svc/v1/task_svc.proto index ffc2f1128..a60a8d9f7 100644 --- a/proto/services/tasks_svc/v1/task_svc.proto +++ b/proto/services/tasks_svc/v1/task_svc.proto @@ -219,7 +219,6 @@ message AssignTaskResponse { message UnassignTaskRequest { string task_id = 1; // @gotags: validate:"uuid4" string user_id = 2; // @gotags: validate:"uuid4" - optional string consistency = 3; // no conflict detection, if not provided } message UnassignTaskResponse { diff --git a/services/property-svc/go.mod b/services/property-svc/go.mod index 6da93f8d8..4cdc538c5 100644 --- a/services/property-svc/go.mod +++ b/services/property-svc/go.mod @@ -8,6 +8,7 @@ replace ( hwauthz => ../../libs/hwauthz hwdb => ../../libs/hwdb hwes => ../../libs/hwes + hwgrpc => ../../libs/hwgrpc hwlocale => ../../libs/hwlocale hwtesting => ../../libs/hwtesting hwutil => ../../libs/hwutil @@ -23,6 +24,7 @@ require ( github.com/golang-migrate/migrate/v4 v4.18.1 github.com/google/uuid v1.6.0 github.com/jackc/pgx/v5 v5.7.1 + github.com/jinzhu/copier v0.3.5 github.com/pashagolub/pgxmock/v4 v4.3.0 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 @@ -32,6 +34,7 @@ require ( hwauthz v0.0.0 hwdb v0.0.0 hwes v0.0.0 + hwgrpc v0.0.0-00010101000000-000000000000 hwtesting v0.0.0 hwutil v0.0.0 telemetry v0.0.0 diff --git a/services/property-svc/go.sum b/services/property-svc/go.sum index 6794c70e6..cd6fee0c0 100644 --- a/services/property-svc/go.sum +++ b/services/property-svc/go.sum @@ -141,6 +141,8 @@ github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= +github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jzelinskie/stringz v0.0.3 h1:0GhG3lVMYrYtIvRbxvQI6zqRTT1P1xyQlpa0FhfUXas= diff --git a/services/property-svc/internal/property-value/aggregate/actions.go b/services/property-svc/internal/property-value/aggregate/actions.go index d230b2e20..35661ffb4 100644 --- a/services/property-svc/internal/property-value/aggregate/actions.go +++ b/services/property-svc/internal/property-value/aggregate/actions.go @@ -6,25 +6,26 @@ import ( "github.com/google/uuid" propertyEventsV1 "property-svc/internal/property-value/events/v1" + "property-svc/internal/property-value/models" ) func (a *PropertyValueAggregate) CreatePropertyValue( ctx context.Context, propertyID uuid.UUID, - value interface{}, + valueChange models.TypedValueChange, subjectID uuid.UUID, ) error { id := a.GetID() - event, err := propertyEventsV1.NewPropertyValueCreatedEvent(ctx, a, id, propertyID, value, subjectID) + event, err := propertyEventsV1.NewPropertyValueCreatedEvent(ctx, a, id, propertyID, valueChange, subjectID) if err != nil { return fmt.Errorf("PropertyValueAggregate.CreatePropertyValue: %w", err) } return a.Apply(event) } -func (a *PropertyValueAggregate) UpdatePropertyValue(ctx context.Context, value interface{}) error { - event, err := propertyEventsV1.NewPropertyValueUpdatedEvent(ctx, a, value) +func (a *PropertyValueAggregate) UpdatePropertyValue(ctx context.Context, valueChange models.TypedValueChange) error { + event, err := propertyEventsV1.NewPropertyValueUpdatedEvent(ctx, a, valueChange) if err != nil { return fmt.Errorf("PropertyValueAggregate.UpdatePropertyValue: %w", err) } diff --git a/services/property-svc/internal/property-value/aggregate/aggregate.go b/services/property-svc/internal/property-value/aggregate/aggregate.go index 9dd4b2781..82009ef8d 100644 --- a/services/property-svc/internal/property-value/aggregate/aggregate.go +++ b/services/property-svc/internal/property-value/aggregate/aggregate.go @@ -1,11 +1,13 @@ package aggregate import ( + "common" "context" "fmt" "hwes" "github.com/google/uuid" + "github.com/jinzhu/copier" propertyEventsV1 "property-svc/internal/property-value/events/v1" "property-svc/internal/property-value/models" @@ -19,9 +21,15 @@ type PropertyValueAggregate struct { } func NewPropertyValueAggregate(id uuid.UUID) *PropertyValueAggregate { - aggregate := &PropertyValueAggregate{PropertyValue: models.NewPropertyValue()} - aggregate.AggregateBase = hwes.NewAggregateBase(PropertyValueAggregateType, id) - aggregate.PropertyValue.ID = id + aggregate := &PropertyValueAggregate{ + PropertyValue: &models.PropertyValue{ + ID: id, + PropertyID: uuid.UUID{}, + SubjectID: uuid.UUID{}, + Value: nil, + }, + AggregateBase: hwes.NewAggregateBase(PropertyValueAggregateType, id), + } aggregate.initEventListeners() return aggregate } @@ -38,6 +46,36 @@ func LoadPropertyValueAggregate( return property, nil } +func LoadPropertyValueAggregateWithSnapshotAt( + ctx context.Context, + as hwes.AggregateStore, + id uuid.UUID, + pauseAt *common.ConsistencyToken, +) (*PropertyValueAggregate, *models.PropertyValue, error) { + property := NewPropertyValueAggregate(id) + + var snapshot *models.PropertyValue + + if pauseAt != nil { + // load pauseAt+1-many events (version is 0-indexed) + if err := as.LoadN(ctx, property, uint64(*pauseAt)+1); err != nil { + return nil, nil, err + } + + var cpy models.PropertyValue + if err := copier.CopyWithOption(&cpy, property.PropertyValue, copier.Option{DeepCopy: true}); err != nil { + return nil, nil, fmt.Errorf("LoadPropertyValueAggregateWithSnapshotAt: could not copy snapshot: %w", err) + } + snapshot = &cpy + } + + // load the rest + if err := as.Load(ctx, property); err != nil { + return nil, nil, fmt.Errorf("LoadPropertyValueAggregateWithSnapshotAt: %w", err) + } + return property, snapshot, nil +} + func (a *PropertyValueAggregate) initEventListeners() { a.RegisterEventListener(propertyEventsV1.PropertyValueCreated, a.onPropertyValueCreated) a.RegisterEventListener(propertyEventsV1.PropertyValueUpdated, a.onPropertyValueUpdated) @@ -60,9 +98,12 @@ func (a *PropertyValueAggregate) onPropertyValueCreated(evt hwes.Event) error { } a.PropertyValue.PropertyID = propertyID - a.PropertyValue.Value = payload.Value a.PropertyValue.SubjectID = subjectID + value := &models.SimpleTypedValue{} + payload.ValueChange.Apply(value) + a.PropertyValue.Value = value + return nil } @@ -72,7 +113,12 @@ func (a *PropertyValueAggregate) onPropertyValueUpdated(evt hwes.Event) error { return err } - a.PropertyValue.Value = payload.Value + if payload.ValueChange.ValueRemoved { + a.PropertyValue.Value = nil + return nil + } + + payload.ValueChange.Apply(a.PropertyValue.Value) return nil } diff --git a/services/property-svc/internal/property-value/api/grpc.go b/services/property-svc/internal/property-value/api/grpc.go index 176bd8f80..55ff8c124 100644 --- a/services/property-svc/internal/property-value/api/grpc.go +++ b/services/property-svc/internal/property-value/api/grpc.go @@ -1,14 +1,23 @@ package api import ( + "common" "context" + "errors" "fmt" + commonpb "gen/libs/common/v1" pb "gen/services/property_svc/v1" "hwes" + "hwgrpc" "hwutil" + "time" "github.com/google/uuid" + "github.com/jinzhu/copier" zlog "github.com/rs/zerolog/log" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/timestamppb" "property-svc/internal/property-value/handlers" @@ -69,42 +78,141 @@ func NewPropertyValueService(as hwes.AggregateStore, handlers *handlers.Handlers return &PropertyValueGrpcService{as: as, handlers: handlers} } -func (s *PropertyValueGrpcService) AttachPropertyValue( - ctx context.Context, - req *pb.AttachPropertyValueRequest, -) (*pb.AttachPropertyValueResponse, error) { - propertyValueID := uuid.New() - - propertyID := uuid.MustParse(req.GetPropertyId()) // guarded by validate - subjectID := uuid.MustParse(req.GetSubjectId()) // guarded by validate - - var value interface{} - switch req.Value.(type) { +func toTypedValueChange(value pb.IsAttachPropertyValueRequest_Value) (typedValue *models.TypedValueChange) { + if value == nil { + return &models.TypedValueChange{ + ValueRemoved: true, + } + } + switch value := value.(type) { case *pb.AttachPropertyValueRequest_TextValue: - value = req.GetTextValue() + return &models.TypedValueChange{ + TextValue: &value.TextValue, + } case *pb.AttachPropertyValueRequest_NumberValue: - value = req.GetNumberValue() + return &models.TypedValueChange{ + NumberValue: &value.NumberValue, + } case *pb.AttachPropertyValueRequest_BoolValue: - value = req.GetBoolValue() + return &models.TypedValueChange{ + BoolValue: &value.BoolValue, + } case *pb.AttachPropertyValueRequest_DateValue: - value = req.GetDateValue().GetDate() + return &models.TypedValueChange{ + DateValue: hwutil.PtrTo(value.DateValue.Date.AsTime()), + } case *pb.AttachPropertyValueRequest_DateTimeValue: - value = req.GetDateTimeValue() + return &models.TypedValueChange{ + DateTimeValue: hwutil.PtrTo(value.DateTimeValue.AsTime()), + } case *pb.AttachPropertyValueRequest_SelectValue: - value = req.GetSelectValue() + return &models.TypedValueChange{ + SingleSelectValue: &value.SelectValue, + } case *pb.AttachPropertyValueRequest_MultiSelectValue_: - msv := req.GetMultiSelectValue() - value = models.MultiSelectChange{ - SelectValues: msv.SelectValues, - RemoveSelectValues: msv.RemoveSelectValues, + msv := value.MultiSelectValue + return &models.TypedValueChange{ + MultiSelectValues: &models.MultiSelectChange{ + SelectValues: msv.SelectValues, + RemoveSelectValues: msv.RemoveSelectValues, + }, } default: - value = nil + return nil } +} - consistency, err := s.handlers.Commands.V1.AttachPropertyValue(ctx, propertyValueID, propertyID, value, subjectID) - if err != nil { - return nil, err +func (s *PropertyValueGrpcService) AttachPropertyValue( + ctx context.Context, + req *pb.AttachPropertyValueRequest, +) (*pb.AttachPropertyValueResponse, error) { + log := zlog.Ctx(ctx) + propertyValueID := uuid.New() + + propertyID := uuid.MustParse(req.GetPropertyId()) // guarded by validate + subjectID := uuid.MustParse(req.GetSubjectId()) // guarded by validate + + valueChange := toTypedValueChange(req.Value) + if valueChange == nil { + log.Error().Type("valueType", req.Value).Msg("req.ValueChange type is not known") + return nil, status.Error(codes.Internal, "failed to parse value") + } + + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + + var consistency common.ConsistencyToken + + for i := 0; true; i++ { + if i > 10 { + log.Warn().Msg("AttachPropertyValue: conflict circuit breaker triggered") + return nil, errors.New("failed conflict resolution") + } + + c, conflict, err := s.handlers.Commands.V1.AttachPropertyValue( + ctx, + propertyValueID, + propertyID, + *valueChange, + subjectID, + expConsistency, + ) + if err != nil { + return nil, err + } + consistency = c + + if conflict == nil { + break + } + conflicts := make(map[string]*commonpb.AttributeConflict) + + // TODO: find a generic approach + valueUpdateRequested := valueChange.ConflictPossible(conflict.Was.Value) + valueAlreadyUpdated := func() bool { + if conflict.Is == nil && conflict.Was == nil { + return false + } + if conflict.Is == nil || conflict.Was == nil { + return true + } + return !conflict.Is.Value.Equals(*conflict.Was.Value) + } + if valueUpdateRequested && valueAlreadyUpdated() { + var is proto.Message + if conflict.Is.Value != nil { + is = conflict.Is.Value.ToProtoMessage() + } + var want proto.Message + if conflict.Was.Value != nil { + var val models.SimpleTypedValue + if err := copier.CopyWithOption(&val, conflict.Was.Value, copier.Option{DeepCopy: true}); err != nil { + return nil, fmt.Errorf("could not copy was to want: %w", err) + } + valueChange.Apply(&val) + want = val.ToProtoMessage() + } + + conflicts["value"], err = hwgrpc.AttributeConflict( + is, + want, + ) + if err != nil { + return nil, err + } + } + + if len(conflicts) != 0 { + return &pb.AttachPropertyValueResponse{ + Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts}, + Consistency: consistency.String(), + }, nil + } + + // no conflict? retry with new consistency + expConsistency = &consistency } return &pb.AttachPropertyValueResponse{ @@ -137,63 +245,67 @@ func (s *PropertyValueGrpcService) GetAttachedPropertyValues( } return &pb.GetAttachedPropertyValuesResponse{ - Values: hwutil.Map( - propertiesWithValues, + Values: hwutil.Map(propertiesWithValues, func(pnv models.PropertyAndValue) *pb.GetAttachedPropertyValuesResponse_Value { res := &pb.GetAttachedPropertyValuesResponse_Value{ - PropertyId: pnv.PropertyID.String(), - FieldType: pnv.FieldType, - Name: pnv.Name, - Description: hwutil.MapIf(pnv.Description != "", pnv.Description, func(s string) string { return s }), + PropertyId: pnv.PropertyID.String(), + FieldType: pnv.FieldType, + Name: pnv.Name, + Description: hwutil.MapIf(pnv.Description != "", pnv.Description, + func(s string) string { return s }), IsArchived: pnv.IsArchived, Value: nil, PropertyConsistency: pnv.PropertyConsistency, ValueConsistency: pnv.ValueConsistency, } - switch { - case pnv.Value == nil: + + if pnv.Value == nil { return res - case pnv.Value.TextValue != nil: - res.Value = &pb.GetAttachedPropertyValuesResponse_Value_TextValue{TextValue: *pnv.Value.TextValue} - case pnv.Value.BoolValue != nil: - res.Value = &pb.GetAttachedPropertyValuesResponse_Value_BoolValue{BoolValue: *pnv.Value.BoolValue} - case pnv.Value.NumberValue != nil: - res.Value = &pb.GetAttachedPropertyValuesResponse_Value_NumberValue{NumberValue: *pnv.Value.NumberValue} - case len(pnv.Value.MultiSelectValues) != 0 && pnv.FieldType == pb.FieldType_FIELD_TYPE_SELECT: - v := pnv.Value.MultiSelectValues[0] - res.Value = &pb.GetAttachedPropertyValuesResponse_Value_SelectValue{ - SelectValue: &pb.GetAttachedPropertyValuesResponse_Value_SelectValueOption{ - Id: v.Id.String(), - Name: v.Name, - Description: v.Description, - }, - } - case len(pnv.Value.MultiSelectValues) != 0 && pnv.FieldType == pb.FieldType_FIELD_TYPE_MULTI_SELECT: - res.Value = &pb.GetAttachedPropertyValuesResponse_Value_MultiSelectValue_{ - MultiSelectValue: &pb.GetAttachedPropertyValuesResponse_Value_MultiSelectValue{ - SelectValues: hwutil.Map( - pnv.Value.MultiSelectValues, - func(o models.SelectValueOption) *pb.GetAttachedPropertyValuesResponse_Value_SelectValueOption { - return &pb.GetAttachedPropertyValuesResponse_Value_SelectValueOption{ + } + + switch val := pnv.Value.(type) { + case models.TextValue: + res.Value = &pb.GetAttachedPropertyValuesResponse_Value_TextValue{TextValue: string(val)} + case models.BoolValue: + res.Value = &pb.GetAttachedPropertyValuesResponse_Value_BoolValue{BoolValue: bool(val)} + case models.NumberValue: + res.Value = &pb.GetAttachedPropertyValuesResponse_Value_NumberValue{NumberValue: float64(val)} + case models.MultiSelectValues: + // TODO: use value encoding + if pnv.FieldType == pb.FieldType_FIELD_TYPE_SELECT { + v := val[0] + res.Value = &pb.GetAttachedPropertyValuesResponse_Value_SelectValue{ + SelectValue: &pb.SelectValueOption{ + Id: v.Id.String(), + Name: v.Name, + Description: v.Description, + }, + } + } else if pnv.FieldType == pb.FieldType_FIELD_TYPE_MULTI_SELECT { + res.Value = &pb.GetAttachedPropertyValuesResponse_Value_MultiSelectValue{ + MultiSelectValue: &pb.MultiSelectValue{ + SelectValues: hwutil.Map(val, func(o models.SelectValueOption) *pb.SelectValueOption { + return &pb.SelectValueOption{ Id: o.Id.String(), Name: o.Name, Description: o.Description, } }), - }, + }, + } } - case pnv.Value.DateTimeValue != nil: + case models.DateTimeValue: res.Value = &pb.GetAttachedPropertyValuesResponse_Value_DateTimeValue{ - DateTimeValue: timestamppb.New(*pnv.Value.DateTimeValue), + DateTimeValue: timestamppb.New(time.Time(val)), } - case pnv.Value.DateValue != nil: + case models.DateValue: res.Value = &pb.GetAttachedPropertyValuesResponse_Value_DateValue{ DateValue: &pb.Date{ - Date: timestamppb.New(*pnv.Value.DateValue), + Date: timestamppb.New(time.Time(val)), }, } default: - log.Error().Any("pnv", pnv).Msg("pnv.Value is in an invalid state!") + log.Error().Any("pnv", pnv).Msg("pnv.ValueChange is in an invalid state!") } return res }), diff --git a/services/property-svc/internal/property-value/commands/v1/attach_property_value.go b/services/property-svc/internal/property-value/commands/v1/attach_property_value.go index f8d759286..06f475762 100644 --- a/services/property-svc/internal/property-value/commands/v1/attach_property_value.go +++ b/services/property-svc/internal/property-value/commands/v1/attach_property_value.go @@ -9,6 +9,7 @@ import ( "github.com/google/uuid" "property-svc/internal/property-value/aggregate" + "property-svc/internal/property-value/models" "property-svc/repos/property_value_repo" ) @@ -16,18 +17,20 @@ type AttachPropertyValueCommandHandler func( ctx context.Context, propertyValueID uuid.UUID, propertyID uuid.UUID, - value interface{}, + valueChange models.TypedValueChange, subjectID uuid.UUID, -) (common.ConsistencyToken, error) + expConsistency *common.ConsistencyToken, +) (common.ConsistencyToken, *common.Conflict[*models.PropertyValue], error) func NewAttachPropertyValueCommandHandler(as hwes.AggregateStore) AttachPropertyValueCommandHandler { return func( ctx context.Context, propertyValueID uuid.UUID, propertyID uuid.UUID, - value interface{}, + valueChange models.TypedValueChange, subjectID uuid.UUID, - ) (common.ConsistencyToken, error) { + expConsistency *common.ConsistencyToken, + ) (common.ConsistencyToken, *common.Conflict[*models.PropertyValue], error) { propertyValueRepo := property_value_repo.New(hwdb.GetDB()) var a *aggregate.PropertyValueAggregate @@ -37,24 +40,44 @@ func NewAttachPropertyValueCommandHandler(as hwes.AggregateStore) AttachProperty SubjectID: subjectID, }) if err := hwdb.Error(ctx, err); err != nil { - return 0, err + return 0, nil, err } - if existingPropertyValueID != nil { - if a, err = aggregate.LoadPropertyValueAggregate(ctx, as, *existingPropertyValueID); err != nil { - return 0, err + // if no value exists yet, create one + if existingPropertyValueID == nil { + a = aggregate.NewPropertyValueAggregate(propertyValueID) + if err := a.CreatePropertyValue(ctx, propertyID, valueChange, subjectID); err != nil { + return 0, nil, err } - // TODO: update value will be triggered, even if the value is not the type the property defines - if err := a.UpdatePropertyValue(ctx, value); err != nil { - return 0, err + } else { // else, update the existing value + var snapshot *models.PropertyValue + a, snapshot, err = aggregate.LoadPropertyValueAggregateWithSnapshotAt( + ctx, + as, + *existingPropertyValueID, + expConsistency, + ) + if err != nil { + return 0, nil, err } - } else { - a = aggregate.NewPropertyValueAggregate(propertyValueID) - if err := a.CreatePropertyValue(ctx, propertyID, value, subjectID); err != nil { - return 0, err + + // conflict detection + consistency := common.ConsistencyToken(a.GetVersion()) + if expConsistency != nil && consistency != *expConsistency { + return consistency, &common.Conflict[*models.PropertyValue]{ + Was: snapshot, + Is: a.PropertyValue, + }, err + } + + // TODO: update value will be triggered, even if the value is not the type the property defines + + if err := a.UpdatePropertyValue(ctx, valueChange); err != nil { + return 0, nil, err } } - return as.Save(ctx, a) + consistency, err := as.Save(ctx, a) + return consistency, nil, err } } diff --git a/services/property-svc/internal/property-value/events/v1/events.go b/services/property-svc/internal/property-value/events/v1/events.go index 46613d3f9..e1297a80f 100644 --- a/services/property-svc/internal/property-value/events/v1/events.go +++ b/services/property-svc/internal/property-value/events/v1/events.go @@ -4,6 +4,8 @@ import ( "context" "hwes" + "property-svc/internal/property-value/models" + "github.com/google/uuid" ) @@ -13,10 +15,10 @@ const ( ) type PropertyValueCreatedEvent struct { - ID string `json:"id"` - PropertyID string `json:"property_id"` - Value interface{} `json:"value"` - SubjectID string `json:"subject_id"` + ID string `json:"id"` + PropertyID string `json:"property_id"` + ValueChange models.TypedValueChange `json:"value_change"` + SubjectID string `json:"subject_id"` } func NewPropertyValueCreatedEvent( @@ -24,25 +26,29 @@ func NewPropertyValueCreatedEvent( a hwes.Aggregate, id uuid.UUID, propertyID uuid.UUID, - value interface{}, + valueChange models.TypedValueChange, subjectID uuid.UUID, ) (hwes.Event, error) { payload := PropertyValueCreatedEvent{ - ID: id.String(), - PropertyID: propertyID.String(), - Value: value, - SubjectID: subjectID.String(), + ID: id.String(), + PropertyID: propertyID.String(), + ValueChange: valueChange, + SubjectID: subjectID.String(), } return hwes.NewEvent(a, PropertyValueCreated, hwes.WithData(payload), hwes.WithContext(ctx)) } type PropertyValueUpdatedEvent struct { - Value interface{} `json:"value"` + ValueChange models.TypedValueChange `json:"value_change"` } -func NewPropertyValueUpdatedEvent(ctx context.Context, a hwes.Aggregate, value interface{}) (hwes.Event, error) { +func NewPropertyValueUpdatedEvent( + ctx context.Context, + a hwes.Aggregate, + value models.TypedValueChange, +) (hwes.Event, error) { payload := PropertyValueUpdatedEvent{ - Value: value, + ValueChange: value, } return hwes.NewEvent(a, PropertyValueUpdated, hwes.WithData(payload), hwes.WithContext(ctx)) } diff --git a/services/property-svc/internal/property-value/models/propertyValue.go b/services/property-svc/internal/property-value/models/propertyValue.go index 69560b59f..30769e016 100644 --- a/services/property-svc/internal/property-value/models/propertyValue.go +++ b/services/property-svc/internal/property-value/models/propertyValue.go @@ -1,24 +1,26 @@ package models import ( - "errors" "fmt" + commonpb "gen/libs/common/v1" pb "gen/services/property_svc/v1" + "hwdb" "hwutil" "time" "github.com/google/uuid" + "github.com/jackc/pgx/v5/pgtype" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/timestamppb" + "google.golang.org/protobuf/types/known/wrapperspb" ) type PropertyValue struct { ID uuid.UUID PropertyID uuid.UUID SubjectID uuid.UUID - Value interface{} -} - -func NewPropertyValue() *PropertyValue { - return &PropertyValue{} + Value *SimpleTypedValue } type PropertyValueWithProperty struct { @@ -36,18 +38,105 @@ type PropertyValueWithProperty struct { } type SelectValueOption struct { - Id uuid.UUID - Name string - Description string + Id uuid.UUID `json:"id"` + Name string `json:"name"` + Description string `json:"description,omitempty"` } -type TypedValue struct { +type SimpleTypedValue struct { TextValue *string BoolValue *bool NumberValue *float64 - MultiSelectValues []SelectValueOption DateTimeValue *time.Time DateValue *time.Time + SingleSelectValue *string + MultiSelectValues []string +} + +func (v SimpleTypedValue) Equals(o SimpleTypedValue) bool { + switch { + case v.TextValue != nil && o.TextValue != nil: + return *v.TextValue == *o.TextValue + case v.BoolValue != nil && o.BoolValue != nil: + return *v.BoolValue == *o.BoolValue + case v.NumberValue != nil && o.NumberValue != nil: + return *v.NumberValue == *o.NumberValue + case v.DateTimeValue != nil && o.DateTimeValue != nil: + return *v.DateTimeValue == *o.DateTimeValue + case v.DateValue != nil && o.DateValue != nil: + return *v.DateValue == *o.DateValue + case v.SingleSelectValue != nil && o.SingleSelectValue != nil: + return *v.SingleSelectValue == *o.SingleSelectValue + case v.MultiSelectValues != nil && o.MultiSelectValues != nil: + return hwutil.SameItems(v.MultiSelectValues, o.MultiSelectValues) + default: + return false + } +} + +func (v SimpleTypedValue) ToProtoMessage() proto.Message { + switch { + case v.TextValue != nil: + return wrapperspb.String(*v.TextValue) + case v.BoolValue != nil: + return wrapperspb.Bool(*v.BoolValue) + case v.NumberValue != nil: + return wrapperspb.Double(*v.NumberValue) + case v.DateTimeValue != nil: + return timestamppb.New(*v.DateTimeValue) + case v.DateValue != nil: + return &pb.Date{Date: timestamppb.New(*v.DateValue)} + case v.SingleSelectValue != nil: + return wrapperspb.String(*v.SingleSelectValue) + case v.MultiSelectValues != nil: + els, err := hwutil.MapWithErr(v.MultiSelectValues, func(o string) (*anypb.Any, error) { + return anypb.New(wrapperspb.String(o)) + }) + if err != nil { + panic("SimpleTypedValue.ToProtoMessage: could not create anypb of string") + } + return &commonpb.AnyArray{Elements: els} + default: + panic(fmt.Sprintf("SimpleTypedValue.ToProtoMessage: unhandled state: %v", v)) + } +} + +// TypedValue is a poor man's enum +type TypedValue interface { + isTypedValue() +} + +type TextValue string + +func (v TextValue) isTypedValue() {} + +type BoolValue bool + +func (v BoolValue) isTypedValue() {} + +type NumberValue float64 + +func (v NumberValue) isTypedValue() {} + +type DateTimeValue time.Time + +func (v DateTimeValue) isTypedValue() {} + +type DateValue time.Time + +func (v DateValue) isTypedValue() {} + +type SingleSelectValue SelectValueOption + +func (v SingleSelectValue) isTypedValue() {} + +type MultiSelectValues []SelectValueOption + +func (v MultiSelectValues) isTypedValue() {} + +type MultiSelectChange struct { + SelectValues []string `json:"select_values,omitempty"` + RemoveSelectValues []string `json:"remove_select_values,omitempty"` } type PropertyAndValue struct { @@ -64,57 +153,102 @@ type PropertyAndValue struct { PropertyConsistency string ValueConsistency *string - Value *TypedValue + Value TypedValue } -type MultiSelectChange struct { - SelectValues []string - RemoveSelectValues []string +type TypedValueChange struct { + ValueRemoved bool `json:"value_removed,omitempty"` + TextValue *string `json:"text_value,omitempty"` + BoolValue *bool `json:"bool_value,omitempty"` + NumberValue *float64 `json:"number_value,omitempty"` + DateTimeValue *time.Time `json:"date_time_value,omitempty"` + DateValue *time.Time `json:"date_value,omitempty"` + SingleSelectValue *string `json:"single_select_value,omitempty"` + MultiSelectValues *MultiSelectChange `json:"multi_select_values,omitempty"` } -func interfaceToStringSlice(interf interface{}) ([]string, error) { - slice, ok := interf.([]interface{}) - if !ok { - return nil, errors.New("value is not a slice") - } +func applyMultiSelectValueChange(options []string, change MultiSelectChange) []string { + return append( + hwutil.Without(options, change.RemoveSelectValues), // remove first + change.SelectValues..., // add new options second + ) +} - strings, ok := hwutil.InterfacesToStrings(slice) - if !ok { - return nil, errors.New("value is not a []string") +// Apply applies a TypedValueChange to a TypedValue (except removal) +func (c TypedValueChange) Apply(value *SimpleTypedValue) bool { + switch { + case c.TextValue != nil: + value.TextValue = c.TextValue + case c.NumberValue != nil: + value.NumberValue = c.NumberValue + case c.BoolValue != nil: + value.BoolValue = c.BoolValue + case c.DateValue != nil: + value.DateValue = c.DateValue + case c.DateTimeValue != nil: + value.DateTimeValue = c.DateTimeValue + case c.SingleSelectValue != nil: + value.SingleSelectValue = c.SingleSelectValue + case c.MultiSelectValues != nil: + value.MultiSelectValues = applyMultiSelectValueChange(value.MultiSelectValues, *c.MultiSelectValues) + + default: + return false } - return strings, nil + + return true } -func MultiSelectChangeFromMap(m map[string]interface{}) (MultiSelectChange, error) { - self := MultiSelectChange{} - if m["SelectValues"] == nil { - self.SelectValues = []string{} - } else { - selectValues, err := interfaceToStringSlice(m["SelectValues"]) - if err != nil { - return MultiSelectChange{}, fmt.Errorf("MultiSelectChangeFromMap: could not parse \"SelectValues\": %w", err) - } - self.SelectValues = selectValues - } +type BasicChangeSettable interface { + SetTextValue(value *string) + SetNumberValue(value *float64) + SetBoolValue(value *bool) + SetDateValue(value pgtype.Date) + SetDateTimeValue(value pgtype.Timestamp) +} - if m["RemoveSelectValues"] == nil { - self.RemoveSelectValues = []string{} - } else { - removeSelectValues, err := interfaceToStringSlice(m["RemoveSelectValues"]) - if err != nil { - return MultiSelectChange{}, fmt.Errorf("MultiSelectChangeFromMap: could not parse \"RemoveSelectValues\": %w", err) - } - self.RemoveSelectValues = removeSelectValues +func (c TypedValueChange) SetBasicValues(settable BasicChangeSettable) bool { + switch { + case c.TextValue != nil: + settable.SetTextValue(c.TextValue) + case c.NumberValue != nil: + settable.SetNumberValue(c.NumberValue) + case c.BoolValue != nil: + settable.SetBoolValue(c.BoolValue) + case c.DateValue != nil: + settable.SetDateValue(hwdb.TimeToDate(*c.DateValue)) + case c.DateTimeValue != nil: + settable.SetDateTimeValue(hwdb.TimeToTimestamp(*c.DateTimeValue)) + default: + return false } - return self, nil + return true } -func MultiSelectChangeFromInterface(value interface{}) (MultiSelectChange, error) { - m, ok := value.(map[string]interface{}) - if !ok { - return MultiSelectChange{}, errors.New("MultiSelectChangeFromInterface: value is not a map") +func (c TypedValueChange) ConflictPossible(value *SimpleTypedValue) bool { + if value == nil { + return !c.ValueRemoved } - return MultiSelectChangeFromMap(m) + switch { + case c.ValueRemoved: + return false // no conflict possible + case c.TextValue != nil: + return value.TextValue != nil && *c.TextValue != *value.TextValue + case c.BoolValue != nil: + return value.BoolValue != nil && *c.BoolValue != *value.BoolValue + case c.NumberValue != nil: + return value.NumberValue != nil && *c.NumberValue != *value.NumberValue + case c.DateValue != nil: + return value.DateValue != nil && *c.DateValue != *value.DateValue + case c.DateTimeValue != nil: + return value.DateTimeValue != nil && *c.DateTimeValue != *value.DateTimeValue + case c.SingleSelectValue != nil: + return value.SingleSelectValue != nil && *c.SingleSelectValue != *value.SingleSelectValue + case c.MultiSelectValues != nil: + return false // no conflict possible + default: + panic(fmt.Sprintf("TypedValueChange.ConflictPossible: value unknown: %v", c)) + } } diff --git a/services/property-svc/internal/property-value/projections/property_value_postgres_projection/property_value_postgres_projection.go b/services/property-svc/internal/property-value/projections/property_value_postgres_projection/property_value_postgres_projection.go index 8d8f74f15..3394ceeed 100644 --- a/services/property-svc/internal/property-value/projections/property_value_postgres_projection/property_value_postgres_projection.go +++ b/services/property-svc/internal/property-value/projections/property_value_postgres_projection/property_value_postgres_projection.go @@ -2,17 +2,16 @@ package property_value_postgres_projection import ( "context" - "errors" "fmt" - pb "gen/services/property_svc/v1" "hwdb" "hwes" "hwes/eventstoredb/projections/custom" "hwutil" + zlog "github.com/rs/zerolog/log" + "github.com/EventStore/EventStore-Client-Go/v4/esdb" "github.com/google/uuid" - zlog "github.com/rs/zerolog/log" "property-svc/internal/property-value/aggregate" propertyValueEventsV1 "property-svc/internal/property-value/events/v1" @@ -58,9 +57,7 @@ func (p *Projection) onPropertyValueCreated(ctx context.Context, evt hwes.Event) return err, hwutil.PtrTo(esdb.NackActionPark) } - if payload.Value == nil { - return errors.New("onPropertyValueCreated: payload is empty"), hwutil.PtrTo(esdb.NackActionPark) - } + valueChange := payload.ValueChange propertyID, err := uuid.Parse(payload.PropertyID) if err != nil { @@ -72,16 +69,7 @@ func (p *Projection) onPropertyValueCreated(ctx context.Context, evt hwes.Event) return err, hwutil.PtrTo(esdb.NackActionPark) } - // GetProperty for the fieldType - property, err := hwdb.Optional(p.propertyRepo.GetPropertyById)(ctx, propertyID) - if property == nil { - return fmt.Errorf("property with id %s not found for propertyValue", payload.PropertyID), - hwutil.PtrTo(esdb.NackActionRetry) - } - if err := hwdb.Error(ctx, err); err != nil { - return err, hwutil.PtrTo(esdb.NackActionRetry) - } - fieldType := (pb.FieldType)(property.FieldType) + // Start TX tx, rollback, err := hwdb.BeginTx(p.db, ctx) if err != nil { @@ -91,38 +79,30 @@ func (p *Projection) onPropertyValueCreated(ctx context.Context, evt hwes.Event) repo := p.propertyValueRepo.WithTx(tx) - err, ack := createBasicPropertyValue(ctx, evt, repo, payload, propertyID, evt.AggregateID, subjectID, fieldType) + // first create a new value, this will also immediately store the value + // for basic types (e.g., text, number, bool, ...) + err, ack := createBasicPropertyValue(ctx, evt, repo, valueChange, propertyID, evt.AggregateID, subjectID) if err != nil { return fmt.Errorf("onPropertyValueCreated: could not createbasicPropertyValue: %w", err), ack } - if fieldType == pb.FieldType_FIELD_TYPE_SELECT || fieldType == pb.FieldType_FIELD_TYPE_MULTI_SELECT { + // for selects we are going to add options into the appropriate tables as well + isSingleSelectChange := valueChange.SingleSelectValue != nil + isMultiSelectChange := valueChange.MultiSelectValues != nil + + if isSingleSelectChange || isMultiSelectChange { var selectsToAdd []property_value_repo.ConnectValueWithSelectOptionsParams - if fieldType == pb.FieldType_FIELD_TYPE_SELECT { - val, ok := payload.Value.(string) - if !ok { - return errors.New("could not assert string"), hwutil.PtrTo(esdb.NackActionPark) - } - id, err := uuid.Parse(val) + if isSingleSelectChange { + id, err := uuid.Parse(*valueChange.SingleSelectValue) if err != nil { - return err, hwutil.PtrTo(esdb.NackActionPark) + return fmt.Errorf("option change is not a uuid: %w", err), hwutil.PtrTo(esdb.NackActionSkip) } selectsToAdd = []property_value_repo.ConnectValueWithSelectOptionsParams{ {ValueID: evt.AggregateID, SelectOption: id}, } - } else { - // FieldType_FIELD_TYPE_MULTI_SELECT - multiSelectChange, err := models.MultiSelectChangeFromInterface(payload.Value) - if err != nil { - log.Error(). - Err(err). - Type("value_type", payload.Value). - Any("value", payload.Value). - Msg("onPropertyValueCreated: could not parse payload.Value as MultiSelectChange") - return fmt.Errorf("onPropertyValueCreated: could not parse payload.Value as MultiSelectChange: %w", err), - hwutil.PtrTo(esdb.NackActionPark) - } + } else { // isMultiSelectChange + multiSelectChange := payload.ValueChange.MultiSelectValues ids, err := hwutil.StringsToUUIDs(multiSelectChange.SelectValues) if err != nil { return fmt.Errorf("onPropertyValueCreated: at least one select option uuid could not be parsed: %w", err), @@ -143,6 +123,7 @@ func (p *Projection) onPropertyValueCreated(ctx context.Context, evt hwes.Event) } } + // Commit if err := tx.Commit(ctx); err != nil { return fmt.Errorf("could not commit transaction: %w", err), hwutil.PtrTo(esdb.NackActionRetry) } @@ -155,11 +136,10 @@ func createBasicPropertyValue( ctx context.Context, evt hwes.Event, repo *property_value_repo.Queries, - payload propertyValueEventsV1.PropertyValueCreatedEvent, + valueChange models.TypedValueChange, propertyID, aggregateID, subjectID uuid.UUID, - fieldType pb.FieldType, ) (error, *esdb.NackAction) { createPropertyValueParams := property_value_repo.CreateBasicPropertyValueParams{ ID: aggregateID, @@ -168,35 +148,11 @@ func createBasicPropertyValue( Consistency: int64(evt.GetVersion()), //nolint:gosec } - switch { - case fieldType == pb.FieldType_FIELD_TYPE_TEXT: - createPropertyValueParams.TextValue = hwutil.PtrTo(fmt.Sprintf("%v", payload.Value)) - case fieldType == pb.FieldType_FIELD_TYPE_NUMBER: - val, ok := payload.Value.(float64) - if !ok { - return errors.New("could not assert number"), hwutil.PtrTo(esdb.NackActionPark) - } - createPropertyValueParams.NumberValue = &val - case fieldType == pb.FieldType_FIELD_TYPE_CHECKBOX: - val, ok := payload.Value.(bool) - if !ok { - return errors.New("could not assert bool"), hwutil.PtrTo(esdb.NackActionPark) - } - createPropertyValueParams.BoolValue = &val - case fieldType == pb.FieldType_FIELD_TYPE_DATE: - val, err := hwutil.AssertTimestampToTime(payload.Value) - if err != nil { - return err, hwutil.PtrTo(esdb.NackActionPark) - } - createPropertyValueParams.DateValue = hwdb.TimeToDate(*val) - case fieldType == pb.FieldType_FIELD_TYPE_DATE_TIME: - val, err := hwutil.AssertTimestampToTime(payload.Value) - if err != nil { - return err, hwutil.PtrTo(esdb.NackActionPark) - } - createPropertyValueParams.DateTimeValue = hwdb.TimeToTimestamp(*val) - } + _ = valueChange.SetBasicValues(&createPropertyValueParams) + // do nothing, if nothing was set, we will create the property anyway, + // we are going to add options to it later in the handler + // create value err := repo.CreateBasicPropertyValue(ctx, createPropertyValueParams) if err := hwdb.Error(ctx, err); err != nil { return err, hwutil.PtrTo(esdb.NackActionRetry) @@ -214,136 +170,116 @@ func (p *Projection) onPropertyValueUpdated(ctx context.Context, evt hwes.Event) return err, hwutil.PtrTo(esdb.NackActionPark) } - // Get Property for FieldType - propertyValue, err := hwdb.Optional(p.propertyValueRepo.GetPropertyValueByID)(ctx, evt.AggregateID) - if propertyValue == nil { - return fmt.Errorf("propertyValue with id %s not found", evt.AggregateID), hwutil.PtrTo(esdb.NackActionRetry) - } - if err := hwdb.Error(ctx, err); err != nil { - return err, hwutil.PtrTo(esdb.NackActionRetry) - } - - property, err := hwdb.Optional(p.propertyRepo.GetPropertyById)(ctx, propertyValue.PropertyID) - if property == nil { - return fmt.Errorf("property with id %s not found for propertyValue", propertyValue.PropertyID.String()), - hwutil.PtrTo(esdb.NackActionRetry) - } - if err := hwdb.Error(ctx, err); err != nil { - return err, hwutil.PtrTo(esdb.NackActionRetry) - } - - fieldType := (pb.FieldType)(property.FieldType) + valueChange := payload.ValueChange - switch { - case payload.Value == nil: + if valueChange.ValueRemoved { // Delete PropertyValue err := p.propertyValueRepo.DeletePropertyValue(ctx, evt.AggregateID) if err := hwdb.Error(ctx, err); err != nil { return err, hwutil.PtrTo(esdb.NackActionRetry) } - case fieldType == pb.FieldType_FIELD_TYPE_SELECT || fieldType == pb.FieldType_FIELD_TYPE_MULTI_SELECT: - tx, rollback, err := hwdb.BeginTx(p.db, ctx) + return nil, nil + } + + isSingleSelectUpdate := valueChange.SingleSelectValue != nil + isMultiSelectUpdate := valueChange.MultiSelectValues != nil + + if isSingleSelectUpdate || isMultiSelectUpdate { + return updateSelectPropertyValue(ctx, p.db, evt, valueChange) + } + + return updateBasicPropertyValue(ctx, evt, p.propertyValueRepo, valueChange) +} + +func updateSelectPropertyValue( + ctx context.Context, + db hwdb.DBTX, + evt hwes.Event, + valueChange models.TypedValueChange, +) (error, *esdb.NackAction) { + aggregateID := evt.AggregateID + + tx, rollback, err := hwdb.BeginTx(db, ctx) + if err != nil { + return fmt.Errorf("could not start tx: %w", err), hwutil.PtrTo(esdb.NackActionRetry) + } + defer rollback() + + propertyValueRepo := property_value_repo.New(tx) + + var toAdd []uuid.UUID + if valueChange.SingleSelectValue != nil { + parsedID, err := uuid.Parse(*valueChange.SingleSelectValue) if err != nil { - return fmt.Errorf("could not start tx: %w", err), hwutil.PtrTo(esdb.NackActionRetry) + return err, hwutil.PtrTo(esdb.NackActionPark) } - defer rollback() - - propertyValueRepo := p.propertyValueRepo.WithTx(tx) - - var toAdd []uuid.UUID - if fieldType == pb.FieldType_FIELD_TYPE_SELECT { - val, ok := payload.Value.(string) - if !ok { - err = fmt.Errorf( - "onPropertyValueUpdated: could not get select value: type is %T, expected string", - payload.Value, - ) - return err, hwutil.PtrTo(esdb.NackActionPark) - } - parsedID, err := uuid.Parse(val) - if err != nil { - return err, hwutil.PtrTo(esdb.NackActionPark) - } - toAdd = []uuid.UUID{parsedID} + toAdd = []uuid.UUID{parsedID} - // delete any other connection - err = propertyValueRepo.DisconnectValueFromAllSelectOptions(ctx, evt.AggregateID) - if err != nil { - return fmt.Errorf("onPropertyValueUpdated: could not disconnectvalue from all options: %w", err), - hwutil.PtrTo(esdb.NackActionRetry) - } - } else { - val, err := models.MultiSelectChangeFromInterface(payload.Value) - if err != nil { - log.Error(). - Err(err). - Type("value_type", payload.Value). - Any("value", payload.Value). - Msg("onPropertyValueUpdated: could not parse payload.Value as MultiSelectChange") - return fmt.Errorf("onPropertyValueUpdated: could not parse payload.Value as MultiSelectChange: %w", err), - hwutil.PtrTo(esdb.NackActionPark) - } + // delete any other connection + err = propertyValueRepo.DisconnectValueFromAllSelectOptions(ctx, aggregateID) + if err != nil { + return fmt.Errorf("onPropertyValueUpdated: could not disconnectvalue from all options: %w", err), + hwutil.PtrTo(esdb.NackActionRetry) + } + } else if valueChange.MultiSelectValues != nil { + val := *valueChange.MultiSelectValues + + toAdd, err = hwutil.StringsToUUIDs(val.SelectValues) + if err != nil { + return fmt.Errorf("onPropertyValueUpdated: could not parse SelectValues: %w", err), + hwutil.PtrTo(esdb.NackActionPark) + } - toAdd, err = hwutil.StringsToUUIDs(val.SelectValues) + // delete requested options + if len(val.RemoveSelectValues) != 0 { + arr, err := hwutil.MapWithErr(val.RemoveSelectValues, + func(s string) (property_value_repo.DisconnectValueFromSelectOptionsParams, error) { + id, err := uuid.Parse(s) + if err != nil { + return property_value_repo.DisconnectValueFromSelectOptionsParams{}, err + } + return property_value_repo.DisconnectValueFromSelectOptionsParams{ + ValueID: aggregateID, + SelectOption: id, + }, nil + }) if err != nil { - return fmt.Errorf("onPropertyValueUpdated: could not parse SelectValues: %w", err), + return fmt.Errorf("onPropertyValueUpdated: could not parse RemoveSelectValues: %w", err), hwutil.PtrTo(esdb.NackActionPark) } - - // delete requested options - if len(val.RemoveSelectValues) != 0 { - arr, err := hwutil.MapWithErr( - val.RemoveSelectValues, - func(s string) (property_value_repo.DisconnectValueFromSelectOptionsParams, error) { - id, err := uuid.Parse(s) - if err != nil { - return property_value_repo.DisconnectValueFromSelectOptionsParams{}, err - } - return property_value_repo.DisconnectValueFromSelectOptionsParams{ - ValueID: evt.AggregateID, - SelectOption: id, - }, nil - }) - if err != nil { - return fmt.Errorf("onPropertyValueUpdated: could not parse RemoveSelectValues: %w", err), - hwutil.PtrTo(esdb.NackActionPark) - } - if err := hwdb.ExecBatch(propertyValueRepo.DisconnectValueFromSelectOptions(ctx, arr)); err != nil { - return fmt.Errorf("onPropertyValueUpdated: could not disconnect desired options: %w", err), - hwutil.PtrTo(esdb.NackActionRetry) - } + if err := hwdb.ExecBatch(propertyValueRepo.DisconnectValueFromSelectOptions(ctx, arr)); err != nil { + return fmt.Errorf("onPropertyValueUpdated: could not disconnect desired options: %w", err), + hwutil.PtrTo(esdb.NackActionRetry) } } + } - // add new connection - args := hwutil.Map(toAdd, func(id uuid.UUID) property_value_repo.ConnectValueWithSelectOptionsParams { - return property_value_repo.ConnectValueWithSelectOptionsParams{ - ValueID: evt.AggregateID, - SelectOption: id, - } - }) - if err := hwdb.ExecBatch(propertyValueRepo.ConnectValueWithSelectOptions(ctx, args)); err != nil { - return fmt.Errorf("onPropertyValueUpdated: could not connect select options: %w", err), - hwutil.PtrTo(esdb.NackActionRetry) + // add new connection + args := hwutil.Map(toAdd, func(id uuid.UUID) property_value_repo.ConnectValueWithSelectOptionsParams { + return property_value_repo.ConnectValueWithSelectOptionsParams{ + ValueID: evt.AggregateID, + SelectOption: id, } + }) + if err := hwdb.ExecBatch(propertyValueRepo.ConnectValueWithSelectOptions(ctx, args)); err != nil { + return fmt.Errorf("onPropertyValueUpdated: could not connect select options: %w", err), + hwutil.PtrTo(esdb.NackActionRetry) + } - // update consistency - err = propertyValueRepo.UpdatePropertyValueByID(ctx, property_value_repo.UpdatePropertyValueByIDParams{ - ID: evt.AggregateID, - Consistency: int64(evt.GetVersion()), //nolint:gosec - }) - if err := hwdb.Error(ctx, err); err != nil { - return fmt.Errorf("onPropertyValueUpdated: could not update consistency of value: %w", err), - hwutil.PtrTo(esdb.NackActionRetry) - } + // update consistency + err = propertyValueRepo.UpdatePropertyValueByID(ctx, property_value_repo.UpdatePropertyValueByIDParams{ + ID: evt.AggregateID, + Consistency: int64(evt.GetVersion()), //nolint:gosec + }) + if err := hwdb.Error(ctx, err); err != nil { + return fmt.Errorf("onPropertyValueUpdated: could not update consistency of value: %w", err), + hwutil.PtrTo(esdb.NackActionRetry) + } - if err := tx.Commit(ctx); err != nil { - return fmt.Errorf("onPropertyValueUpdated: could not commit tx: %w", err), - hwutil.PtrTo(esdb.NackActionRetry) - } - default: - return updateBasicPropertyValue(ctx, evt, p.propertyValueRepo, fieldType, evt.AggregateID, payload) + if err := tx.Commit(ctx); err != nil { + return fmt.Errorf("onPropertyValueUpdated: could not commit tx: %w", err), + hwutil.PtrTo(esdb.NackActionRetry) } return nil, nil } @@ -353,44 +289,17 @@ func updateBasicPropertyValue( ctx context.Context, evt hwes.Event, repo *property_value_repo.Queries, - fieldType pb.FieldType, - aggregateID uuid.UUID, - payload propertyValueEventsV1.PropertyValueUpdatedEvent, + valueChange models.TypedValueChange, ) (error, *esdb.NackAction) { + aggregateID := evt.AggregateID + updatePropertyValueParams := property_value_repo.UpdatePropertyValueByIDParams{ ID: aggregateID, Consistency: int64(evt.GetVersion()), //nolint:gosec } - switch { - case fieldType == pb.FieldType_FIELD_TYPE_TEXT: - updatePropertyValueParams.TextValue = hwutil.PtrTo(fmt.Sprintf("%v", payload.Value)) - case fieldType == pb.FieldType_FIELD_TYPE_NUMBER: - val, ok := payload.Value.(float64) - if !ok { - return errors.New("could not assert number"), hwutil.PtrTo(esdb.NackActionPark) - } - updatePropertyValueParams.NumberValue = &val - case fieldType == pb.FieldType_FIELD_TYPE_CHECKBOX: - val, ok := payload.Value.(bool) - if !ok { - return errors.New("could not assert bool"), hwutil.PtrTo(esdb.NackActionPark) - } - updatePropertyValueParams.BoolValue = &val - case fieldType == pb.FieldType_FIELD_TYPE_DATE: - val, err := hwutil.AssertTimestampToTime(payload.Value) - if err != nil { - return err, hwutil.PtrTo(esdb.NackActionPark) - } - updatePropertyValueParams.DateValue = hwdb.TimeToDate(*val) - case fieldType == pb.FieldType_FIELD_TYPE_DATE_TIME: - val, err := hwutil.AssertTimestampToTime(payload.Value) - if err != nil { - return err, hwutil.PtrTo(esdb.NackActionPark) - } - updatePropertyValueParams.DateTimeValue = hwdb.TimeToTimestamp(*val) - default: - return fmt.Errorf("updateBasicPropertyValue called with fieldType %s", fieldType.String()), + if done := valueChange.SetBasicValues(&updatePropertyValueParams); !done { + return fmt.Errorf("updateBasicPropertyValue: could not set setBasicFromChange: %v", valueChange), hwutil.PtrTo(esdb.NackActionPark) } diff --git a/services/property-svc/internal/property-value/queries/v1/get_property_values_by_subject_id.go b/services/property-svc/internal/property-value/queries/v1/get_property_values_by_subject_id.go index ae0e01fcc..6a73eafff 100644 --- a/services/property-svc/internal/property-value/queries/v1/get_property_values_by_subject_id.go +++ b/services/property-svc/internal/property-value/queries/v1/get_property_values_by_subject_id.go @@ -8,10 +8,9 @@ import ( "hwdb" "hwes" "hwutil" - "time" "github.com/google/uuid" - "github.com/jackc/pgx/v5/pgtype" + "github.com/rs/zerolog/log" "property-svc/internal/property-value/models" vh "property-svc/internal/property-view/handlers" @@ -87,39 +86,36 @@ func NewGetRelevantPropertyValuesQueryHandler(as hwes.AggregateStore) GetRelevan if row.SelectOptionID.Valid { // make sure MultiSelectValues is an array if properties[row.Property.ID].Value == nil { - properties[row.Property.ID].Value = &models.TypedValue{ - TextValue: nil, - BoolValue: nil, - NumberValue: nil, - MultiSelectValues: make([]models.SelectValueOption, 0), - DateTimeValue: nil, - } + properties[row.Property.ID].Value = models.MultiSelectValues(make([]models.SelectValueOption, 0)) } // add multiselectvalue to array - properties[row.Property.ID].Value.MultiSelectValues = append( - properties[row.Property.ID].Value.MultiSelectValues, models.SelectValueOption{ - Id: row.SelectOptionID.UUID, // known to be valid by if - Name: *row.SelectOptionName, // known to be set due to NOT NULL and successful LEFT JOIN - Description: *row.SelectOptionDescription, // known to be set due to NOT NULL and successful LEFT JOIN - }) + arr := properties[row.Property.ID].Value.(models.MultiSelectValues) //nolint:forcetypeassert + arr = append(arr, models.SelectValueOption{ + Id: row.SelectOptionID.UUID, // known to be valid by if + Name: *row.SelectOptionName, // known to be set due to NOT NULL and successful LEFT JOIN + Description: *row.SelectOptionDescription, // known to be set due to NOT NULL and successful LEFT JOIN + }) + properties[row.Property.ID].Value = arr } else { // basic values can just be set, we expect only one of them to be not null, // but at least one has to due to ifs - properties[row.Property.ID].Value = &models.TypedValue{ - TextValue: row.TextValue, - BoolValue: row.BoolValue, - NumberValue: row.NumberValue, - MultiSelectValues: nil, - DateTimeValue: hwutil.MapIf( - row.DateTimeValue.Valid, - row.DateTimeValue, - func(dtV pgtype.Timestamp) time.Time { - return dtV.Time - }), - DateValue: hwutil.MapIf(row.DateValue.Valid, row.DateValue, func(dV pgtype.Date) time.Time { - return dV.Time - }), + + switch { + case row.TextValue != nil: + properties[row.Property.ID].Value = models.TextValue(*row.TextValue) + case row.BoolValue != nil: + properties[row.Property.ID].Value = models.BoolValue(*row.BoolValue) + case row.NumberValue != nil: + properties[row.Property.ID].Value = models.NumberValue(*row.NumberValue) + case row.DateValue.Valid: + properties[row.Property.ID].Value = models.DateValue(row.DateValue.Time) + case row.DateTimeValue.Valid: + properties[row.Property.ID].Value = models.DateTimeValue(row.DateTimeValue.Time) + default: + log.Warn().Interface("row", row).Msg("row is all nil, one case does not seem to be handled") + // if you are debugging the above log line, consider updating the "if" in the beginning + continue } } } diff --git a/services/property-svc/internal/property/aggregate/aggregate.go b/services/property-svc/internal/property/aggregate/aggregate.go index 7390cbb2d..99bcada55 100644 --- a/services/property-svc/internal/property/aggregate/aggregate.go +++ b/services/property-svc/internal/property/aggregate/aggregate.go @@ -1,6 +1,7 @@ package aggregate import ( + "common" "context" "fmt" pb "gen/services/property_svc/v1" @@ -8,6 +9,7 @@ import ( "hwutil" "github.com/google/uuid" + "github.com/jinzhu/copier" propertyEventsV1 "property-svc/internal/property/events/v1" "property-svc/internal/property/models" @@ -33,12 +35,34 @@ func NewPropertyAggregate(id uuid.UUID) *PropertyAggregate { return aggregate } -func LoadPropertyAggregate(ctx context.Context, as hwes.AggregateStore, id uuid.UUID) (*PropertyAggregate, error) { +func LoadPropertyAggregateWithSnapshotAt( + ctx context.Context, + as hwes.AggregateStore, + id uuid.UUID, + pauseAt *common.ConsistencyToken, +) (*PropertyAggregate, *models.Property, error) { property := NewPropertyAggregate(id) + + var snapshot *models.Property + + if pauseAt != nil { + // load pauseAt+1-many events (version is 0-indexed) + if err := as.LoadN(ctx, property, uint64(*pauseAt)+1); err != nil { + return nil, nil, err + } + + var cpy models.Property + if err := copier.CopyWithOption(&cpy, property.Property, copier.Option{DeepCopy: true}); err != nil { + return nil, nil, fmt.Errorf("LoadPropertyAggregateWithSnapshotAt: could not copy snapshot: %w", err) + } + snapshot = &cpy + } + + // continue loading all other events if err := as.Load(ctx, property); err != nil { - return nil, err + return nil, nil, err } - return property, nil + return property, snapshot, nil } func (a *PropertyAggregate) initEventListeners() { diff --git a/services/property-svc/internal/property/api/grpc.go b/services/property-svc/internal/property/api/grpc.go index 9f46367a4..2441feceb 100644 --- a/services/property-svc/internal/property/api/grpc.go +++ b/services/property-svc/internal/property/api/grpc.go @@ -1,12 +1,22 @@ package api import ( + "common" "context" + "errors" + commonpb "gen/libs/common/v1" pb "gen/services/property_svc/v1" "hwes" + "hwgrpc" "hwutil" + "slices" "github.com/google/uuid" + "github.com/rs/zerolog/log" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/wrapperspb" "property-svc/internal/property/handlers" "property-svc/internal/property/models" @@ -140,6 +150,11 @@ func (s *PropertyGrpcService) UpdateProperty( return nil, err } + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + var allowFreetext *bool var removeOptions []string var upsertOptions *[]models.UpdateSelectOption @@ -174,20 +189,176 @@ func (s *PropertyGrpcService) UpdateProperty( } } - consistency, err := s.handlers.Commands.V1.UpdateProperty( - ctx, - propertyID, - req.SubjectType, - req.Name, - req.Description, - req.SetId, - allowFreetext, - upsertOptions, - removeOptions, - req.IsArchived, - ) - if err != nil { - return nil, err + var consistency common.ConsistencyToken + + for i := 0; true; i++ { + if i > 10 { + log.Warn().Msg("UpdatePatient: conflict circuit breaker triggered") + return nil, errors.New("failed conflict resolution") + } + + c, conflict, err := s.handlers.Commands.V1.UpdateProperty( + ctx, + propertyID, + req.SubjectType, + req.Name, + req.Description, + req.SetId, + allowFreetext, + upsertOptions, + removeOptions, + req.IsArchived, + expConsistency, + ) + if err != nil { + return nil, err + } + consistency = c + if conflict == nil { + break + } + + conflicts := make(map[string]*commonpb.AttributeConflict) + + // TODO: find a generic approach + subjTypeUpdateRequested := req.SubjectType != nil && *req.SubjectType != conflict.Is.SubjectType + subjTypeAlreadyUpdated := conflict.Was.SubjectType != conflict.Is.SubjectType + if subjTypeUpdateRequested && subjTypeAlreadyUpdated { + conflicts["subject_type"], err = hwgrpc.AttributeConflict( + wrapperspb.Int32(int32(conflict.Is.SubjectType.Number())), + wrapperspb.Int32(int32(req.SubjectType.Number())), + ) + if err != nil { + return nil, err + } + } + + nameUpdateRequested := req.Name != nil && *req.Name != conflict.Is.Name + nameAlreadyUpdated := conflict.Was.Name != conflict.Is.Name + if nameUpdateRequested && nameAlreadyUpdated { + conflicts["name"], err = hwgrpc.AttributeConflict( + wrapperspb.String(conflict.Is.Name), + wrapperspb.String(*req.Name), + ) + if err != nil { + return nil, err + } + } + descrUpdateRequested := req.Description != nil && *req.Description != conflict.Is.Description + descrAlreadyUpdated := conflict.Was.Description != conflict.Is.Description + if descrUpdateRequested && descrAlreadyUpdated { + conflicts["description"], err = hwgrpc.AttributeConflict( + wrapperspb.String(conflict.Is.Description), + wrapperspb.String(*req.Description), + ) + if err != nil { + return nil, err + } + } + setIdUpdateRequested := req.SetId != nil && *req.SetId != conflict.Is.SetID.UUID.String() + setIdAlreadyUpdated := conflict.Was.SetID != conflict.Is.SetID + if setIdUpdateRequested && setIdAlreadyUpdated { + var is proto.Message + if conflict.Is.SetID.Valid { + is = wrapperspb.String(conflict.Is.SetID.UUID.String()) + } + + conflicts["set_id"], err = hwgrpc.AttributeConflict( + is, + wrapperspb.String(*req.SetId), + ) + if err != nil { + return nil, err + } + } + + fTDUpdateRequested := req.FieldTypeData != nil && req.GetSelectData() != nil // currently only select data is possible + if fTDUpdateRequested { + sd := req.GetSelectData() + + // boolean can not cause conflicts + + // removal can not cause conflicts + + // upsert can only cause conflicts if update (not insert) + + // nothing to check in the first place + if conflict.Is.FieldTypeData.SelectData == nil || len(conflict.Is.FieldTypeData.SelectData.SelectOptions) == 0 { + continue + } + + for _, upsertedOption := range sd.UpsertOptions { + if upsertedOption.Id == "" { + continue + } + + optionsWas := conflict.Was.FieldTypeData.SelectData.SelectOptions + optionsIs := conflict.Is.FieldTypeData.SelectData.SelectOptions + + searchFn := func(option models.SelectOption) bool { + return option.ID.String() == upsertedOption.Id + } + + // upsert is update, check if it was updated between WAS and IS + wasIx := slices.IndexFunc(optionsWas, searchFn) + if wasIx < 0 { + msg := "The option '%s' you attempted to update did not exist" + + " at the state the provided consistency points to. " + + "You likely provided an incorrect consistency token." + return nil, status.Errorf(codes.InvalidArgument, msg, upsertedOption.Id) + } + wasOpt := optionsWas[wasIx] + + isIx := slices.IndexFunc(optionsIs, searchFn) + if isIx < 0 { + // option was removed since, update will be ignored or cause an error, but will not cause a conflict + continue + } + isOpt := optionsIs[isIx] + + optNameUpdateRequested := upsertedOption.Name != nil && *upsertedOption.Name != isOpt.Name + optnameAlreadyUpdated := wasOpt.Name != isOpt.Name + if optNameUpdateRequested && optnameAlreadyUpdated { + conflicts["select_data.upsert_options."+upsertedOption.Id+".name"], err = hwgrpc.AttributeConflict( + wrapperspb.String(isOpt.Name), + wrapperspb.String(*upsertedOption.Name), + ) + if err != nil { + return nil, err + } + } + optDescUpdateRequested := upsertedOption.Description != nil && + (isOpt.Description == nil || *upsertedOption.Description != *isOpt.Description) + + optDescAlreadyUpdated := func() bool { + if wasOpt.Description != nil && isOpt.Description != nil { + return *wasOpt.Description != *isOpt.Description + } + + return !(wasOpt.Description == nil && isOpt.Description == nil) + } + + if optDescUpdateRequested && optDescAlreadyUpdated() { + conflicts["select_data.upsert_options."+upsertedOption.Id+".description"], err = hwgrpc.AttributeConflict( + wrapperspb.String(*isOpt.Description), + wrapperspb.String(*upsertedOption.Description), + ) + if err != nil { + return nil, err + } + } + } + } + + if len(conflicts) != 0 { + return &pb.UpdatePropertyResponse{ + Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts}, + Consistency: c.String(), + }, nil + } + + // no conflict? retry with new consistency + expConsistency = &c } return &pb.UpdatePropertyResponse{ diff --git a/services/property-svc/internal/property/commands/v1/update_property.go b/services/property-svc/internal/property/commands/v1/update_property.go index a06b1278b..e4a947b8d 100644 --- a/services/property-svc/internal/property/commands/v1/update_property.go +++ b/services/property-svc/internal/property/commands/v1/update_property.go @@ -25,7 +25,8 @@ type UpdatePropertyCommandHandler func( upsertOptions *[]models.UpdateSelectOption, removeOptions []string, isArchived *bool, -) (common.ConsistencyToken, error) + expConsistency *common.ConsistencyToken, +) (common.ConsistencyToken, *common.Conflict[*models.Property], error) func NewUpdatePropertyCommandHandler(as hwes.AggregateStore, authz hwauthz.AuthZ) UpdatePropertyCommandHandler { return func( @@ -39,43 +40,53 @@ func NewUpdatePropertyCommandHandler(as hwes.AggregateStore, authz hwauthz.AuthZ upsertOptions *[]models.UpdateSelectOption, removeOptions []string, isArchived *bool, - ) (common.ConsistencyToken, error) { + expConsistency *common.ConsistencyToken, + ) (common.ConsistencyToken, *common.Conflict[*models.Property], error) { user, err := perm.UserFromCtx(ctx) if err != nil { - return 0, err + return 0, nil, err } check := hwauthz.NewPermissionCheck(user, perm.PropertyCanUserUpdate, perm.Property(propertyID)) if err = authz.Must(ctx, check); err != nil { - return 0, err + return 0, nil, err } - a, err := aggregate.LoadPropertyAggregate(ctx, as, propertyID) + a, oldState, err := aggregate.LoadPropertyAggregateWithSnapshotAt(ctx, as, propertyID, expConsistency) if err != nil { - return 0, err + return 0, nil, err + } + + // update happened since? + newToken := common.ConsistencyToken(a.GetVersion()) + if expConsistency != nil && *expConsistency != newToken { + return newToken, &common.Conflict[*models.Property]{ + Was: oldState, + Is: a.Property, + }, nil } if subjectType != nil { if err := a.UpdateSubjectType(ctx, *subjectType); err != nil { - return 0, err + return 0, nil, err } } if name != nil { if err := a.UpdateName(ctx, *name); err != nil { - return 0, err + return 0, nil, err } } if description != nil { if err := a.UpdateDescription(ctx, *description); err != nil { - return 0, err + return 0, nil, err } } if setID != nil { if err := a.UpdateSetID(ctx, *setID); err != nil { - return 0, err + return 0, nil, err } } @@ -83,7 +94,7 @@ func NewUpdatePropertyCommandHandler(as hwes.AggregateStore, authz hwauthz.AuthZ if a.Property.FieldType == pb.FieldType_FIELD_TYPE_SELECT || a.Property.FieldType == pb.FieldType_FIELD_TYPE_MULTI_SELECT { if err := a.UpdateAllowFreetext(ctx, *allowFreetext); err != nil { - return 0, err + return 0, nil, err } } } @@ -92,7 +103,7 @@ func NewUpdatePropertyCommandHandler(as hwes.AggregateStore, authz hwauthz.AuthZ if a.Property.FieldType == pb.FieldType_FIELD_TYPE_SELECT || a.Property.FieldType == pb.FieldType_FIELD_TYPE_MULTI_SELECT { if err := a.FieldTypeDataUpsertOptions(ctx, *upsertOptions); err != nil { - return 0, err + return 0, nil, err } } } @@ -102,7 +113,7 @@ func NewUpdatePropertyCommandHandler(as hwes.AggregateStore, authz hwauthz.AuthZ if a.Property.FieldType == pb.FieldType_FIELD_TYPE_SELECT || a.Property.FieldType == pb.FieldType_FIELD_TYPE_MULTI_SELECT { if err := a.FieldTypeDataRemoveOptions(ctx, removeOptions); err != nil { - return 0, err + return 0, nil, err } } } @@ -110,15 +121,16 @@ func NewUpdatePropertyCommandHandler(as hwes.AggregateStore, authz hwauthz.AuthZ if isArchived != nil { if *isArchived { if err := a.ArchiveProperty(ctx); err != nil { - return 0, err + return 0, nil, err } } else { if err := a.RetrieveProperty(ctx); err != nil { - return 0, err + return 0, nil, err } } } - return as.Save(ctx, a) + consistency, err := as.Save(ctx, a) + return consistency, nil, err } } diff --git a/services/property-svc/internal/property/projections/postgres_projection/postgres_projection.go b/services/property-svc/internal/property/projections/postgres_projection/postgres_projection.go index 868c3fe79..d41c55425 100644 --- a/services/property-svc/internal/property/projections/postgres_projection/postgres_projection.go +++ b/services/property-svc/internal/property/projections/postgres_projection/postgres_projection.go @@ -73,6 +73,11 @@ func (p *Projection) initEventListeners() { func (p *Projection) onPropertyCreated(ctx context.Context, evt hwes.Event) (error, *esdb.NackAction) { log := zlog.Ctx(ctx) + organizationID := evt.OrganizationID + if organizationID == nil { + return errors.New("onPropertyCreated event is missing organizationID"), hwutil.PtrTo(esdb.NackActionSkip) + } + var payload propertyEventsV1.PropertyCreatedEvent if err := evt.GetJsonData(&payload); err != nil { log.Error().Err(err).Msg("unmarshal failed") @@ -100,11 +105,12 @@ func (p *Projection) onPropertyCreated(ctx context.Context, evt hwes.Event) (err // create query err = p.propertyRepo.CreateProperty(ctx, property_repo.CreatePropertyParams{ - ID: propertyID, - SubjectType: int32(subjectType), - FieldType: int32(fieldType), - Name: payload.Name, - Consistency: int64(evt.GetVersion()), //nolint:gosec + ID: propertyID, + SubjectType: int32(subjectType), + FieldType: int32(fieldType), + Name: payload.Name, + Consistency: int64(evt.GetVersion()), //nolint:gosec + OrganizationID: *organizationID, }) if err := hwdb.Error(ctx, err); err != nil { return err, hwutil.PtrTo(esdb.NackActionRetry) diff --git a/services/property-svc/internal/property/queries/v1/get_properties_by_subject_type.go b/services/property-svc/internal/property/queries/v1/get_properties_by_subject_type.go index b05039916..a4f6849d2 100644 --- a/services/property-svc/internal/property/queries/v1/get_properties_by_subject_type.go +++ b/services/property-svc/internal/property/queries/v1/get_properties_by_subject_type.go @@ -2,7 +2,9 @@ package v1 import ( "common" + "common/auth" "context" + "errors" pb "gen/services/property_svc/v1" "hwauthz" "hwdb" @@ -29,6 +31,11 @@ func NewGetPropertiesQueryHandler(authz hwauthz.AuthZ) GetPropertiesQueryHandler propertyRepo := property_repo.New(hwdb.GetDB()) + organizationID, err := auth.GetOrganizationID(ctx) + if err != nil { + return nil, errors.New("GetPropertiesQueryHandler called without organization in context") + } + var subjectTypeID *int32 if subjectType != nil { subjectTypeID = hwutil.PtrTo(int32(*subjectType)) @@ -37,7 +44,8 @@ func NewGetPropertiesQueryHandler(authz hwauthz.AuthZ) GetPropertiesQueryHandler rows, err := propertyRepo.GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrID( ctx, property_repo.GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrIDParams{ - SubjectType: subjectTypeID, + SubjectType: subjectTypeID, + OrganizationID: organizationID, }) if err := hwdb.Error(ctx, err); err != nil { return nil, err diff --git a/services/property-svc/internal/property/queries/v1/get_property_by_id.go b/services/property-svc/internal/property/queries/v1/get_property_by_id.go index 96ba2d0c9..49fdddc38 100644 --- a/services/property-svc/internal/property/queries/v1/get_property_by_id.go +++ b/services/property-svc/internal/property/queries/v1/get_property_by_id.go @@ -2,6 +2,7 @@ package v1 import ( "common" + "common/auth" "context" "fmt" pb "gen/services/property_svc/v1" @@ -35,10 +36,16 @@ func NewGetPropertyByIDQueryHandler(authz hwauthz.AuthZ) GetPropertyByIDQueryHan propertyRepo := property_repo.New(hwdb.GetDB()) + organizationID, err := auth.GetOrganizationID(ctx) + if err != nil { + return nil, 0, err + } + rows, err := propertyRepo.GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrID( ctx, property_repo.GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrIDParams{ - ID: uuid.NullUUID{UUID: propertyID, Valid: true}, + ID: uuid.NullUUID{UUID: propertyID, Valid: true}, + OrganizationID: organizationID, }) if err := hwdb.Error(ctx, err); err != nil { return nil, 0, err diff --git a/services/property-svc/migrations/000009_properties_organization.down.sql b/services/property-svc/migrations/000009_properties_organization.down.sql new file mode 100644 index 000000000..3a959ca3c --- /dev/null +++ b/services/property-svc/migrations/000009_properties_organization.down.sql @@ -0,0 +1 @@ +ALTER TABLE properties DROP COLUMN IF EXISTS organization_id; diff --git a/services/property-svc/migrations/000009_properties_organization.up.sql b/services/property-svc/migrations/000009_properties_organization.up.sql new file mode 100644 index 000000000..51abe5bdc --- /dev/null +++ b/services/property-svc/migrations/000009_properties_organization.up.sql @@ -0,0 +1,2 @@ +DELETE FROM properties; -- remove all rows, adding a new NOT NULL column without default +ALTER TABLE properties ADD COLUMN IF NOT EXISTS organization_id uuid NOT NULL; diff --git a/services/property-svc/repos/patient_views_repo/models.go b/services/property-svc/repos/patient_views_repo/models.go index 975bc7ac3..27133a465 100644 --- a/services/property-svc/repos/patient_views_repo/models.go +++ b/services/property-svc/repos/patient_views_repo/models.go @@ -21,15 +21,16 @@ type PatientPropertyViewRule struct { } type Property struct { - ID uuid.UUID - SubjectType int32 - FieldType int32 - Name string - Description string - IsArchived bool - SetID uuid.NullUUID - SelectDataID uuid.NullUUID - Consistency int64 + ID uuid.UUID + SubjectType int32 + FieldType int32 + Name string + Description string + IsArchived bool + SetID uuid.NullUUID + SelectDataID uuid.NullUUID + Consistency int64 + OrganizationID uuid.UUID } type PropertyValue struct { diff --git a/services/property-svc/repos/property_repo.sql b/services/property-svc/repos/property_repo.sql index 31a01a53b..cb14e7259 100644 --- a/services/property-svc/repos/property_repo.sql +++ b/services/property-svc/repos/property_repo.sql @@ -1,7 +1,7 @@ -- name: CreateProperty :exec INSERT INTO properties - (id, subject_type, field_type, name, consistency) -VALUES ($1, $2, $3, $4, $5); + (id, subject_type, field_type, name, consistency, organization_id) +VALUES ($1, $2, $3, $4, $5, $6); -- name: GetPropertyById :one SELECT * FROM properties WHERE id = $1; @@ -24,7 +24,9 @@ SELECT WHERE (subject_type = sqlc.narg('subject_type') OR sqlc.narg('subject_type') IS NULL ) AND - (properties.id = sqlc.narg('id') OR sqlc.narg('id') IS NULL); + (properties.id = sqlc.narg('id') OR sqlc.narg('id') IS NULL) + AND + properties.organization_id = @organization_id; -- name: UpdateProperty :exec UPDATE properties diff --git a/services/property-svc/repos/property_repo/models.go b/services/property-svc/repos/property_repo/models.go index 28a1f1ceb..dbc6ded18 100644 --- a/services/property-svc/repos/property_repo/models.go +++ b/services/property-svc/repos/property_repo/models.go @@ -21,15 +21,16 @@ type PatientPropertyViewRule struct { } type Property struct { - ID uuid.UUID - SubjectType int32 - FieldType int32 - Name string - Description string - IsArchived bool - SetID uuid.NullUUID - SelectDataID uuid.NullUUID - Consistency int64 + ID uuid.UUID + SubjectType int32 + FieldType int32 + Name string + Description string + IsArchived bool + SetID uuid.NullUUID + SelectDataID uuid.NullUUID + Consistency int64 + OrganizationID uuid.UUID } type PropertyValue struct { diff --git a/services/property-svc/repos/property_repo/property_repo.sql.go b/services/property-svc/repos/property_repo/property_repo.sql.go index ba34214fe..4f27c8107 100644 --- a/services/property-svc/repos/property_repo/property_repo.sql.go +++ b/services/property-svc/repos/property_repo/property_repo.sql.go @@ -13,16 +13,17 @@ import ( const createProperty = `-- name: CreateProperty :exec INSERT INTO properties - (id, subject_type, field_type, name, consistency) -VALUES ($1, $2, $3, $4, $5) + (id, subject_type, field_type, name, consistency, organization_id) +VALUES ($1, $2, $3, $4, $5, $6) ` type CreatePropertyParams struct { - ID uuid.UUID - SubjectType int32 - FieldType int32 - Name string - Consistency int64 + ID uuid.UUID + SubjectType int32 + FieldType int32 + Name string + Consistency int64 + OrganizationID uuid.UUID } func (q *Queries) CreateProperty(ctx context.Context, arg CreatePropertyParams) error { @@ -32,6 +33,7 @@ func (q *Queries) CreateProperty(ctx context.Context, arg CreatePropertyParams) arg.FieldType, arg.Name, arg.Consistency, + arg.OrganizationID, ) return err } @@ -77,7 +79,7 @@ func (q *Queries) CreateSelectOption(ctx context.Context, arg CreateSelectOption const getPropertiesWithSelectDataAndOptionsBySubjectTypeOrID = `-- name: GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrID :many SELECT - properties.id, properties.subject_type, properties.field_type, properties.name, properties.description, properties.is_archived, properties.set_id, properties.select_data_id, properties.consistency, + properties.id, properties.subject_type, properties.field_type, properties.name, properties.description, properties.is_archived, properties.set_id, properties.select_data_id, properties.consistency, properties.organization_id, select_options.id as select_option_id, select_options.name as select_option_name, select_options.description as select_option_description, @@ -91,11 +93,14 @@ SELECT (subject_type = $1 OR $1 IS NULL ) AND (properties.id = $2 OR $2 IS NULL) + AND + properties.organization_id = $3 ` type GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrIDParams struct { - SubjectType *int32 - ID uuid.NullUUID + SubjectType *int32 + ID uuid.NullUUID + OrganizationID uuid.UUID } type GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrIDRow struct { @@ -109,7 +114,7 @@ type GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrIDRow struct { } func (q *Queries) GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrID(ctx context.Context, arg GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrIDParams) ([]GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrIDRow, error) { - rows, err := q.db.Query(ctx, getPropertiesWithSelectDataAndOptionsBySubjectTypeOrID, arg.SubjectType, arg.ID) + rows, err := q.db.Query(ctx, getPropertiesWithSelectDataAndOptionsBySubjectTypeOrID, arg.SubjectType, arg.ID, arg.OrganizationID) if err != nil { return nil, err } @@ -127,6 +132,7 @@ func (q *Queries) GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrID(ctx con &i.Property.SetID, &i.Property.SelectDataID, &i.Property.Consistency, + &i.Property.OrganizationID, &i.SelectOptionID, &i.SelectOptionName, &i.SelectOptionDescription, @@ -145,7 +151,7 @@ func (q *Queries) GetPropertiesWithSelectDataAndOptionsBySubjectTypeOrID(ctx con } const getPropertyById = `-- name: GetPropertyById :one -SELECT id, subject_type, field_type, name, description, is_archived, set_id, select_data_id, consistency FROM properties WHERE id = $1 +SELECT id, subject_type, field_type, name, description, is_archived, set_id, select_data_id, consistency, organization_id FROM properties WHERE id = $1 ` func (q *Queries) GetPropertyById(ctx context.Context, id uuid.UUID) (Property, error) { @@ -161,6 +167,7 @@ func (q *Queries) GetPropertyById(ctx context.Context, id uuid.UUID) (Property, &i.SetID, &i.SelectDataID, &i.Consistency, + &i.OrganizationID, ) return i, err } diff --git a/services/property-svc/repos/property_value_repo/interfaces.go b/services/property-svc/repos/property_value_repo/interfaces.go new file mode 100644 index 000000000..164f3b79f --- /dev/null +++ b/services/property-svc/repos/property_value_repo/interfaces.go @@ -0,0 +1,52 @@ +package property_value_repo + +import "github.com/jackc/pgx/v5/pgtype" + +// This is a handwritten file, +// we should open a PR to generate {s/g}etters in sqlc + +// Implement models.BasicChangeSettable + +// CreateBasicPropertyValueParams + +func (c *CreateBasicPropertyValueParams) SetTextValue(s *string) { + c.TextValue = s +} + +func (c *CreateBasicPropertyValueParams) SetNumberValue(f *float64) { + c.NumberValue = f +} + +func (c *CreateBasicPropertyValueParams) SetBoolValue(b *bool) { + c.BoolValue = b +} + +func (c *CreateBasicPropertyValueParams) SetDateValue(d pgtype.Date) { + c.DateValue = d +} + +func (c *CreateBasicPropertyValueParams) SetDateTimeValue(t pgtype.Timestamp) { + c.DateTimeValue = t +} + +// UpdatePropertyValueByIDParams + +func (u *UpdatePropertyValueByIDParams) SetTextValue(s *string) { + u.TextValue = s +} + +func (u *UpdatePropertyValueByIDParams) SetNumberValue(f *float64) { + u.NumberValue = f +} + +func (u *UpdatePropertyValueByIDParams) SetBoolValue(b *bool) { + u.BoolValue = b +} + +func (u *UpdatePropertyValueByIDParams) SetDateValue(d pgtype.Date) { + u.DateValue = d +} + +func (u *UpdatePropertyValueByIDParams) SetDateTimeValue(t pgtype.Timestamp) { + u.DateTimeValue = t +} diff --git a/services/property-svc/repos/property_value_repo/models.go b/services/property-svc/repos/property_value_repo/models.go index 2f7cdac21..fca9b6ae9 100644 --- a/services/property-svc/repos/property_value_repo/models.go +++ b/services/property-svc/repos/property_value_repo/models.go @@ -21,15 +21,16 @@ type PatientPropertyViewRule struct { } type Property struct { - ID uuid.UUID - SubjectType int32 - FieldType int32 - Name string - Description string - IsArchived bool - SetID uuid.NullUUID - SelectDataID uuid.NullUUID - Consistency int64 + ID uuid.UUID + SubjectType int32 + FieldType int32 + Name string + Description string + IsArchived bool + SetID uuid.NullUUID + SelectDataID uuid.NullUUID + Consistency int64 + OrganizationID uuid.UUID } type PropertyValue struct { diff --git a/services/property-svc/repos/property_value_repo/property_value_repo.sql.go b/services/property-svc/repos/property_value_repo/property_value_repo.sql.go index 3d80ad865..9552da7c1 100644 --- a/services/property-svc/repos/property_value_repo/property_value_repo.sql.go +++ b/services/property-svc/repos/property_value_repo/property_value_repo.sql.go @@ -176,7 +176,7 @@ func (q *Queries) GetPropertyValuesWithPropertyBySubjectID(ctx context.Context, const getRelevantPropertyViews = `-- name: GetRelevantPropertyViews :many SELECT - properties.id, properties.subject_type, properties.field_type, properties.name, properties.description, properties.is_archived, properties.set_id, properties.select_data_id, properties.consistency, + properties.id, properties.subject_type, properties.field_type, properties.name, properties.description, properties.is_archived, properties.set_id, properties.select_data_id, properties.consistency, properties.organization_id, values.id as value_id, values.text_value, values.bool_value, @@ -237,6 +237,7 @@ func (q *Queries) GetRelevantPropertyViews(ctx context.Context, arg GetRelevantP &i.Property.SetID, &i.Property.SelectDataID, &i.Property.Consistency, + &i.Property.OrganizationID, &i.ValueID, &i.TextValue, &i.BoolValue, diff --git a/services/property-svc/repos/task_views_repo/models.go b/services/property-svc/repos/task_views_repo/models.go index ca784ca3f..42ffa230f 100644 --- a/services/property-svc/repos/task_views_repo/models.go +++ b/services/property-svc/repos/task_views_repo/models.go @@ -21,15 +21,16 @@ type PatientPropertyViewRule struct { } type Property struct { - ID uuid.UUID - SubjectType int32 - FieldType int32 - Name string - Description string - IsArchived bool - SetID uuid.NullUUID - SelectDataID uuid.NullUUID - Consistency int64 + ID uuid.UUID + SubjectType int32 + FieldType int32 + Name string + Description string + IsArchived bool + SetID uuid.NullUUID + SelectDataID uuid.NullUUID + Consistency int64 + OrganizationID uuid.UUID } type PropertyValue struct { diff --git a/services/property-svc/repos/views_repo/models.go b/services/property-svc/repos/views_repo/models.go index c6551859d..d21e8c01a 100644 --- a/services/property-svc/repos/views_repo/models.go +++ b/services/property-svc/repos/views_repo/models.go @@ -21,15 +21,16 @@ type PatientPropertyViewRule struct { } type Property struct { - ID uuid.UUID - SubjectType int32 - FieldType int32 - Name string - Description string - IsArchived bool - SetID uuid.NullUUID - SelectDataID uuid.NullUUID - Consistency int64 + ID uuid.UUID + SubjectType int32 + FieldType int32 + Name string + Description string + IsArchived bool + SetID uuid.NullUUID + SelectDataID uuid.NullUUID + Consistency int64 + OrganizationID uuid.UUID } type PropertyValue struct { diff --git a/services/property-svc/schema.sql b/services/property-svc/schema.sql index caaa1fe9b..6aea45e0e 100644 --- a/services/property-svc/schema.sql +++ b/services/property-svc/schema.sql @@ -97,7 +97,8 @@ CREATE TABLE public.properties ( is_archived boolean DEFAULT false NOT NULL, set_id uuid, select_data_id uuid, - consistency bigint DEFAULT 0 NOT NULL + consistency bigint DEFAULT 0 NOT NULL, + organization_id uuid NOT NULL ); diff --git a/services/property-svc/stories/AttachPropertyValueConflict_test.go b/services/property-svc/stories/AttachPropertyValueConflict_test.go new file mode 100644 index 000000000..3b0c2a4f8 --- /dev/null +++ b/services/property-svc/stories/AttachPropertyValueConflict_test.go @@ -0,0 +1,424 @@ +//nolint:lll +package stories + +import ( + "context" + pb "gen/services/property_svc/v1" + "hwtesting" + "strconv" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestAttachPropertyValueConflict_Text(t *testing.T) { + propertyClient := propertyServiceClient() + propertyValueClient := propertyValueServiceClient() + + ctx := context.Background() + + // Preparations + + createPropertyRequest := &pb.CreatePropertyRequest{ + SubjectType: pb.SubjectType_SUBJECT_TYPE_PATIENT, + FieldType: pb.FieldType_FIELD_TYPE_TEXT, + Name: t.Name(), + Description: nil, + SetId: nil, + } + + createRes, err := propertyClient.CreateProperty(ctx, createPropertyRequest) + require.NoError(t, err) + hwtesting.WaitForProjectionsToSettle() + + propertyID := createRes.PropertyId + subjectID := uuid.New().String() + + // WAS + + wasRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_TextValue{ + TextValue: t.Name() + " WAS", + }, + Consistency: nil, + }) + + require.NoError(t, err) + assert.Nil(t, wasRes.Conflict) + + initialConsistency := wasRes.Consistency + + // IS + + isRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_TextValue{ + TextValue: t.Name() + " IS", + }, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, isRes.Conflict) + + // WANT + + wantRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_TextValue{ + TextValue: t.Name() + " WANT", + }, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.NotNil(t, wantRes.Conflict) + + s := "conflicting_attributes:{key:\"value\" value:{is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + t.Name() + " IS\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + t.Name() + " WANT\"}}}}" + + assert.Equal(t, s, strings.ReplaceAll(wantRes.Conflict.String(), " ", " ")) +} + +func TestAttachPropertyValueConflict_Number(t *testing.T) { + propertyClient := propertyServiceClient() + propertyValueClient := propertyValueServiceClient() + + ctx := context.Background() + + // Preparations + + createPropertyRequest := &pb.CreatePropertyRequest{ + SubjectType: pb.SubjectType_SUBJECT_TYPE_PATIENT, + FieldType: pb.FieldType_FIELD_TYPE_NUMBER, + Name: t.Name(), + Description: nil, + SetId: nil, + } + + createRes, err := propertyClient.CreateProperty(ctx, createPropertyRequest) + require.NoError(t, err) + hwtesting.WaitForProjectionsToSettle() + + propertyID := createRes.PropertyId + subjectID := uuid.New().String() + + // WAS + + wasRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_NumberValue{ + NumberValue: 1.0, + }, + Consistency: nil, + }) + + require.NoError(t, err) + assert.Nil(t, wasRes.Conflict) + hwtesting.WaitForProjectionsToSettle() + + initialConsistency := wasRes.Consistency + + // IS + + isRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_NumberValue{ + NumberValue: 2.0, + }, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, isRes.Conflict) + hwtesting.WaitForProjectionsToSettle() + + // WANT + + wantRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_NumberValue{ + NumberValue: 3.0, + }, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.NotNil(t, wantRes.Conflict) + + s := "conflicting_attributes:{key:\"value\" value:{is:{[type.googleapis.com/google.protobuf.DoubleValue]:{value:2}} " + + "want:{[type.googleapis.com/google.protobuf.DoubleValue]:{value:3}}}}" + + assert.Equal(t, s, strings.ReplaceAll(wantRes.Conflict.String(), " ", " ")) +} + +func TestAttachPropertyValueConflict_Date(t *testing.T) { + propertyClient := propertyServiceClient() + propertyValueClient := propertyValueServiceClient() + + ctx := context.Background() + + // Preparations + + createPropertyRequest := &pb.CreatePropertyRequest{ + SubjectType: pb.SubjectType_SUBJECT_TYPE_PATIENT, + FieldType: pb.FieldType_FIELD_TYPE_DATE, + Name: t.Name(), + Description: nil, + SetId: nil, + } + + createRes, err := propertyClient.CreateProperty(ctx, createPropertyRequest) + require.NoError(t, err) + hwtesting.WaitForProjectionsToSettle() + + propertyID := createRes.PropertyId + subjectID := uuid.New().String() + + // WAS + + was := time.Now().Round(time.Millisecond) + + wasRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_DateValue{ + DateValue: &pb.Date{Date: timestamppb.New(was)}, + }, + Consistency: nil, + }) + + require.NoError(t, err) + assert.Nil(t, wasRes.Conflict) + + initialConsistency := wasRes.Consistency + hwtesting.WaitForProjectionsToSettle() + + // IS + + is := time.Now().Round(time.Millisecond) + + isRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_DateValue{ + DateValue: &pb.Date{Date: timestamppb.New(is)}, + }, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, isRes.Conflict) + hwtesting.WaitForProjectionsToSettle() + + // WANT + + want := time.Now().Round(time.Millisecond) + + wantRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_DateValue{ + DateValue: &pb.Date{Date: timestamppb.New(want)}, + }, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.NotNil(t, wantRes.Conflict) + + s := "conflicting_attributes:{key:\"value\" " + + "value:{is:{[type.googleapis.com/services.property_svc.v1.Date]:{date:{seconds:" + strconv.FormatInt(is.Unix(), 10) + " nanos:" + strconv.Itoa(is.Nanosecond()) + "}}} " + + "want:{[type.googleapis.com/services.property_svc.v1.Date]:{date:{seconds:" + strconv.FormatInt(want.Unix(), 10) + " nanos:" + strconv.Itoa(want.Nanosecond()) + "}}}}}" + + assert.Equal(t, s, strings.ReplaceAll(wantRes.Conflict.String(), " ", " ")) +} + +func TestAttachPropertyValueConflict_DateTime(t *testing.T) { + propertyClient := propertyServiceClient() + propertyValueClient := propertyValueServiceClient() + + ctx := context.Background() + + // Preparations + + createPropertyRequest := &pb.CreatePropertyRequest{ + SubjectType: pb.SubjectType_SUBJECT_TYPE_PATIENT, + FieldType: pb.FieldType_FIELD_TYPE_DATE_TIME, + Name: t.Name(), + Description: nil, + SetId: nil, + } + + createRes, err := propertyClient.CreateProperty(ctx, createPropertyRequest) + require.NoError(t, err) + hwtesting.WaitForProjectionsToSettle() + + propertyID := createRes.PropertyId + subjectID := uuid.New().String() + + // WAS + + was := time.Now().Round(time.Millisecond) + + wasRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_DateTimeValue{ + DateTimeValue: timestamppb.New(was), + }, + Consistency: nil, + }) + + require.NoError(t, err) + assert.Nil(t, wasRes.Conflict) + + initialConsistency := wasRes.Consistency + hwtesting.WaitForProjectionsToSettle() + + // IS + + is := time.Now().Round(time.Millisecond) + + isRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_DateTimeValue{ + DateTimeValue: timestamppb.New(is), + }, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, isRes.Conflict) + hwtesting.WaitForProjectionsToSettle() + + // WANT + + want := time.Now().Round(time.Millisecond) + + wantRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_DateTimeValue{ + DateTimeValue: timestamppb.New(want), + }, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.NotNil(t, wantRes.Conflict) + + s := "conflicting_attributes:{key:\"value\" " + + "value:{is:{[type.googleapis.com/google.protobuf.Timestamp]:{seconds:" + strconv.FormatInt(is.Unix(), 10) + " nanos:" + strconv.Itoa(is.Nanosecond()) + "}} " + + "want:{[type.googleapis.com/google.protobuf.Timestamp]:{seconds:" + strconv.FormatInt(want.Unix(), 10) + " nanos:" + strconv.Itoa(want.Nanosecond()) + "}}}}" + + assert.Equal(t, s, strings.ReplaceAll(wantRes.Conflict.String(), " ", " ")) +} + +func TestAttachPropertyValueConflict_SingleSelect(t *testing.T) { + propertyClient := propertyServiceClient() + propertyValueClient := propertyValueServiceClient() + + ctx := context.Background() + + // Preparations + + createPropertyRequest := &pb.CreatePropertyRequest{ + SubjectType: pb.SubjectType_SUBJECT_TYPE_PATIENT, + FieldType: pb.FieldType_FIELD_TYPE_SELECT, + Name: t.Name(), + Description: nil, + SetId: nil, + FieldTypeData: &pb.CreatePropertyRequest_SelectData_{ + SelectData: &pb.CreatePropertyRequest_SelectData{ + Options: []*pb.CreatePropertyRequest_SelectData_SelectOption{ + { + Name: t.Name() + " A", + Description: nil, + }, + { + Name: t.Name() + " B", + Description: nil, + }, + { + Name: t.Name() + " C", + Description: nil, + }, + }, + }, + }, + } + + createRes, err := propertyClient.CreateProperty(ctx, createPropertyRequest) + require.NoError(t, err) + hwtesting.WaitForProjectionsToSettle() + + propertyID := createRes.PropertyId + subjectID := uuid.New().String() + + prop, err := propertyClient.GetProperty(ctx, &pb.GetPropertyRequest{ + Id: propertyID, + ViewSource: nil, + }) + require.NoError(t, err) + opts := prop.GetSelectData().Options + was := opts[0].Id + is := opts[1].Id + want := opts[2].Id + + // WAS + + wasRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_SelectValue{ + SelectValue: was, + }, + Consistency: nil, + }) + + require.NoError(t, err) + assert.Nil(t, wasRes.Conflict) + + initialConsistency := wasRes.Consistency + hwtesting.WaitForProjectionsToSettle() + + // IS + + isRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_SelectValue{ + SelectValue: is, + }, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, isRes.Conflict) + hwtesting.WaitForProjectionsToSettle() + + // WANT + + wantRes, err := propertyValueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ + SubjectId: subjectID, + PropertyId: propertyID, + Value: &pb.AttachPropertyValueRequest_SelectValue{ + SelectValue: want, + }, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.NotNil(t, wantRes.Conflict) + + s := "conflicting_attributes:{key:\"value\" " + + "value:{is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + is + "\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + want + "\"}}}}" + + assert.Equal(t, s, strings.ReplaceAll(wantRes.Conflict.String(), " ", " ")) +} diff --git a/services/property-svc/stories/GetPropertieBySubjectType_test.go b/services/property-svc/stories/GetPropertieBySubjectType_test.go index f6e0d4123..1b4f4b27c 100644 --- a/services/property-svc/stories/GetPropertieBySubjectType_test.go +++ b/services/property-svc/stories/GetPropertieBySubjectType_test.go @@ -4,6 +4,9 @@ import ( "context" "encoding/json" pb "gen/services/property_svc/v1" + "hwauthz" + "hwauthz/commonPerm" + "hwauthz/spicedb" "hwtesting" "hwutil" "regexp" @@ -18,10 +21,18 @@ import ( // - Create Properties // - Check GetPropertiesBySubjectType func TestGetProperties(t *testing.T) { - propertyClient := propertyServiceClient() - ctx := context.Background() + orgID := uuid.New() + authz := spicedb.NewSpiceDBAuthZ() + _, err := authz.Create(hwauthz.NewRelationship( + commonPerm.User(uuid.MustParse(hwtesting.FakeTokenUser)), + "member", + commonPerm.Organization(orgID), + )).Commit(ctx) + require.NoError(t, err) + propertyClient := pb.NewPropertyServiceClient(hwtesting.GetGrpcConn("", orgID.String())) + // // Create new Properties // diff --git a/services/property-svc/stories/PropertyValueCRUD_test.go b/services/property-svc/stories/PropertyValueCRUD_test.go index 405d3e465..ded5e0e1a 100644 --- a/services/property-svc/stories/PropertyValueCRUD_test.go +++ b/services/property-svc/stories/PropertyValueCRUD_test.go @@ -14,7 +14,7 @@ import ( // TestCreateAttachUpdateTextProperty: // - Create a Property, -// - Attach a Value +// - Attach a ValueChange // - Update said value func TestCreateAttachUpdateTextProperty(t *testing.T) { propertyClient := propertyServiceClient() @@ -86,12 +86,14 @@ func TestCreateAttachUpdateTextProperty(t *testing.T) { SubjectId: subjectID, PropertyId: propertyID.String(), Value: &pb.AttachPropertyValueRequest_TextValue{ - TextValue: "Initial Text Value", + TextValue: "Initial Text ValueChange", }, }) require.NoError(t, err, "could not attach value") + assert.Nil(t, attachResponse.Conflict) + hwtesting.WaitForProjectionsToSettle() // @@ -111,24 +113,25 @@ func TestCreateAttachUpdateTextProperty(t *testing.T) { assert.Len(t, attachedValuesResponse.Values, 1) - assert.Equal(t, "Initial Text Value", attachedValuesResponse.Values[0].GetTextValue()) + assert.Equal(t, "Initial Text ValueChange", attachedValuesResponse.Values[0].GetTextValue()) assert.Equal(t, &attachResponse.Consistency, attachedValuesResponse.Values[0].ValueConsistency) // - // Update Value + // Update ValueChange // updateResponse, err := valueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ SubjectId: subjectID, PropertyId: propertyID.String(), Value: &pb.AttachPropertyValueRequest_TextValue{ - TextValue: "Updated Text Value", + TextValue: "Updated Text ValueChange", }, }) require.NoError(t, err, "could not update value") + assert.Nil(t, updateResponse.Conflict) assert.NotEqual(t, attachedValuesResponse.Values[0].ValueConsistency, &updateResponse.Consistency) hwtesting.WaitForProjectionsToSettle() @@ -150,7 +153,7 @@ func TestCreateAttachUpdateTextProperty(t *testing.T) { assert.Len(t, attachedValuesResponse.Values, 1) - assert.Equal(t, "Updated Text Value", attachedValuesResponse.Values[0].GetTextValue()) + assert.Equal(t, "Updated Text ValueChange", attachedValuesResponse.Values[0].GetTextValue()) assert.Equal( t, @@ -162,7 +165,7 @@ func TestCreateAttachUpdateTextProperty(t *testing.T) { // TestCreateAttachUpdateSelectProperty: // - Create a Property, -// - Attach a Value +// - Attach a ValueChange // - Update said value func TestCreateAttachUpdateSelectProperty(t *testing.T) { propertyClient := propertyServiceClient() @@ -259,6 +262,7 @@ func TestCreateAttachUpdateSelectProperty(t *testing.T) { }) require.NoError(t, err, "could not attach value") + assert.Nil(t, attachResponse.Conflict) hwtesting.WaitForProjectionsToSettle() @@ -284,7 +288,7 @@ func TestCreateAttachUpdateSelectProperty(t *testing.T) { assert.Equal(t, &attachResponse.Consistency, attachedValuesResponse.Values[0].ValueConsistency) // - // Update Value + // Update ValueChange // updateResponse, err := valueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ @@ -296,6 +300,7 @@ func TestCreateAttachUpdateSelectProperty(t *testing.T) { }) require.NoError(t, err, "could not update value") + assert.Nil(t, updateResponse.Conflict) assert.NotEqual(t, attachedValuesResponse.Values[0].ValueConsistency, &updateResponse.Consistency) @@ -330,7 +335,7 @@ func TestCreateAttachUpdateSelectProperty(t *testing.T) { // TestCreateAttachUpdateMultiSelectProperty: // - Create a Property, -// - Attach a Value +// - Attach a ValueChange // - Update said value func TestCreateAttachUpdateMultiSelectProperty(t *testing.T) { propertyClient := propertyServiceClient() @@ -435,6 +440,7 @@ func TestCreateAttachUpdateMultiSelectProperty(t *testing.T) { }) require.NoError(t, err, "could not attach value") + assert.Nil(t, attachResponse.Conflict) hwtesting.WaitForProjectionsToSettle() @@ -464,7 +470,7 @@ func TestCreateAttachUpdateMultiSelectProperty(t *testing.T) { assert.Equal(t, &attachResponse.Consistency, attachedValuesResponse.Values[0].ValueConsistency) // - // Update Value + // Update ValueChange // updateResponse, err := valueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ @@ -479,6 +485,7 @@ func TestCreateAttachUpdateMultiSelectProperty(t *testing.T) { }) require.NoError(t, err, "could not update value") + assert.Nil(t, updateResponse.Conflict) assert.NotEqual(t, attachedValuesResponse.Values[0].ValueConsistency, &updateResponse.Consistency) @@ -517,9 +524,9 @@ func TestCreateAttachUpdateMultiSelectProperty(t *testing.T) { // TestCreateAttachAddOptionAttachSelectProperty: // - Create a Property, -// - Attach a Value +// - Attach a ValueChange // - Upsert an Option -// - Attach another Value +// - Attach another ValueChange func TestCreateAttachAddOptionAttachSelectProperty(t *testing.T) { propertyClient := propertyServiceClient() ctx := context.Background() @@ -638,7 +645,7 @@ func TestCreateAttachAddOptionAttachSelectProperty(t *testing.T) { option2 := propertyResponse.GetSelectData().Options[1].GetId() // not guaranteed tbf // - // Update Value + // Update ValueChange // _, err = valueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ @@ -675,9 +682,9 @@ func TestCreateAttachAddOptionAttachSelectProperty(t *testing.T) { // TestCreateAttachAddOptionAttachMultiSelectProperty: // - Create a Property, -// - Attach a Value +// - Attach a ValueChange // - Upsert an Option -// - Attach another Value +// - Attach another ValueChange func TestCreateAttachAddOptionAttachMultiSelectProperty(t *testing.T) { propertyClient := propertyServiceClient() ctx := context.Background() @@ -804,7 +811,7 @@ func TestCreateAttachAddOptionAttachMultiSelectProperty(t *testing.T) { option2 := propertyResponse.GetSelectData().Options[1].GetId() // order not guaranteed // - // Update Value + // Update ValueChange // _, err = valueClient.AttachPropertyValue(ctx, &pb.AttachPropertyValueRequest{ diff --git a/services/property-svc/stories/UpdatePropertyConflict_test.go b/services/property-svc/stories/UpdatePropertyConflict_test.go new file mode 100644 index 000000000..dd1e87077 --- /dev/null +++ b/services/property-svc/stories/UpdatePropertyConflict_test.go @@ -0,0 +1,138 @@ +//nolint:lll +package stories + +import ( + "context" + pb "gen/services/property_svc/v1" + "hwtesting" + "hwutil" + "strconv" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/stretchr/testify/assert" +) + +func TestUpdatePropertyConflict(t *testing.T) { + propertyClient := propertyServiceClient() + + ctx := context.Background() + + // Preparations + + createPropertyRequest := &pb.CreatePropertyRequest{ + SubjectType: pb.SubjectType_SUBJECT_TYPE_TASK, + FieldType: pb.FieldType_FIELD_TYPE_SELECT, + Name: t.Name() + " WAS", + Description: nil, + SetId: nil, + FieldTypeData: &pb.CreatePropertyRequest_SelectData_{SelectData: &pb.CreatePropertyRequest_SelectData{ + Options: []*pb.CreatePropertyRequest_SelectData_SelectOption{ + { + Name: "Option WAS", + Description: hwutil.PtrTo("Option WAS Descr"), + }, + }, + }}, + } + + createRes, err := propertyClient.CreateProperty(ctx, createPropertyRequest) + require.NoError(t, err) + hwtesting.WaitForProjectionsToSettle() + + propertyID := createRes.PropertyId + initialConsistency := createRes.Consistency + + getRes, err := propertyClient.GetProperty(ctx, &pb.GetPropertyRequest{ + Id: propertyID, + }) + require.NoError(t, err) + + initialOpts := getRes.GetSelectData().Options + assert.Len(t, initialOpts, 1) + optionID := initialOpts[0].Id + + // First Update + is, err := propertyClient.UpdateProperty(ctx, &pb.UpdatePropertyRequest{ + Id: propertyID, + SubjectType: hwutil.PtrTo(pb.SubjectType_SUBJECT_TYPE_PATIENT), + Name: hwutil.PtrTo(t.Name() + " IS"), + Description: hwutil.PtrTo(t.Name() + " Description IS"), + FieldTypeData: &pb.UpdatePropertyRequest_SelectData_{SelectData: &pb.UpdatePropertyRequest_SelectData{ + UpsertOptions: []*pb.UpdatePropertyRequest_SelectData_SelectOption{ + { + Id: optionID, + Name: hwutil.PtrTo("Option IS"), + Description: hwutil.PtrTo("Option IS Descr"), + }, + }, + }}, + Consistency: &initialConsistency, + }) + + require.NoError(t, err) + assert.Nil(t, is.Conflict) + hwtesting.WaitForProjectionsToSettle() + + // Second Update + want, err := propertyClient.UpdateProperty(ctx, &pb.UpdatePropertyRequest{ + Id: propertyID, + SubjectType: hwutil.PtrTo(pb.SubjectType_SUBJECT_TYPE_TASK), + Name: hwutil.PtrTo(t.Name() + " WANT"), + Description: hwutil.PtrTo(t.Name() + " Description WANT"), + FieldTypeData: &pb.UpdatePropertyRequest_SelectData_{SelectData: &pb.UpdatePropertyRequest_SelectData{ + UpsertOptions: []*pb.UpdatePropertyRequest_SelectData_SelectOption{ + { + Id: optionID, + Name: hwutil.PtrTo("Option WANT"), + Description: hwutil.PtrTo("Option WANT Descr"), + }, + }, + }}, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // Assertions + assert.NotNil(t, want.Conflict) + assert.False(t, want.Conflict.HistoryMissing) + + keys := hwutil.Keys(want.Conflict.ConflictingAttributes) + expKeys := []string{ + "name", + "description", + "subject_type", + "select_data.upsert_options." + optionID + ".name", + "select_data.upsert_options." + optionID + ".description", + } + + expValues := []interface{}{ + // name + "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + t.Name() + " IS\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + t.Name() + " WANT\"}}", + // description + "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + t.Name() + " Description IS\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + t.Name() + " Description WANT\"}}", + // subject_type + "is:{[type.googleapis.com/google.protobuf.Int32Value]:{value:" + strconv.Itoa(int(pb.SubjectType_SUBJECT_TYPE_PATIENT.Number())) + "}} " + + "want:{[type.googleapis.com/google.protobuf.Int32Value]:{value:" + strconv.Itoa(int(pb.SubjectType_SUBJECT_TYPE_TASK.Number())) + "}}", + // .name + "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"Option IS\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"Option WANT\"}}", + // .description + "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"Option IS Descr\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"Option WANT Descr\"}}", + } + + assert.Len(t, keys, len(expKeys)) + assert.Subset(t, expKeys, keys) + + for i, key := range expKeys { + assert.Equal(t, + expValues[i], + strings.ReplaceAll(want.Conflict.ConflictingAttributes[key].String(), " ", " "), + ) + } +} diff --git a/services/property-svc/stories/setup_test.go b/services/property-svc/stories/setup_test.go index 44da2efee..76191ee4a 100644 --- a/services/property-svc/stories/setup_test.go +++ b/services/property-svc/stories/setup_test.go @@ -66,19 +66,19 @@ func TestMain(m *testing.M) { } func propertyServiceClient() pb.PropertyServiceClient { - return pb.NewPropertyServiceClient(hwtesting.GetGrpcConn("")) + return pb.NewPropertyServiceClient(hwtesting.GetGrpcConn("", "")) } func propertyViewServiceClient() pb.PropertyViewsServiceClient { - return pb.NewPropertyViewsServiceClient(hwtesting.GetGrpcConn("")) + return pb.NewPropertyViewsServiceClient(hwtesting.GetGrpcConn("", "")) } func propertyValueServiceClient() pb.PropertyValueServiceClient { - return pb.NewPropertyValueServiceClient(hwtesting.GetGrpcConn("")) + return pb.NewPropertyValueServiceClient(hwtesting.GetGrpcConn("", "")) } -func NamesOf(arr []*pb.GetAttachedPropertyValuesResponse_Value_SelectValueOption) []string { - strs := hwutil.Map(arr, func(v *pb.GetAttachedPropertyValuesResponse_Value_SelectValueOption) string { +func NamesOf(arr []*pb.SelectValueOption) []string { + strs := hwutil.Map(arr, func(v *pb.SelectValueOption) string { return v.Name }) sort.Strings(strs) diff --git a/services/tasks-svc/go.mod b/services/tasks-svc/go.mod index dc3101cca..93c6f67b3 100644 --- a/services/tasks-svc/go.mod +++ b/services/tasks-svc/go.mod @@ -9,6 +9,7 @@ replace ( hwauthz => ../../libs/hwauthz hwdb => ../../libs/hwdb hwes => ../../libs/hwes + hwgrpc => ../../libs/hwgrpc hwlocale => ../../libs/hwlocale hwtesting => ../../libs/hwtesting hwutil => ../../libs/hwutil @@ -25,6 +26,7 @@ require ( github.com/golang-migrate/migrate/v4 v4.18.1 github.com/google/uuid v1.6.0 github.com/jackc/pgx/v5 v5.7.1 + github.com/jinzhu/copier v0.4.0 github.com/nicksnyder/go-i18n/v2 v2.4.0 github.com/rs/zerolog v1.33.0 github.com/stretchr/testify v1.9.0 @@ -35,6 +37,7 @@ require ( hwauthz v0.0.0 hwdb v0.0.0 hwes v0.0.0 + hwgrpc v0.0.0 hwlocale v0.0.0 hwtesting v0.0.0 hwutil v0.0.0 diff --git a/services/tasks-svc/go.sum b/services/tasks-svc/go.sum index a00b131b8..15f63d86a 100644 --- a/services/tasks-svc/go.sum +++ b/services/tasks-svc/go.sum @@ -149,6 +149,8 @@ github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= +github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jzelinskie/stringz v0.0.3 h1:0GhG3lVMYrYtIvRbxvQI6zqRTT1P1xyQlpa0FhfUXas= diff --git a/services/tasks-svc/internal/bed/bed.go b/services/tasks-svc/internal/bed/bed.go index c7f2c1e6f..79f8854c8 100644 --- a/services/tasks-svc/internal/bed/bed.go +++ b/services/tasks-svc/internal/bed/bed.go @@ -4,12 +4,15 @@ import ( "common" "common/hwerr" "context" + commonpb "gen/libs/common/v1" "hwdb" + "hwgrpc" "hwlocale" "hwutil" "github.com/jackc/pgx/v5/pgconn" "google.golang.org/genproto/googleapis/rpc/errdetails" + "google.golang.org/protobuf/types/known/wrapperspb" "tasks-svc/locale" "tasks-svc/repos/bed_repo" @@ -200,8 +203,6 @@ func (ServiceServer) GetBedsByRoom( } func (ServiceServer) UpdateBed(ctx context.Context, req *pb.UpdateBedRequest) (*pb.UpdateBedResponse, error) { - bedRepo := bed_repo.New(hwdb.GetDB()) - bedID, err := uuid.Parse(req.GetId()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) @@ -212,7 +213,21 @@ func (ServiceServer) UpdateBed(ctx context.Context, req *pb.UpdateBedRequest) (* return nil, status.Error(codes.InvalidArgument, err.Error()) } - consistency, err := bedRepo.UpdateBed(ctx, bed_repo.UpdateBedParams{ + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + + // Start TX + tx, rollback, err := hwdb.BeginTx(hwdb.GetDB(), ctx) + if err != nil { + return nil, err + } + defer rollback() + bedRepo := bed_repo.New(tx) + + // do update + result, err := bedRepo.UpdateBed(ctx, bed_repo.UpdateBedParams{ ID: bedID, Name: req.Name, RoomID: roomId, @@ -222,9 +237,59 @@ func (ServiceServer) UpdateBed(ctx context.Context, req *pb.UpdateBedRequest) (* return nil, err } + // conflict detection + if expConsistency != nil && *expConsistency != common.ConsistencyToken(result.OldConsistency) { //nolint:gosec + // bed is not event sourced yet and has more than one field, + // thus we are not able to pinpoint conflicts to a field, we only know *some* update has happened since + // for convenience we are filtering out obvious non-conflicts, where the update is the same as the is state, + // or the field was not changed + + conflicts := make(map[string]*commonpb.AttributeConflict) + + if req.Name != nil && *req.Name != result.OldName { + conflicts["name"], err = hwgrpc.AttributeConflict( + wrapperspb.String(result.OldName), + wrapperspb.String(*req.Name), + ) + if err != nil { + return nil, err + } + } + + if req.RoomId != nil && *req.RoomId != result.OldRoomID.String() { + conflicts["room_id"], err = hwgrpc.AttributeConflict( + wrapperspb.String(result.OldRoomID.String()), + wrapperspb.String(*req.RoomId), + ) + if err != nil { + return nil, err + } + } + + if len(conflicts) != 0 { + // prevent the update + if err := hwdb.Error(ctx, tx.Rollback(ctx)); err != nil { + return nil, err + } + + // return conflict + return &pb.UpdateBedResponse{ + Conflict: &commonpb.Conflict{ + ConflictingAttributes: conflicts, + HistoryMissing: true, + }, + Consistency: common.ConsistencyToken(result.OldConsistency).String(), //nolint:gosec + }, nil + } + } + + if err := hwdb.Error(ctx, tx.Commit(ctx)); err != nil { + return nil, err + } + return &pb.UpdateBedResponse{ - Conflict: nil, // TODO - Consistency: common.ConsistencyToken(consistency).String(), //nolint:gosec + Conflict: nil, + Consistency: common.ConsistencyToken(result.Consistency).String(), //nolint:gosec }, nil } diff --git a/services/tasks-svc/internal/patient/aggregate/aggregate.go b/services/tasks-svc/internal/patient/aggregate/aggregate.go index 554cff76a..6ff7475ea 100644 --- a/services/tasks-svc/internal/patient/aggregate/aggregate.go +++ b/services/tasks-svc/internal/patient/aggregate/aggregate.go @@ -1,10 +1,13 @@ package aggregate import ( + "common" "context" + "fmt" "hwes" "github.com/google/uuid" + "github.com/jinzhu/copier" patientEventsV1 "tasks-svc/internal/patient/events/v1" "tasks-svc/internal/patient/models" @@ -33,6 +36,36 @@ func LoadPatientAggregate(ctx context.Context, as hwes.AggregateStore, id uuid.U return patientAggregate, nil } +func LoadPatientAggregateWithSnapshotAt( + ctx context.Context, + as hwes.AggregateStore, + id uuid.UUID, + pauseAt *common.ConsistencyToken, +) (*PatientAggregate, *models.Patient, error) { + patientAggregate := NewPatientAggregate(id) + var snapshot *models.Patient + + if pauseAt != nil { + // load pauseAt+1-many events (version is 0-indexed) + if err := as.LoadN(ctx, patientAggregate, uint64(*pauseAt)+1); err != nil { + return nil, nil, err + } + + var cpy models.Patient + if err := copier.CopyWithOption(&cpy, patientAggregate.Patient, copier.Option{DeepCopy: true}); err != nil { + return nil, nil, fmt.Errorf("LoadPatientAggregateWithSnapshotAt: could not copy snapshot: %w", err) + } + snapshot = &cpy + } + + // continue loading all other events + if err := as.Load(ctx, patientAggregate); err != nil { + return nil, nil, err + } + + return patientAggregate, snapshot, nil +} + func (a *PatientAggregate) initEventListeners() { a.RegisterEventListener(patientEventsV1.PatientCreated, a.onPatientCreated) a.RegisterEventListener(patientEventsV1.BedAssigned, a.onBedAssigned) diff --git a/services/tasks-svc/internal/patient/api/grpc.go b/services/tasks-svc/internal/patient/api/grpc.go index 1d147085f..88b8c3695 100644 --- a/services/tasks-svc/internal/patient/api/grpc.go +++ b/services/tasks-svc/internal/patient/api/grpc.go @@ -4,16 +4,22 @@ import ( "common" "common/hwerr" "context" + "errors" + "fmt" + commonpb "gen/libs/common/v1" pb "gen/services/tasks_svc/v1" "hwdb" "hwdb/locale" "hwes" + "hwgrpc" "hwutil" "github.com/google/uuid" zlog "github.com/rs/zerolog/log" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/wrapperspb" "tasks-svc/internal/patient/handlers" "tasks-svc/internal/patient/models" @@ -411,15 +417,77 @@ func (s *PatientGrpcService) UpdatePatient( return nil, err } - consistency, err := s.handlers.Commands.V1.UpdatePatient(ctx, patientID, req.HumanReadableIdentifier, req.Notes) - if err != nil { - return nil, err + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + + var consistency common.ConsistencyToken + + for i := 0; true; i++ { + if i > 10 { + zlog.Ctx(ctx).Warn().Msg("UpdatePatient: conflict circuit breaker triggered") + return nil, errors.New("failed conflict resolution") + } + + c, conflict, err := s.handlers.Commands.V1.UpdatePatient( + ctx, + patientID, + expConsistency, + req.HumanReadableIdentifier, + req.Notes, + ) + consistency = c + + if err != nil { + return nil, err + } + if conflict == nil { + break + } + conflicts := make(map[string]*commonpb.AttributeConflict) + + // TODO: find a generic approach + hriUpdateRequested := req.HumanReadableIdentifier != nil && + *req.HumanReadableIdentifier != conflict.Is.HumanReadableIdentifier + hriAlreadyUpdated := conflict.Was.HumanReadableIdentifier != conflict.Is.HumanReadableIdentifier + if hriUpdateRequested && hriAlreadyUpdated { + conflicts["human_readable_identifier"], err = hwgrpc.AttributeConflict( + wrapperspb.String(conflict.Is.HumanReadableIdentifier), + wrapperspb.String(*req.HumanReadableIdentifier), + ) + if err != nil { + return nil, err + } + } + + notesUpdateRequested := req.Notes != nil && *req.Notes != conflict.Is.Notes + notesAlreadyUpdated := conflict.Was.Notes != conflict.Is.Notes + if notesUpdateRequested && notesAlreadyUpdated { + conflicts["notes"], err = hwgrpc.AttributeConflict( + wrapperspb.String(conflict.Is.Notes), + wrapperspb.String(*req.Notes), + ) + if err != nil { + return nil, fmt.Errorf("could not marshall notes conflict: %w", err) + } + } + + if len(conflicts) != 0 { + return &pb.UpdatePatientResponse{ + Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts}, + Consistency: c.String(), + }, nil + } + + // no conflict? retry with new consistency + expConsistency = &c } tracking.AddPatientToRecentActivity(ctx, patientID.String()) return &pb.UpdatePatientResponse{ - Conflict: nil, // TODO + Conflict: nil, Consistency: consistency.String(), }, nil } @@ -439,17 +507,67 @@ func (s *PatientGrpcService) AssignBed(ctx context.Context, req *pb.AssignBedReq return nil, err } - consistency, err := s.handlers.Commands.V1.AssignBed(ctx, patientID, bedID) - if err != nil { - return nil, err + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + + var consistency common.ConsistencyToken + + for i := 0; true; i++ { + if i > 10 { + log.Warn().Msg("AssignBed: conflict circuit breaker triggered") + return nil, errors.New("failed conflict resolution") + } + + c, conflict, err := s.handlers.Commands.V1.AssignBed(ctx, patientID, bedID, expConsistency) + consistency = c + + if err != nil { + return nil, err + } + if conflict == nil { + break + } + conflicts := make(map[string]*commonpb.AttributeConflict) + + // TODO: find a generic approach + bedUpdateRequested := req.BedId != conflict.Is.BedID.UUID.String() + bedAlreadyUpdated := conflict.Was.BedID != conflict.Is.BedID + if bedUpdateRequested && bedAlreadyUpdated { + var is proto.Message = nil + if conflict.Is.BedID.Valid { + is = wrapperspb.String(conflict.Is.BedID.UUID.String()) + } + conflicts["bed_id"], err = hwgrpc.AttributeConflict( + is, + wrapperspb.String(req.BedId), + ) + if err != nil { + return nil, err + } + } + + if len(conflicts) != 0 { + return &pb.AssignBedResponse{ + Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts}, + Consistency: consistency.String(), + }, nil + } + + // no conflict? retry with new consistency + expConsistency = &c } - log.Info().Str("patientID", patientID.String()).Str("bedID", bedID.String()).Msg("assigned bed to patient") + log.Info(). + Str("patientID", patientID.String()). + Str("bedID", bedID.String()). + Msg("assigned bed to patient") tracking.AddWardToRecentActivity(ctx, patientID.String()) return &pb.AssignBedResponse{ - Conflict: nil, // TODO + Conflict: nil, Consistency: consistency.String(), }, nil } @@ -467,9 +585,49 @@ func (s *PatientGrpcService) UnassignBed( return nil, err } - consistency, err := s.handlers.Commands.V1.UnassignBed(ctx, patientID) - if err != nil { - return nil, err + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + + var consistency common.ConsistencyToken + + for i := 0; true; i++ { + if i > 10 { + log.Warn().Msg("AssignBed: conflict circuit breaker triggered") + return nil, errors.New("failed conflict resolution") + } + + c, conflict, err := s.handlers.Commands.V1.UnassignBed(ctx, patientID, expConsistency) + if err != nil { + return nil, err + } + consistency = c + if conflict == nil { + break + } + conflicts := make(map[string]*commonpb.AttributeConflict) + + // TODO: find a generic approach + if conflict.Is.BedID.Valid && conflict.Was.BedID != conflict.Is.BedID { + conflicts["bed_id"], err = hwgrpc.AttributeConflict( + wrapperspb.String(conflict.Is.BedID.UUID.String()), + nil, + ) + if err != nil { + return nil, err + } + } + + if len(conflicts) != 0 { + return &pb.UnassignBedResponse{ + Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts}, + Consistency: c.String(), + }, nil + } + + // no conflict? retry with new consistency + expConsistency = &c } log.Info().Str("patientID", patientID.String()).Msg("unassigned bed from patient") diff --git a/services/tasks-svc/internal/patient/commands/v1/assign_bed.go b/services/tasks-svc/internal/patient/commands/v1/assign_bed.go index 3b99597ca..e9c4afaec 100644 --- a/services/tasks-svc/internal/patient/commands/v1/assign_bed.go +++ b/services/tasks-svc/internal/patient/commands/v1/assign_bed.go @@ -8,24 +8,42 @@ import ( "github.com/google/uuid" "tasks-svc/internal/patient/aggregate" + "tasks-svc/internal/patient/models" ) type AssignBedCommandHandler func( ctx context.Context, patientID uuid.UUID, bedID uuid.UUID, -) (common.ConsistencyToken, error) + expConsistency *common.ConsistencyToken, +) (common.ConsistencyToken, *common.Conflict[*models.Patient], error) func NewAssignBedCommandHandler(as hwes.AggregateStore) AssignBedCommandHandler { - return func(ctx context.Context, patientID uuid.UUID, bedID uuid.UUID) (common.ConsistencyToken, error) { - a, err := aggregate.LoadPatientAggregate(ctx, as, patientID) + return func( + ctx context.Context, + patientID uuid.UUID, + bedID uuid.UUID, + expConsistency *common.ConsistencyToken, + ) (common.ConsistencyToken, *common.Conflict[*models.Patient], error) { + a, oldState, err := aggregate.LoadPatientAggregateWithSnapshotAt(ctx, as, patientID, expConsistency) if err != nil { - return 0, err + return 0, nil, err + } + + // update happened since? + newToken := common.ConsistencyToken(a.GetVersion()) + if expConsistency != nil && *expConsistency != newToken { + return newToken, &common.Conflict[*models.Patient]{ + Was: oldState, + Is: a.Patient, + }, nil } if err := a.AssignBed(ctx, bedID); err != nil { - return 0, err + return 0, nil, err } - return as.Save(ctx, a) + + consistency, err := as.Save(ctx, a) + return consistency, nil, err } } diff --git a/services/tasks-svc/internal/patient/commands/v1/unassign_bed.go b/services/tasks-svc/internal/patient/commands/v1/unassign_bed.go index c3a7533cd..cea2f4cb8 100644 --- a/services/tasks-svc/internal/patient/commands/v1/unassign_bed.go +++ b/services/tasks-svc/internal/patient/commands/v1/unassign_bed.go @@ -8,20 +8,39 @@ import ( "github.com/google/uuid" "tasks-svc/internal/patient/aggregate" + "tasks-svc/internal/patient/models" ) -type UnassignBedCommandHandler func(ctx context.Context, patientID uuid.UUID) (common.ConsistencyToken, error) +type UnassignBedCommandHandler func( + ctx context.Context, + patientID uuid.UUID, + expectedConsistency *common.ConsistencyToken, +) (common.ConsistencyToken, *common.Conflict[*models.Patient], error) func NewUnassignBedCommandHandler(as hwes.AggregateStore) UnassignBedCommandHandler { - return func(ctx context.Context, patientID uuid.UUID) (common.ConsistencyToken, error) { - a, err := aggregate.LoadPatientAggregate(ctx, as, patientID) + return func( + ctx context.Context, + patientID uuid.UUID, + expectedConsistency *common.ConsistencyToken, + ) (common.ConsistencyToken, *common.Conflict[*models.Patient], error) { + a, oldState, err := aggregate.LoadPatientAggregateWithSnapshotAt(ctx, as, patientID, expectedConsistency) if err != nil { - return 0, err + return 0, nil, err + } + + // update has happened since? + newToken := common.ConsistencyToken(a.GetVersion()) + if expectedConsistency != nil && *expectedConsistency != newToken { + return newToken, &common.Conflict[*models.Patient]{ + Was: oldState, + Is: a.Patient, + }, nil } if err := a.UnassignBed(ctx); err != nil { - return 0, err + return 0, nil, err } - return as.Save(ctx, a) + consistency, err := as.Save(ctx, a) + return consistency, nil, err } } diff --git a/services/tasks-svc/internal/patient/commands/v1/update_patient.go b/services/tasks-svc/internal/patient/commands/v1/update_patient.go index 477f9a7e6..e3496ec93 100644 --- a/services/tasks-svc/internal/patient/commands/v1/update_patient.go +++ b/services/tasks-svc/internal/patient/commands/v1/update_patient.go @@ -8,39 +8,52 @@ import ( "github.com/google/uuid" "tasks-svc/internal/patient/aggregate" + "tasks-svc/internal/patient/models" ) type UpdatePatientCommandHandler func( ctx context.Context, patientID uuid.UUID, + expConsistency *common.ConsistencyToken, humanReadableIdentifier *string, notes *string, -) (common.ConsistencyToken, error) +) (common.ConsistencyToken, *common.Conflict[*models.Patient], error) func NewUpdatePatientCommandHandler(as hwes.AggregateStore) UpdatePatientCommandHandler { return func( ctx context.Context, patientID uuid.UUID, + expConsistency *common.ConsistencyToken, humanReadableIdentifier *string, notes *string, - ) (common.ConsistencyToken, error) { - a, err := aggregate.LoadPatientAggregate(ctx, as, patientID) + ) (common.ConsistencyToken, *common.Conflict[*models.Patient], error) { + a, oldState, err := aggregate.LoadPatientAggregateWithSnapshotAt(ctx, as, patientID, expConsistency) if err != nil { - return 0, err + return 0, nil, err + } + + // was an update performed since expConsistency? + newToken := common.ConsistencyToken(a.GetVersion()) + if expConsistency != nil && *expConsistency != newToken { + return newToken, &common.Conflict[*models.Patient]{ + Was: oldState, + Is: a.Patient, + }, nil } if humanReadableIdentifier != nil { if err := a.UpdateHumanReadableIdentifier(ctx, *humanReadableIdentifier); err != nil { - return 0, err + return 0, nil, err } } if notes != nil { if err := a.UpdateNotes(ctx, *notes); err != nil { - return 0, err + return 0, nil, err } } - return as.Save(ctx, a) + consistency, err := as.Save(ctx, a) + return consistency, nil, err } } diff --git a/services/tasks-svc/internal/room/room.go b/services/tasks-svc/internal/room/room.go index 868f714b1..c75760173 100644 --- a/services/tasks-svc/internal/room/room.go +++ b/services/tasks-svc/internal/room/room.go @@ -3,12 +3,15 @@ package room import ( "common" "context" + commonpb "gen/libs/common/v1" "hwdb" + "hwgrpc" "hwutil" "github.com/google/uuid" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/wrapperspb" "tasks-svc/internal/tracking" "tasks-svc/repos/room_repo" @@ -102,8 +105,6 @@ func (ServiceServer) GetRoom(ctx context.Context, req *pb.GetRoomRequest) (*pb.G } func (ServiceServer) UpdateRoom(ctx context.Context, req *pb.UpdateRoomRequest) (*pb.UpdateRoomResponse, error) { - roomRepo := room_repo.New(hwdb.GetDB()) - // TODO: Auth patientID, err := uuid.Parse(req.GetId()) @@ -111,7 +112,20 @@ func (ServiceServer) UpdateRoom(ctx context.Context, req *pb.UpdateRoomRequest) return nil, status.Error(codes.InvalidArgument, err.Error()) } - consistency, err := roomRepo.UpdateRoom(ctx, room_repo.UpdateRoomParams{ + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + + // Start TX + tx, rollback, err := hwdb.BeginTx(hwdb.GetDB(), ctx) + if err != nil { + return nil, err + } + defer rollback() + roomRepo := room_repo.New(tx) + + result, err := roomRepo.UpdateRoom(ctx, room_repo.UpdateRoomParams{ ID: patientID, Name: req.Name, }) @@ -120,9 +134,42 @@ func (ServiceServer) UpdateRoom(ctx context.Context, req *pb.UpdateRoomRequest) return nil, err } + // conflict detection + if expConsistency != nil && *expConsistency != common.ConsistencyToken(result.OldConsistency) { //nolint:gosec + conflicts := make(map[string]*commonpb.AttributeConflict) + + if req.Name != nil && *req.Name != result.OldName { + conflicts["name"], err = hwgrpc.AttributeConflict( + wrapperspb.String(result.OldName), + wrapperspb.String(*req.Name), + ) + if err != nil { + return nil, err + } + } + + if len(conflicts) != 0 { + // prevent the update + if err := hwdb.Error(ctx, tx.Rollback(ctx)); err != nil { + return nil, err + } + + // return conflict + return &pb.UpdateRoomResponse{ + Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts}, + Consistency: common.ConsistencyToken(result.OldConsistency).String(), //nolint:gosec + }, nil + } + } + + // Commit Update + if err := hwdb.Error(ctx, tx.Commit(ctx)); err != nil { + return nil, err + } + return &pb.UpdateRoomResponse{ - Conflict: nil, // TODO - Consistency: common.ConsistencyToken(consistency).String(), //nolint:gosec + Conflict: nil, + Consistency: common.ConsistencyToken(result.Consistency).String(), //nolint:gosec }, nil } diff --git a/services/tasks-svc/internal/task-template/task_template.go b/services/tasks-svc/internal/task-template/task_template.go index 24a5ecda2..3bb17c566 100644 --- a/services/tasks-svc/internal/task-template/task_template.go +++ b/services/tasks-svc/internal/task-template/task_template.go @@ -4,12 +4,15 @@ import ( "common" "common/auth" "context" + commonpb "gen/libs/common/v1" "hwdb" + "hwgrpc" "hwutil" "github.com/google/uuid" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/wrapperspb" "tasks-svc/repos/task_template_repo" @@ -150,7 +153,7 @@ func (ServiceServer) DeleteTaskTemplateSubTask( } // increase consistency of taskTemplate - consistency, err := templateRepo.UpdateTaskTemplate(ctx, task_template_repo.UpdateTaskTemplateParams{ + ttResult, err := templateRepo.UpdateTaskTemplate(ctx, task_template_repo.UpdateTaskTemplateParams{ ID: subtask.TaskTemplateID, }) if err := hwdb.Error(ctx, err); err != nil { @@ -168,7 +171,7 @@ func (ServiceServer) DeleteTaskTemplateSubTask( Msg("taskTemplateSubtask deleted") return &pb.DeleteTaskTemplateSubTaskResponse{ - TaskTemplateConsistency: common.ConsistencyToken(consistency).String(), //nolint:gosec + TaskTemplateConsistency: common.ConsistencyToken(ttResult.Consistency).String(), //nolint:gosec }, nil } @@ -185,7 +188,20 @@ func (ServiceServer) UpdateTaskTemplate( return nil, status.Error(codes.InvalidArgument, err.Error()) } - consistency, err := templateRepo.UpdateTaskTemplate(ctx, task_template_repo.UpdateTaskTemplateParams{ + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + + // Start TX + tx, rollback, err := hwdb.BeginTx(hwdb.GetDB(), ctx) + if err != nil { + return nil, err + } + defer rollback() + + // do update + result, err := templateRepo.UpdateTaskTemplate(ctx, task_template_repo.UpdateTaskTemplateParams{ Name: req.Name, Description: req.Description, ID: id, @@ -195,9 +211,59 @@ func (ServiceServer) UpdateTaskTemplate( return nil, err } + // conflict detection + if expConsistency != nil && *expConsistency != common.ConsistencyToken(result.OldConsistency) { //nolint:gosec + // task_template is not event sourced yet and has more than one field, + // thus we are not able to pinpoint conflicts to a field, we only know *some* update has happened since + // for convenience we are filtering out obvious non-conflicts, where the update is the same as the is state, + // or the field was not changed + + conflicts := make(map[string]*commonpb.AttributeConflict) + + if req.Name != nil && *req.Name != result.OldName { + conflicts["name"], err = hwgrpc.AttributeConflict( + wrapperspb.String(result.OldName), + wrapperspb.String(*req.Name), + ) + if err != nil { + return nil, err + } + } + if req.Description != nil && *req.Description != result.OldDescription { + conflicts["description"], err = hwgrpc.AttributeConflict( + wrapperspb.String(result.OldDescription), + wrapperspb.String(*req.Description), + ) + if err != nil { + return nil, err + } + } + + if len(conflicts) != 0 { + // prevent the update + if err := hwdb.Error(ctx, tx.Rollback(ctx)); err != nil { + return nil, err + } + + // return conflict + return &pb.UpdateTaskTemplateResponse{ + Conflict: &commonpb.Conflict{ + ConflictingAttributes: conflicts, + HistoryMissing: true, + }, + Consistency: common.ConsistencyToken(result.OldConsistency).String(), //nolint:gosec + }, nil + } + } + + // Commit Update + if err := hwdb.Error(ctx, tx.Commit(ctx)); err != nil { + return nil, err + } + return &pb.UpdateTaskTemplateResponse{ - Conflict: nil, // TODO - Consistency: common.ConsistencyToken(consistency).String(), //nolint:gosec + Conflict: nil, + Consistency: common.ConsistencyToken(result.Consistency).String(), //nolint:gosec }, nil } @@ -220,10 +286,15 @@ func (ServiceServer) UpdateTaskTemplateSubTask( return nil, status.Error(codes.InvalidArgument, err.Error()) } + expConsistency, ok := common.ParseConsistency(req.TaskTemplateConsistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "task_template_consistency") + } + // update subtask and get related taskTemplate - taskTemplateID, err := templateRepo.UpdateSubtask(ctx, task_template_repo.UpdateSubtaskParams{ - Name: req.Name, + subTaskResult, err := templateRepo.UpdateSubtask(ctx, task_template_repo.UpdateSubtaskParams{ ID: id, + Name: req.Name, }) err = hwdb.Error(ctx, err) if err != nil { @@ -231,21 +302,51 @@ func (ServiceServer) UpdateTaskTemplateSubTask( } // increase consistency of taskTemplate - consistency, err := templateRepo.UpdateTaskTemplate(ctx, task_template_repo.UpdateTaskTemplateParams{ - ID: taskTemplateID, + result, err := templateRepo.UpdateTaskTemplate(ctx, task_template_repo.UpdateTaskTemplateParams{ + ID: subTaskResult.TaskTemplateID, }) if err := hwdb.Error(ctx, err); err != nil { return nil, err } + // conflict detection + if expConsistency != nil && *expConsistency != common.ConsistencyToken(result.OldConsistency) { //nolint:gosec + conflicts := make(map[string]*commonpb.AttributeConflict) + + if req.Name != nil && *req.Name != subTaskResult.OldName { + conflicts["name"], err = hwgrpc.AttributeConflict( + wrapperspb.String(subTaskResult.OldName), + wrapperspb.String(*req.Name), + ) + if err != nil { + return nil, err + } + } + + if len(conflicts) != 0 { + // prevent the updates + if err := hwdb.Error(ctx, tx.Rollback(ctx)); err != nil { + return nil, err + } + + // return conflict + return &pb.UpdateTaskTemplateSubTaskResponse{ + Conflict: &commonpb.Conflict{ + ConflictingAttributes: conflicts, + HistoryMissing: true, + }, + TaskTemplateConsistency: common.ConsistencyToken(result.OldConsistency).String(), //nolint:gosec + }, nil + } + } + // commit if err := hwdb.Error(ctx, tx.Commit(ctx)); err != nil { return nil, err } return &pb.UpdateTaskTemplateSubTaskResponse{ - Conflict: nil, // TODO - TaskTemplateConsistency: common.ConsistencyToken(consistency).String(), //nolint:gosec + TaskTemplateConsistency: common.ConsistencyToken(result.Consistency).String(), //nolint:gosec }, nil } diff --git a/services/tasks-svc/internal/task/aggregate/aggregate.go b/services/tasks-svc/internal/task/aggregate/aggregate.go index e1288ee30..f81d9374c 100644 --- a/services/tasks-svc/internal/task/aggregate/aggregate.go +++ b/services/tasks-svc/internal/task/aggregate/aggregate.go @@ -1,6 +1,7 @@ package aggregate import ( + "common" "context" "fmt" pb "gen/services/tasks_svc/v1" @@ -8,6 +9,7 @@ import ( "time" "github.com/google/uuid" + "github.com/jinzhu/copier" taskEventsV1 "tasks-svc/internal/task/events/v1" "tasks-svc/internal/task/models" @@ -41,6 +43,36 @@ func LoadTaskAggregate(ctx context.Context, as hwes.AggregateStore, id uuid.UUID return taskAggregate, nil } +func LoadTaskAggregateWithSnapshotAt( + ctx context.Context, + as hwes.AggregateStore, + id uuid.UUID, + pauseAt *common.ConsistencyToken, +) (*TaskAggregate, *models.Task, error) { + taskAggregate := NewTaskAggregate(id) + var snapshot *models.Task + + if pauseAt != nil { + // load pauseAt+1-many events (version is 0-indexed) + if err := as.LoadN(ctx, taskAggregate, uint64(*pauseAt)+1); err != nil { + return nil, nil, err + } + + var cpy models.Task + if err := copier.CopyWithOption(&cpy, taskAggregate.Task, copier.Option{DeepCopy: true}); err != nil { + return nil, nil, fmt.Errorf("LoadTaskAggregateWithSnapshotAt: could not copy snapshot: %w", err) + } + snapshot = &cpy + } + + // continue loading all other events + if err := as.Load(ctx, taskAggregate); err != nil { + return nil, nil, err + } + + return taskAggregate, snapshot, nil +} + func (a *TaskAggregate) initEventListeners() { a. RegisterEventListener(taskEventsV1.TaskCreated, a.onTaskCreated). diff --git a/services/tasks-svc/internal/task/api/grpc.go b/services/tasks-svc/internal/task/api/grpc.go index fd0e70f76..a734eb54c 100644 --- a/services/tasks-svc/internal/task/api/grpc.go +++ b/services/tasks-svc/internal/task/api/grpc.go @@ -1,19 +1,28 @@ package api import ( + "common" "common/auth" "context" + "errors" + "fmt" + commonpb "gen/libs/common/v1" pb "gen/services/tasks_svc/v1" "hwes" + "hwgrpc" "hwutil" + "time" "github.com/google/uuid" - "github.com/rs/zerolog/log" + zlog "github.com/rs/zerolog" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/timestamppb" + "google.golang.org/protobuf/types/known/wrapperspb" "tasks-svc/internal/task/handlers" + "tasks-svc/internal/task/models" ) type TaskGrpcService struct { @@ -63,16 +72,114 @@ func (s *TaskGrpcService) CreateTask(ctx context.Context, req *pb.CreateTaskRequ }, nil } +func timeAlreadyUpdated(was, is *time.Time) bool { + if was != nil && is != nil { + return !was.Round(time.Second).Equal(is.Round(time.Second)) + } + + return true +} + func (s *TaskGrpcService) UpdateTask(ctx context.Context, req *pb.UpdateTaskRequest) (*pb.UpdateTaskResponse, error) { + log := zlog.Ctx(ctx) + taskID, err := uuid.Parse(req.GetId()) if err != nil { return nil, err } - consistency, err := s.handlers.Commands.V1.UpdateTask( - ctx, taskID, req.Name, req.Description, req.Status, req.Public, req.DueAt) - if err != nil { - return nil, err + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + + var consistency common.ConsistencyToken + + for i := 0; true; i++ { + if i > 10 { + log.Warn().Msg("UpdatePatient: conflict circuit breaker triggered") + return nil, errors.New("failed conflict resolution") + } + + c, conflict, err := s.handlers.Commands.V1.UpdateTask(ctx, + taskID, req.Name, req.Description, req.Status, req.Public, req.DueAt, expConsistency) + if err != nil { + return nil, err + } + consistency = c + + if conflict == nil { + break + } + conflicts := make(map[string]*commonpb.AttributeConflict) + + // TODO: find a generic approach + nameUpdateRequested := req.Name != nil && *req.Name != conflict.Is.Name + nameAlreadyUpdated := conflict.Was.Name != conflict.Is.Name + if nameUpdateRequested && nameAlreadyUpdated { + conflicts["name"], err = hwgrpc.AttributeConflict( + wrapperspb.String(conflict.Is.Name), + wrapperspb.String(*req.Name), + ) + if err != nil { + return nil, err + } + } + + descrUpdateRequested := req.Description != nil && *req.Description != conflict.Is.Description + descrAlreadyUpdated := conflict.Was.Description != conflict.Is.Description + if descrUpdateRequested && descrAlreadyUpdated { + conflicts["description"], err = hwgrpc.AttributeConflict( + wrapperspb.String(conflict.Is.Description), + wrapperspb.String(*req.Description), + ) + if err != nil { + return nil, fmt.Errorf("could not marshall description conflict: %w", err) + } + } + + dueUpdateRequested := req.DueAt != nil && + (conflict.Is.DueAt == nil || !req.DueAt.AsTime().Round(time.Second).Equal(conflict.Is.DueAt.Round(time.Second))) + dueAlreadyUpdated := timeAlreadyUpdated(conflict.Was.DueAt, conflict.Is.DueAt) + if dueUpdateRequested && dueAlreadyUpdated { + var is proto.Message = nil + if conflict.Is.DueAt != nil { + is = timestamppb.New(*conflict.Is.DueAt) + } + conflicts["due_at"], err = hwgrpc.AttributeConflict( + is, + req.DueAt, + ) + if err != nil { + return nil, fmt.Errorf("could not marshall due_at conflict: %w", err) + } + } + + statusUpdateRequested := req.Status != nil && *req.Status != conflict.Is.Status + statusAlreadyUpdated := conflict.Was.Status != conflict.Is.Status + if statusUpdateRequested && statusAlreadyUpdated { + conflicts["status"], err = hwgrpc.AttributeConflict( + wrapperspb.Int32(int32(conflict.Is.Status)), + wrapperspb.Int32(int32(*req.Status)), + ) + if err != nil { + return nil, fmt.Errorf("could not marshall status conflict: %w", err) + } + } + + // bool public can never cause a problem + // the user expects public = B, and sets it to \neg B + // so either that is the case still, or the update will do nothing anyway + + if len(conflicts) != 0 { + return &pb.UpdateTaskResponse{ + Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts}, + Consistency: c.String(), + }, nil + } + + // no conflict? retry with new consistency + expConsistency = &c } return &pb.UpdateTaskResponse{ @@ -91,9 +198,55 @@ func (s *TaskGrpcService) AssignTask(ctx context.Context, req *pb.AssignTaskRequ return nil, err } - consistency, err := s.handlers.Commands.V1.AssignTask(ctx, taskID, userID) - if err != nil { - return nil, err + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + + var consistency common.ConsistencyToken + + for i := 0; true; i++ { + if i > 10 { + zlog.Ctx(ctx).Warn().Msg("UpdatePatient: conflict circuit breaker triggered") + return nil, errors.New("failed conflict resolution") + } + + c, conflict, err := s.handlers.Commands.V1.AssignTask(ctx, taskID, userID, expConsistency) + if err != nil { + return nil, err + } + consistency = c + if conflict == nil { + break + } + conflicts := make(map[string]*commonpb.AttributeConflict) + + // TODO: find a generic approach + userUpdateRequested := req.UserId != conflict.Is.AssignedUser.UUID.String() + userAlreadyUpdated := conflict.Was.AssignedUser != conflict.Is.AssignedUser + if userUpdateRequested && userAlreadyUpdated { + var is proto.Message = nil + if conflict.Is.AssignedUser.Valid { + is = wrapperspb.String(conflict.Is.AssignedUser.UUID.String()) + } + conflicts["user_id"], err = hwgrpc.AttributeConflict( + is, + wrapperspb.String(req.UserId), + ) + if err != nil { + return nil, err + } + } + + if len(conflicts) != 0 { + return &pb.AssignTaskResponse{ + Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts}, + Consistency: c.String(), + }, nil + } + + // no conflict? retry with new consistency + expConsistency = &c } return &pb.AssignTaskResponse{ @@ -227,6 +380,7 @@ func (s *TaskGrpcService) GetTasksByPatientSortedByStatus( ctx context.Context, req *pb.GetTasksByPatientSortedByStatusRequest, ) (*pb.GetTasksByPatientSortedByStatusResponse, error) { + log := zlog.Ctx(ctx) patientID, err := uuid.Parse(req.GetPatientId()) if err != nil { return nil, err @@ -399,10 +553,73 @@ func (s *TaskGrpcService) UpdateSubtask( return nil, err } - consistency, err := s.handlers.Commands.V1.UpdateSubtask( - ctx, taskID, subtaskID, req.Subtask.Name, req.Subtask.Done) - if err != nil { - return nil, err + expConsistency, ok := common.ParseConsistency(req.TaskConsistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "task_consistency") + } + + var consistency common.ConsistencyToken + + for i := 0; true; i++ { + if i > 10 { + zlog.Ctx(ctx).Warn().Msg("UpdateSubtask: conflict circuit breaker triggered") + return nil, errors.New("failed conflict resolution") + } + + c, conflict, err := s.handlers.Commands.V1.UpdateSubtask( + ctx, + taskID, + subtaskID, + req.Subtask.Name, + req.Subtask.Done, + expConsistency, + ) + if err != nil { + return nil, err + } + consistency = c + + if conflict == nil { + break + } + + conflicts := make(map[string]*commonpb.AttributeConflict) + + var was models.Subtask + if w, ok := conflict.Was.Subtasks[subtaskID]; ok { + was = w + } else { + return nil, errors.New("subtask did not exist at expConsistency") + } + + is := conflict.Is.Subtasks[subtaskID] // handler would have failed if non-existent + + // TODO: find a generic approach + nameUpdateRequested := req.Subtask.Name != nil && *req.Subtask.Name != is.Name + nameAlreadyUpdated := was.Name != is.Name + if nameUpdateRequested && nameAlreadyUpdated { + conflicts["name"], err = hwgrpc.AttributeConflict( + wrapperspb.String(is.Name), + wrapperspb.String(*req.Subtask.Name), + ) + if err != nil { + return nil, err + } + } + + if len(conflicts) != 0 { + return &pb.UpdateSubtaskResponse{ + Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts}, + TaskConsistency: c.String(), + }, nil + } + + // bool done can never cause a problem + // the user expects done = B, and sets it to \neg B + // so either that is the case still, or the update will do nothing anyway + + // no conflict? retry with new consistency + expConsistency = &c } return &pb.UpdateSubtaskResponse{ diff --git a/services/tasks-svc/internal/task/commands/v1/assign_task.go b/services/tasks-svc/internal/task/commands/v1/assign_task.go index 81f91b044..1203b14b8 100644 --- a/services/tasks-svc/internal/task/commands/v1/assign_task.go +++ b/services/tasks-svc/internal/task/commands/v1/assign_task.go @@ -8,22 +8,42 @@ import ( "github.com/google/uuid" "tasks-svc/internal/task/aggregate" + "tasks-svc/internal/task/models" ) -type AssignTaskCommandHandler func(ctx context.Context, taskID, userID uuid.UUID) (common.ConsistencyToken, error) +type AssignTaskCommandHandler func( + ctx context.Context, + taskID, + userID uuid.UUID, + expConsistency *common.ConsistencyToken, +) (common.ConsistencyToken, *common.Conflict[*models.Task], error) func NewAssignTaskCommandHandler(as hwes.AggregateStore) AssignTaskCommandHandler { - return func(ctx context.Context, taskID, userID uuid.UUID) (common.ConsistencyToken, error) { - task, err := aggregate.LoadTaskAggregate(ctx, as, taskID) + return func( + ctx context.Context, + taskID, + userID uuid.UUID, + expConsistency *common.ConsistencyToken, + ) (common.ConsistencyToken, *common.Conflict[*models.Task], error) { + task, oldState, err := aggregate.LoadTaskAggregateWithSnapshotAt(ctx, as, taskID, expConsistency) if err != nil { - return 0, err + return 0, nil, err + } + + newToken := common.ConsistencyToken(task.GetVersion()) + if expConsistency != nil && *expConsistency != newToken { + return newToken, &common.Conflict[*models.Task]{ + Was: oldState, + Is: task.Task, + }, nil } // TODO: Handle SelfAssignTask when common.GetUserID() is testable if err := task.AssignTask(ctx, userID); err != nil { - return 0, err + return 0, nil, err } - return as.Save(ctx, task) + consistency, err := as.Save(ctx, task) + return consistency, nil, err } } diff --git a/services/tasks-svc/internal/task/commands/v1/update_subtask.go b/services/tasks-svc/internal/task/commands/v1/update_subtask.go index 3983110fc..9f68c555b 100644 --- a/services/tasks-svc/internal/task/commands/v1/update_subtask.go +++ b/services/tasks-svc/internal/task/commands/v1/update_subtask.go @@ -9,6 +9,7 @@ import ( "github.com/google/uuid" "tasks-svc/internal/task/aggregate" + "tasks-svc/internal/task/models" ) type UpdateSubtaskCommandHandler func( @@ -17,7 +18,8 @@ type UpdateSubtaskCommandHandler func( subtaskID uuid.UUID, name *string, done *bool, -) (common.ConsistencyToken, error) + expConsistency *common.ConsistencyToken, +) (common.ConsistencyToken, *common.Conflict[*models.Task], error) func NewUpdateSubtaskCommandHandler(as hwes.AggregateStore) UpdateSubtaskCommandHandler { return func( @@ -26,29 +28,39 @@ func NewUpdateSubtaskCommandHandler(as hwes.AggregateStore) UpdateSubtaskCommand subtaskID uuid.UUID, name *string, done *bool, - ) (common.ConsistencyToken, error) { - a, err := aggregate.LoadTaskAggregate(ctx, as, taskID) + expConsistency *common.ConsistencyToken, + ) (common.ConsistencyToken, *common.Conflict[*models.Task], error) { + a, oldState, err := aggregate.LoadTaskAggregateWithSnapshotAt(ctx, as, taskID, expConsistency) if err != nil { - return 0, err + return 0, nil, err } currentSubtask, found := a.Task.Subtasks[subtaskID] if !found { - return 0, fmt.Errorf("subtask with ID: %s not found on Task with ID: %s", subtaskID, taskID) + return 0, nil, fmt.Errorf("subtask with ID: %s not found on Task with ID: %s", subtaskID, taskID) + } + + newToken := common.ConsistencyToken(a.GetVersion()) + if expConsistency != nil && *expConsistency != newToken { + return newToken, &common.Conflict[*models.Task]{ + Was: oldState, + Is: a.Task, + }, err } if name != nil && *name != currentSubtask.Name { if err := a.UpdateSubtaskName(ctx, subtaskID, *name); err != nil { - return 0, err + return 0, nil, err } } if done != nil && *done != currentSubtask.Done { if err := a.UpdateSubtaskDone(ctx, subtaskID, *done); err != nil { - return 0, err + return 0, nil, err } } - return as.Save(ctx, a) + consistency, err := as.Save(ctx, a) + return consistency, nil, err } } diff --git a/services/tasks-svc/internal/task/commands/v1/update_task.go b/services/tasks-svc/internal/task/commands/v1/update_task.go index a8c291f0a..c01319fc1 100644 --- a/services/tasks-svc/internal/task/commands/v1/update_task.go +++ b/services/tasks-svc/internal/task/commands/v1/update_task.go @@ -10,6 +10,7 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "tasks-svc/internal/task/aggregate" + "tasks-svc/internal/task/models" ) type UpdateTaskCommandHandler func( @@ -20,7 +21,8 @@ type UpdateTaskCommandHandler func( status *pb.TaskStatus, public *bool, dueAt *timestamppb.Timestamp, -) (common.ConsistencyToken, error) + expConsistency *common.ConsistencyToken, +) (common.ConsistencyToken, *common.Conflict[*models.Task], error) func NewUpdateTaskCommandHandler(as hwes.AggregateStore) UpdateTaskCommandHandler { return func( @@ -31,42 +33,52 @@ func NewUpdateTaskCommandHandler(as hwes.AggregateStore) UpdateTaskCommandHandle status *pb.TaskStatus, public *bool, dueAt *timestamppb.Timestamp, - ) (common.ConsistencyToken, error) { - a, err := aggregate.LoadTaskAggregate(ctx, as, taskID) + expConsistency *common.ConsistencyToken, + ) (common.ConsistencyToken, *common.Conflict[*models.Task], error) { + a, oldState, err := aggregate.LoadTaskAggregateWithSnapshotAt(ctx, as, taskID, expConsistency) if err != nil { - return 0, err + return 0, nil, err + } + + newToken := common.ConsistencyToken(a.GetVersion()) + if expConsistency != nil && *expConsistency != newToken { + return newToken, &common.Conflict[*models.Task]{ + Was: oldState, + Is: a.Task, + }, nil } if name != nil { if err := a.UpdateName(ctx, *name); err != nil { - return 0, err + return 0, nil, err } } if description != nil { if err := a.UpdateDescription(ctx, *description); err != nil { - return 0, err + return 0, nil, err } } if status != nil { if err := a.UpdateStatus(ctx, *status); err != nil { - return 0, err + return 0, nil, err } } if public != nil && a.Task.Public != *public { if err := a.UpdateTaskPublic(ctx, *public); err != nil { - return 0, err + return 0, nil, err } } if dueAt != nil { if err := a.UpdateDueAt(ctx, dueAt.AsTime()); err != nil { - return 0, err + return 0, nil, err } } - return as.Save(ctx, a) + consistency, err := as.Save(ctx, a) + return consistency, nil, err } } diff --git a/services/tasks-svc/internal/ward/ward.go b/services/tasks-svc/internal/ward/ward.go index 25207e60d..dada25056 100644 --- a/services/tasks-svc/internal/ward/ward.go +++ b/services/tasks-svc/internal/ward/ward.go @@ -3,14 +3,17 @@ package ward import ( "common" "context" + commonpb "gen/libs/common/v1" pb "gen/services/tasks_svc/v1" "hwdb" + "hwgrpc" "hwutil" "github.com/google/uuid" zlog "github.com/rs/zerolog/log" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/wrapperspb" "tasks-svc/internal/tracking" "tasks-svc/repos/ward_repo" @@ -144,8 +147,6 @@ func (ServiceServer) GetRecentWards( } func (ServiceServer) UpdateWard(ctx context.Context, req *pb.UpdateWardRequest) (*pb.UpdateWardResponse, error) { - wardRepo := ward_repo.New(hwdb.GetDB()) - // TODO: Auth id, err := uuid.Parse(req.GetId()) @@ -153,7 +154,21 @@ func (ServiceServer) UpdateWard(ctx context.Context, req *pb.UpdateWardRequest) return nil, status.Error(codes.InvalidArgument, err.Error()) } - consistency, err := wardRepo.UpdateWard(ctx, ward_repo.UpdateWardParams{ + expConsistency, ok := common.ParseConsistency(req.Consistency) + if !ok { + return nil, common.UnparsableConsistencyError(ctx, "consistency") + } + + // Start TX + tx, rollback, err := hwdb.BeginTx(hwdb.GetDB(), ctx) + if err != nil { + return nil, err + } + defer rollback() + wardRepo := ward_repo.New(tx) + + // Do Update + result, err := wardRepo.UpdateWard(ctx, ward_repo.UpdateWardParams{ ID: id, Name: req.Name, }) @@ -162,11 +177,44 @@ func (ServiceServer) UpdateWard(ctx context.Context, req *pb.UpdateWardRequest) return nil, err } + // conflict detection + if expConsistency != nil && *expConsistency != common.ConsistencyToken(result.OldConsistency) { //nolint:gosec + conflicts := make(map[string]*commonpb.AttributeConflict) + + if req.Name != nil && *req.Name != result.OldName { + conflicts["name"], err = hwgrpc.AttributeConflict( + wrapperspb.String(result.OldName), + wrapperspb.String(*req.Name), + ) + if err != nil { + return nil, err + } + } + + if len(conflicts) != 0 { + // prevent the update + if err := hwdb.Error(ctx, tx.Rollback(ctx)); err != nil { + return nil, err + } + + // return conflict + return &pb.UpdateWardResponse{ + Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts}, + Consistency: common.ConsistencyToken(result.OldConsistency).String(), //nolint:gosec + }, nil + } + } + + // Commit Update + if err := hwdb.Error(ctx, tx.Commit(ctx)); err != nil { + return nil, err + } + tracking.AddWardToRecentActivity(ctx, id.String()) return &pb.UpdateWardResponse{ - Conflict: nil, // TODO - Consistency: common.ConsistencyToken(consistency).String(), //nolint:gosec + Conflict: nil, + Consistency: common.ConsistencyToken(result.Consistency).String(), //nolint:gosec }, nil } diff --git a/services/tasks-svc/repos/bed_repo.sql b/services/tasks-svc/repos/bed_repo.sql index 2e415abe7..924473c9c 100644 --- a/services/tasks-svc/repos/bed_repo.sql +++ b/services/tasks-svc/repos/bed_repo.sql @@ -27,13 +27,25 @@ WHERE (room_id = sqlc.narg('room_id') OR sqlc.narg('room_id') IS NULL) ORDER BY name ASC; -- name: UpdateBed :one +WITH old_table AS ( + SELECT + name as old_name, + room_id as old_room_id, + consistency as old_consistency + FROM beds + WHERE beds.id = @id +) UPDATE beds SET name = coalesce(sqlc.narg('name'), name), room_id = coalesce(sqlc.narg('room_id'), room_id), consistency = consistency + 1 -WHERE id = @id -RETURNING consistency; +WHERE beds.id = @id +RETURNING + consistency, + (SELECT old_name FROM old_table), + (SELECT old_room_id FROM old_table), + (SELECT old_consistency FROM old_table); -- name: DeleteBed :exec DELETE FROM beds WHERE id = $1; diff --git a/services/tasks-svc/repos/bed_repo/bed_repo.sql.go b/services/tasks-svc/repos/bed_repo/bed_repo.sql.go index 654424f3a..4b8d6df2f 100644 --- a/services/tasks-svc/repos/bed_repo/bed_repo.sql.go +++ b/services/tasks-svc/repos/bed_repo/bed_repo.sql.go @@ -177,13 +177,25 @@ func (q *Queries) GetBeds(ctx context.Context, roomID uuid.NullUUID) ([]Bed, err } const updateBed = `-- name: UpdateBed :one +WITH old_table AS ( + SELECT + name as old_name, + room_id as old_room_id, + consistency as old_consistency + FROM beds + WHERE beds.id = $3 +) UPDATE beds SET name = coalesce($1, name), room_id = coalesce($2, room_id), consistency = consistency + 1 -WHERE id = $3 -RETURNING consistency +WHERE beds.id = $3 +RETURNING + consistency, + (SELECT old_name FROM old_table), + (SELECT old_room_id FROM old_table), + (SELECT old_consistency FROM old_table) ` type UpdateBedParams struct { @@ -192,9 +204,21 @@ type UpdateBedParams struct { ID uuid.UUID } -func (q *Queries) UpdateBed(ctx context.Context, arg UpdateBedParams) (int64, error) { +type UpdateBedRow struct { + Consistency int64 + OldName string + OldRoomID uuid.UUID + OldConsistency int64 +} + +func (q *Queries) UpdateBed(ctx context.Context, arg UpdateBedParams) (UpdateBedRow, error) { row := q.db.QueryRow(ctx, updateBed, arg.Name, arg.RoomID, arg.ID) - var consistency int64 - err := row.Scan(&consistency) - return consistency, err + var i UpdateBedRow + err := row.Scan( + &i.Consistency, + &i.OldName, + &i.OldRoomID, + &i.OldConsistency, + ) + return i, err } diff --git a/services/tasks-svc/repos/room_repo.sql b/services/tasks-svc/repos/room_repo.sql index aef4e4476..6a1275931 100644 --- a/services/tasks-svc/repos/room_repo.sql +++ b/services/tasks-svc/repos/room_repo.sql @@ -76,11 +76,21 @@ WHERE rooms.ward_id = @ward_id ORDER BY rooms.id ASC, beds.name ASC; -- name: UpdateRoom :one +WITH old_table AS ( + SELECT + name as old_name, + consistency as old_consistency + FROM rooms + WHERE rooms.id = @id +) UPDATE rooms SET name = coalesce(sqlc.narg('name'), name), consistency = consistency + 1 -WHERE id = @id -RETURNING consistency; +WHERE rooms.id = @id +RETURNING + consistency, + (SELECT old_name FROM old_table), + (SELECT old_consistency FROM old_table); -- name: DeleteRoom :exec DELETE FROM rooms WHERE id = @id; diff --git a/services/tasks-svc/repos/room_repo/room_repo.sql.go b/services/tasks-svc/repos/room_repo/room_repo.sql.go index 0e0a94b05..9c1bcd9a2 100644 --- a/services/tasks-svc/repos/room_repo/room_repo.sql.go +++ b/services/tasks-svc/repos/room_repo/room_repo.sql.go @@ -292,11 +292,21 @@ func (q *Queries) GetRoomsWithBedsWithPatientsByWard(ctx context.Context, wardID } const updateRoom = `-- name: UpdateRoom :one +WITH old_table AS ( + SELECT + name as old_name, + consistency as old_consistency + FROM rooms + WHERE rooms.id = $2 +) UPDATE rooms SET name = coalesce($1, name), consistency = consistency + 1 -WHERE id = $2 -RETURNING consistency +WHERE rooms.id = $2 +RETURNING + consistency, + (SELECT old_name FROM old_table), + (SELECT old_consistency FROM old_table) ` type UpdateRoomParams struct { @@ -304,9 +314,15 @@ type UpdateRoomParams struct { ID uuid.UUID } -func (q *Queries) UpdateRoom(ctx context.Context, arg UpdateRoomParams) (int64, error) { +type UpdateRoomRow struct { + Consistency int64 + OldName string + OldConsistency int64 +} + +func (q *Queries) UpdateRoom(ctx context.Context, arg UpdateRoomParams) (UpdateRoomRow, error) { row := q.db.QueryRow(ctx, updateRoom, arg.Name, arg.ID) - var consistency int64 - err := row.Scan(&consistency) - return consistency, err + var i UpdateRoomRow + err := row.Scan(&i.Consistency, &i.OldName, &i.OldConsistency) + return i, err } diff --git a/services/tasks-svc/repos/task_template_repo.sql b/services/tasks-svc/repos/task_template_repo.sql index a28ef0919..f6b315315 100644 --- a/services/tasks-svc/repos/task_template_repo.sql +++ b/services/tasks-svc/repos/task_template_repo.sql @@ -47,22 +47,41 @@ AND (task_templates.ward_id IS NULL OR NOT @private_only::bool) AND (task_templates.created_by = sqlc.narg('creator_id') OR sqlc.narg('creator_id') IS NULL); -- name: UpdateTaskTemplate :one +WITH old_table AS ( + SELECT + name as old_name, + description as old_description, + consistency as old_consistency + FROM task_templates + WHERE task_templates.id = @id +) UPDATE task_templates SET name = coalesce(sqlc.narg('name'), name), description = coalesce(sqlc.narg('description'), description), consistency = consistency + 1 -WHERE id = @id -RETURNING consistency; +WHERE task_templates.id = @id +RETURNING + consistency, + (SELECT old_name FROM old_table), + (SELECT old_description FROM old_table), + (SELECT old_consistency FROM old_table); -- name: UpdateSubtask :one +WITH old_table AS ( + SELECT name as old_name + FROM task_template_subtasks + WHERE task_template_subtasks.id = @id +) UPDATE task_template_subtasks ttst SET name = coalesce(sqlc.narg('name'), name) WHERE ttst.id = @id -RETURNING ( - SELECT tt.id - FROM task_templates tt - WHERE tt.id = ttst.task_template_id -); +RETURNING + ( + SELECT tt.id as task_template_id + FROM task_templates tt + WHERE tt.id = ttst.task_template_id + ), + (SELECT old_name FROM old_table); -- name: DeleteSubtask :one DELETE FROM task_template_subtasks WHERE id = @id RETURNING *; diff --git a/services/tasks-svc/repos/task_template_repo/task_template_repo.sql.go b/services/tasks-svc/repos/task_template_repo/task_template_repo.sql.go index 0e910f698..9ec248d65 100644 --- a/services/tasks-svc/repos/task_template_repo/task_template_repo.sql.go +++ b/services/tasks-svc/repos/task_template_repo/task_template_repo.sql.go @@ -203,14 +203,21 @@ func (q *Queries) GetTaskTemplateWithSubtasksByID(ctx context.Context, id uuid.U } const updateSubtask = `-- name: UpdateSubtask :one +WITH old_table AS ( + SELECT name as old_name + FROM task_template_subtasks + WHERE task_template_subtasks.id = $2 +) UPDATE task_template_subtasks ttst SET name = coalesce($1, name) WHERE ttst.id = $2 -RETURNING ( - SELECT tt.id - FROM task_templates tt - WHERE tt.id = ttst.task_template_id -) +RETURNING + ( + SELECT tt.id as task_template_id + FROM task_templates tt + WHERE tt.id = ttst.task_template_id + ), + (SELECT old_name FROM old_table) ` type UpdateSubtaskParams struct { @@ -218,20 +225,37 @@ type UpdateSubtaskParams struct { ID uuid.UUID } -func (q *Queries) UpdateSubtask(ctx context.Context, arg UpdateSubtaskParams) (uuid.UUID, error) { +type UpdateSubtaskRow struct { + TaskTemplateID uuid.UUID + OldName string +} + +func (q *Queries) UpdateSubtask(ctx context.Context, arg UpdateSubtaskParams) (UpdateSubtaskRow, error) { row := q.db.QueryRow(ctx, updateSubtask, arg.Name, arg.ID) - var id uuid.UUID - err := row.Scan(&id) - return id, err + var i UpdateSubtaskRow + err := row.Scan(&i.TaskTemplateID, &i.OldName) + return i, err } const updateTaskTemplate = `-- name: UpdateTaskTemplate :one +WITH old_table AS ( + SELECT + name as old_name, + description as old_description, + consistency as old_consistency + FROM task_templates + WHERE task_templates.id = $3 +) UPDATE task_templates SET name = coalesce($1, name), description = coalesce($2, description), consistency = consistency + 1 -WHERE id = $3 -RETURNING consistency +WHERE task_templates.id = $3 +RETURNING + consistency, + (SELECT old_name FROM old_table), + (SELECT old_description FROM old_table), + (SELECT old_consistency FROM old_table) ` type UpdateTaskTemplateParams struct { @@ -240,9 +264,21 @@ type UpdateTaskTemplateParams struct { ID uuid.UUID } -func (q *Queries) UpdateTaskTemplate(ctx context.Context, arg UpdateTaskTemplateParams) (int64, error) { +type UpdateTaskTemplateRow struct { + Consistency int64 + OldName string + OldDescription string + OldConsistency int64 +} + +func (q *Queries) UpdateTaskTemplate(ctx context.Context, arg UpdateTaskTemplateParams) (UpdateTaskTemplateRow, error) { row := q.db.QueryRow(ctx, updateTaskTemplate, arg.Name, arg.Description, arg.ID) - var consistency int64 - err := row.Scan(&consistency) - return consistency, err + var i UpdateTaskTemplateRow + err := row.Scan( + &i.Consistency, + &i.OldName, + &i.OldDescription, + &i.OldConsistency, + ) + return i, err } diff --git a/services/tasks-svc/repos/ward_repo.sql b/services/tasks-svc/repos/ward_repo.sql index 047603f12..2b5da17e0 100644 --- a/services/tasks-svc/repos/ward_repo.sql +++ b/services/tasks-svc/repos/ward_repo.sql @@ -55,11 +55,19 @@ SELECT EXISTS ( ) ward_exists; -- name: UpdateWard :one +WITH old_table AS ( + SELECT name as old_name, consistency as old_consistency + FROM wards + WHERE wards.id = @id +) UPDATE wards SET name = coalesce(sqlc.narg('name'), name), consistency = consistency + 1 -WHERE id = @id -RETURNING consistency; +WHERE wards.id = @id +RETURNING + consistency, + (SELECT old_name FROM old_table), + (SELECT old_consistency FROM old_table); -- name: DeleteWard :exec diff --git a/services/tasks-svc/repos/ward_repo/ward_repo.sql.go b/services/tasks-svc/repos/ward_repo/ward_repo.sql.go index cf67ca44a..de2967e37 100644 --- a/services/tasks-svc/repos/ward_repo/ward_repo.sql.go +++ b/services/tasks-svc/repos/ward_repo/ward_repo.sql.go @@ -228,11 +228,19 @@ func (q *Queries) GetWardsWithCounts(ctx context.Context, arg GetWardsWithCounts } const updateWard = `-- name: UpdateWard :one +WITH old_table AS ( + SELECT name as old_name, consistency as old_consistency + FROM wards + WHERE wards.id = $2 +) UPDATE wards SET name = coalesce($1, name), consistency = consistency + 1 -WHERE id = $2 -RETURNING consistency +WHERE wards.id = $2 +RETURNING + consistency, + (SELECT old_name FROM old_table), + (SELECT old_consistency FROM old_table) ` type UpdateWardParams struct { @@ -240,9 +248,15 @@ type UpdateWardParams struct { ID uuid.UUID } -func (q *Queries) UpdateWard(ctx context.Context, arg UpdateWardParams) (int64, error) { +type UpdateWardRow struct { + Consistency int64 + OldName string + OldConsistency int64 +} + +func (q *Queries) UpdateWard(ctx context.Context, arg UpdateWardParams) (UpdateWardRow, error) { row := q.db.QueryRow(ctx, updateWard, arg.Name, arg.ID) - var consistency int64 - err := row.Scan(&consistency) - return consistency, err + var i UpdateWardRow + err := row.Scan(&i.Consistency, &i.OldName, &i.OldConsistency) + return i, err } diff --git a/services/tasks-svc/stories/BedCRUD_test.go b/services/tasks-svc/stories/BedCRUD_test.go index dbd39237b..7c83ab0ea 100644 --- a/services/tasks-svc/stories/BedCRUD_test.go +++ b/services/tasks-svc/stories/BedCRUD_test.go @@ -9,6 +9,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/wrapperspb" + "github.com/stretchr/testify/require" ) @@ -177,3 +179,77 @@ func TestGetBeds(t *testing.T) { assert.Subset(t, expectedBedIDs, bedIds, "actual bedIDs are not a subset of expected for room %s", roomId) } } + +func TestUpdateBedConflict(t *testing.T) { + ctx := context.Background() + bedClient := bedServiceClient() + + // prepare + wardId, _ := prepareWard(t, ctx, "") + roomId0, _ := prepareRoom(t, ctx, wardId, "0") + + bedId, initialConsistency := prepareBed(t, ctx, roomId0, "") + + name1 := "This came first" + roomId1, _ := prepareRoom(t, ctx, wardId, "1") + + // update 1 + update1Res, err := bedClient.UpdateBed(ctx, &pb.UpdateBedRequest{ + Id: bedId, + Name: &name1, + RoomId: &roomId1, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, update1Res.Conflict) + assert.NotEqual(t, initialConsistency, update1Res.Consistency) + + name2 := "This came second" + roomId2, _ := prepareRoom(t, ctx, wardId, "2") + + // racing update 2 + update2Res, err := bedClient.UpdateBed(ctx, &pb.UpdateBedRequest{ + Id: bedId, + Name: &name2, + RoomId: &roomId2, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Equal(t, update1Res.Consistency, update2Res.Consistency) + assert.NotNil(t, update2Res.Conflict) + + nameRes := update2Res.Conflict.ConflictingAttributes["name"] + assert.NotNil(t, nameRes) + + nameIs := &wrapperspb.StringValue{} + require.NoError(t, nameRes.Is.UnmarshalTo(nameIs)) + assert.Equal(t, name1, nameIs.Value) + + nameWant := &wrapperspb.StringValue{} + require.NoError(t, nameRes.Want.UnmarshalTo(nameWant)) + assert.Equal(t, name2, nameWant.Value) //nolint:testifylint // false positive + + roomRes := update2Res.Conflict.ConflictingAttributes["room_id"] + assert.NotNil(t, roomRes) + + roomIs := &wrapperspb.StringValue{} + require.NoError(t, roomRes.Is.UnmarshalTo(roomIs)) + assert.Equal(t, roomId1, roomIs.Value) + + roomWant := &wrapperspb.StringValue{} + require.NoError(t, roomRes.Want.UnmarshalTo(roomWant)) + assert.Equal(t, roomId2, roomWant.Value) //nolint:testifylint // false positive + + // racing update 3 + update3Res, err := bedClient.UpdateBed(ctx, &pb.UpdateBedRequest{ + Id: bedId, + Name: &name2, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Equal(t, update1Res.Consistency, update2Res.Consistency) + assert.NotNil(t, update2Res.Conflict) + + assert.NotNil(t, update3Res.Conflict.ConflictingAttributes["name"]) + assert.Nil(t, update3Res.Conflict.ConflictingAttributes["room_id"]) +} diff --git a/services/tasks-svc/stories/PatientCRUD_test.go b/services/tasks-svc/stories/PatientCRUD_test.go index c4236958b..8c691cfb6 100644 --- a/services/tasks-svc/stories/PatientCRUD_test.go +++ b/services/tasks-svc/stories/PatientCRUD_test.go @@ -6,6 +6,7 @@ import ( "hwtesting" "hwutil" "strconv" + "strings" "testing" "time" @@ -93,6 +94,7 @@ func TestCreateUpdateGetPatient(t *testing.T) { readmitRes, err := patientClient.ReadmitPatient(ctx, &pb.ReadmitPatientRequest{PatientId: patientId}) require.NoError(t, err) assert.NotEqual(t, getPatientRes.Consistency, readmitRes.Consistency) + hwtesting.WaitForProjectionsToSettle() // // get re-admitted patient @@ -628,7 +630,7 @@ func TestGetPatientDetails(t *testing.T) { func TestGetRecentPatients(t *testing.T) { userID := uuid.New() // new user for this test, to prevent interference with other tests - patientClient := pb.NewPatientServiceClient(hwtesting.GetGrpcConn(userID.String())) + patientClient := pb.NewPatientServiceClient(hwtesting.GetGrpcConn(userID.String(), "")) ctx := context.Background() wardID, _ := prepareWard(t, ctx, "") @@ -688,3 +690,243 @@ func TestGetRecentPatients(t *testing.T) { assert.Subset(t, ids, foundIds) assert.NotContains(t, foundIds, ids[0]) // thrown out } + +func TestUpdatePatientConflict(t *testing.T) { + ctx := context.Background() + patientClient := patientServiceClient() + + A := "A" + B := "B" + C := "C" + + // Only testing HumanReadableIdentifier + testMatrix := []struct { + was string + is string + want *string + expectConflict bool + }{ + {A, B, nil, false}, + {A, B, &B, false}, + {A, B, &C, true}, + {A, A, &C, false}, + } + + for i, o := range testMatrix { + t.Run(t.Name()+" "+strconv.Itoa(i), func(t *testing.T) { + // WAS + patientRes, err := patientClient.CreatePatient(ctx, &pb.CreatePatientRequest{ + HumanReadableIdentifier: o.was, + Notes: hwutil.PtrTo("A patient for test " + t.Name()), + }) + require.NoError(t, err) + + id := patientRes.Id + initialConsistency := patientRes.Consistency + hwtesting.WaitForProjectionsToSettle() + + // IS + _, err = patientClient.UpdatePatient(ctx, &pb.UpdatePatientRequest{ + Id: id, + HumanReadableIdentifier: &o.is, + Notes: hwutil.PtrTo("Update"), + Consistency: &initialConsistency, + }) + require.NoError(t, err) + hwtesting.WaitForProjectionsToSettle() + + // WANT + updateRes, err := patientClient.UpdatePatient(ctx, &pb.UpdatePatientRequest{ + Id: id, + HumanReadableIdentifier: o.want, + Notes: hwutil.PtrTo("Update"), + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // EXPECT + assert.Equal(t, o.expectConflict, updateRes.Conflict != nil) + if o.expectConflict { + conflict := updateRes.Conflict.ConflictingAttributes["human_readable_identifier"] + assert.NotNil(t, conflict) + exp := "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"B\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"C\"}}" + assert.Equal(t, exp, strings.Replace(conflict.String(), " ", " ", 1)) + } + }) + } +} + +func TestAssignBedConflict(t *testing.T) { + ctx := context.Background() + patientClient := patientServiceClient() + + wardId, _ := prepareWard(t, ctx, "") + roomId, _ := prepareRoom(t, ctx, wardId, "") + + A, _ := prepareBed(t, ctx, roomId, "A") + B, _ := prepareBed(t, ctx, roomId, "B") + C, _ := prepareBed(t, ctx, roomId, "C") + + testMatrix := []struct { + was string + is *string + want string + expectConflict bool + }{ + {A, &B, B, false}, + {A, &B, C, true}, + {A, &A, C, false}, + {A, nil, C, true}, + } + + for i, o := range testMatrix { + t.Run(t.Name()+"_"+strconv.Itoa(i), func(t *testing.T) { + // WAS + patientRes, err := patientClient.CreatePatient(ctx, &pb.CreatePatientRequest{ + HumanReadableIdentifier: t.Name(), + Notes: hwutil.PtrTo("A patient for test " + t.Name()), + }) + require.NoError(t, err) + hwtesting.WaitForProjectionsToSettle() + + initialAssignment, err := patientClient.AssignBed(ctx, &pb.AssignBedRequest{ + Id: patientRes.Id, + BedId: o.was, + Consistency: &patientRes.Consistency, + }) + require.NoError(t, err) + assert.Nil(t, initialAssignment.Conflict) + + id := patientRes.Id + initialConsistency := initialAssignment.Consistency + + hwtesting.WaitForProjectionsToSettle() + + // IS + if o.is != nil { + a, err := patientClient.AssignBed(ctx, &pb.AssignBedRequest{ + Id: id, + BedId: *o.is, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, a.Conflict) + } else { + u, err := patientClient.UnassignBed(ctx, &pb.UnassignBedRequest{ + Id: id, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, u.Conflict) + } + hwtesting.WaitForProjectionsToSettle() + + // WANT + updateRes, err := patientClient.AssignBed(ctx, &pb.AssignBedRequest{ + Id: id, + BedId: o.want, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // EXPECT + assert.Equal(t, o.expectConflict, updateRes.Conflict != nil) + if o.expectConflict { + conflict := updateRes.Conflict.ConflictingAttributes["bed_id"] + assert.NotNil(t, conflict) + + exp := "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + o.want + "\"}}" + if o.is != nil { + exp = "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + *o.is + "\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + o.want + "\"}}" + } + assert.Equal(t, exp, strings.Replace(conflict.String(), " ", " ", 1)) + } + }) + } +} + +func TestUnassignBedConflict(t *testing.T) { + ctx := context.Background() + patientClient := patientServiceClient() + + wardId, _ := prepareWard(t, ctx, "") + roomId, _ := prepareRoom(t, ctx, wardId, "") + + A, _ := prepareBed(t, ctx, roomId, "A") + B, _ := prepareBed(t, ctx, roomId, "B") + + testMatrix := []struct { + was string + is *string + expectConflict bool + }{ + {A, &B, true}, + {A, &A, false}, + {A, nil, false}, + } + + for i, o := range testMatrix { + t.Run(t.Name()+"_"+strconv.Itoa(i), func(t *testing.T) { + // WAS + patientRes, err := patientClient.CreatePatient(ctx, &pb.CreatePatientRequest{ + HumanReadableIdentifier: t.Name(), + Notes: hwutil.PtrTo("A patient for test " + t.Name()), + }) + require.NoError(t, err) + hwtesting.WaitForProjectionsToSettle() + + initialAssignment, err := patientClient.AssignBed(ctx, &pb.AssignBedRequest{ + Id: patientRes.Id, + BedId: o.was, + Consistency: &patientRes.Consistency, + }) + require.NoError(t, err) + assert.Nil(t, initialAssignment.Conflict) + + id := patientRes.Id + initialConsistency := initialAssignment.Consistency + + hwtesting.WaitForProjectionsToSettle() + + // IS + if o.is != nil { + a, err := patientClient.AssignBed(ctx, &pb.AssignBedRequest{ + Id: id, + BedId: *o.is, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, a.Conflict) + } else { + u, err := patientClient.UnassignBed(ctx, &pb.UnassignBedRequest{ + Id: id, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, u.Conflict) + } + hwtesting.WaitForProjectionsToSettle() + + // WANT + updateRes, err := patientClient.UnassignBed(ctx, &pb.UnassignBedRequest{ + Id: id, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // EXPECT + assert.Equal(t, o.expectConflict, updateRes.Conflict != nil) + if o.expectConflict { + conflict := updateRes.Conflict.ConflictingAttributes["bed_id"] + assert.NotNil(t, conflict) + exp := "" + if o.is != nil { + exp = "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + *o.is + "\"}}" + } + assert.Equal(t, exp, conflict.String()) + } + }) + } +} diff --git a/services/tasks-svc/stories/RoomCRUD_test.go b/services/tasks-svc/stories/RoomCRUD_test.go index cd9721cdd..66d5782d5 100644 --- a/services/tasks-svc/stories/RoomCRUD_test.go +++ b/services/tasks-svc/stories/RoomCRUD_test.go @@ -10,6 +10,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/wrapperspb" + "github.com/stretchr/testify/require" ) @@ -288,3 +290,47 @@ func TestGetRoomOverviewsByWard(t *testing.T) { assert.JSONEq(t, string(expectedRoomAJson), string(resRoomAJson)) assert.JSONEq(t, string(expectedRoomBJson), string(resRoomBJson)) } + +func TestUpdateRoomConflict(t *testing.T) { + ctx := context.Background() + roomClient := roomServiceClient() + + // prepare + wardId, _ := prepareWard(t, ctx, "") + roomId, initialConsistency := prepareRoom(t, ctx, wardId, "") + + name1 := "This came first" + + // update 1 + update1Res, err := roomClient.UpdateRoom(ctx, &pb.UpdateRoomRequest{ + Id: roomId, + Name: &name1, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, update1Res.Conflict) + assert.NotEqual(t, initialConsistency, update1Res.Consistency) + + name2 := "This came second" + + // racing update 2 + update2Res, err := roomClient.UpdateRoom(ctx, &pb.UpdateRoomRequest{ + Id: roomId, + Name: &name2, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Equal(t, update1Res.Consistency, update2Res.Consistency) + assert.NotNil(t, update2Res.Conflict) + + nameRes := update2Res.Conflict.ConflictingAttributes["name"] + assert.NotNil(t, nameRes) + + nameIs := &wrapperspb.StringValue{} + require.NoError(t, nameRes.Is.UnmarshalTo(nameIs)) + assert.Equal(t, name1, nameIs.Value) + + nameWant := &wrapperspb.StringValue{} + require.NoError(t, nameRes.Want.UnmarshalTo(nameWant)) + assert.Equal(t, name2, nameWant.Value) //nolint:testifylint // false positive +} diff --git a/services/tasks-svc/stories/TaskCRUD_test.go b/services/tasks-svc/stories/TaskCRUD_test.go index bb86d0a1e..a45ef377c 100644 --- a/services/tasks-svc/stories/TaskCRUD_test.go +++ b/services/tasks-svc/stories/TaskCRUD_test.go @@ -203,9 +203,8 @@ func TestCreateUpdateGetTask(t *testing.T) { // unassignRes, err := taskClient.UnassignTask(ctx, &pb.UnassignTaskRequest{ - TaskId: taskId, - UserId: assignedUser.String(), - Consistency: &task.Consistency, + TaskId: taskId, + UserId: assignedUser.String(), }) require.NoError(t, err) @@ -373,7 +372,7 @@ func TestGetAssignedTasks(t *testing.T) { hwtesting.WaitForProjectionsToSettle() // client for userid - customTaskClient := pb.NewTaskServiceClient(hwtesting.GetGrpcConn(userID.String())) + customTaskClient := pb.NewTaskServiceClient(hwtesting.GetGrpcConn(userID.String(), "")) res, err := customTaskClient.GetAssignedTasks(ctx, &pb.GetAssignedTasksRequest{}) require.NoError(t, err) diff --git a/services/tasks-svc/stories/TaskConflicts_test.go b/services/tasks-svc/stories/TaskConflicts_test.go new file mode 100644 index 000000000..c2b59e276 --- /dev/null +++ b/services/tasks-svc/stories/TaskConflicts_test.go @@ -0,0 +1,471 @@ +package stories + +import ( + "context" + pb "gen/services/tasks_svc/v1" + "math" + "strconv" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestUpdateTaskConflict_Name(t *testing.T) { + ctx := context.Background() + taskClient := taskServiceClient() + + patientId := preparePatient(t, ctx, "") + + A := "A" + B := "B" + C := "C" + + testMatrix := []struct { + was string + is string + want *string + expectConflict bool + }{ + {A, B, nil, false}, + {A, B, &B, false}, + {A, B, &C, true}, + {A, A, &C, false}, + } + + for i, o := range testMatrix { + t.Run(t.Name()+"_"+strconv.Itoa(i), func(t *testing.T) { + // WAS + task, err := taskClient.CreateTask(ctx, &pb.CreateTaskRequest{ + Name: o.was, + Description: nil, + PatientId: patientId, + Public: nil, + DueAt: nil, + InitialStatus: nil, + AssignedUserId: nil, + Subtasks: nil, + }) + require.NoError(t, err) + + id := task.Id + initialConsistency := task.Consistency + + // IS + _, err = taskClient.UpdateTask(ctx, &pb.UpdateTaskRequest{ + Id: id, + Name: &o.is, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // WANT + updateRes, err := taskClient.UpdateTask(ctx, &pb.UpdateTaskRequest{ + Id: id, + Name: o.want, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // EXPECT + assert.Equal(t, o.expectConflict, updateRes.Conflict != nil) + if o.expectConflict { + conflict := updateRes.Conflict.ConflictingAttributes["name"] + assert.NotNil(t, conflict) + exp := "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"B\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"C\"}}" + assert.Equal(t, exp, strings.Replace(conflict.String(), " ", " ", 1)) + } + }) + } +} + +func TestUpdateTaskConflict_Description(t *testing.T) { + ctx := context.Background() + taskClient := taskServiceClient() + + patientId := preparePatient(t, ctx, "") + + A := "A" + B := "B" + C := "C" + + testMatrix := []struct { + was string + is string + want *string + expectConflict bool + }{ + {A, B, nil, false}, + {A, B, &B, false}, + {A, B, &C, true}, + {A, A, &C, false}, + } + + for i, o := range testMatrix { + t.Run(t.Name()+"_"+strconv.Itoa(i), func(t *testing.T) { + // WAS + task, err := taskClient.CreateTask(ctx, &pb.CreateTaskRequest{ + Name: t.Name(), + Description: &o.was, + PatientId: patientId, + Public: nil, + DueAt: nil, + InitialStatus: nil, + AssignedUserId: nil, + Subtasks: nil, + }) + require.NoError(t, err) + + id := task.Id + initialConsistency := task.Consistency + + // IS + _, err = taskClient.UpdateTask(ctx, &pb.UpdateTaskRequest{ + Id: id, + Description: &o.is, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // WANT + updateRes, err := taskClient.UpdateTask(ctx, &pb.UpdateTaskRequest{ + Id: id, + Description: o.want, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // EXPECT + assert.Equal(t, o.expectConflict, updateRes.Conflict != nil) + if o.expectConflict { + conflict := updateRes.Conflict.ConflictingAttributes["description"] + assert.NotNil(t, conflict) + exp := "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"B\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"C\"}}" + assert.Equal(t, exp, strings.Replace(conflict.String(), " ", " ", 1)) + } + }) + } +} + +func TestUpdateTaskConflict_DueAt(t *testing.T) { + ctx := context.Background() + taskClient := taskServiceClient() + + patientId := preparePatient(t, ctx, "") + + A := timestamppb.New(time.Now()) + B := timestamppb.New(time.Now().Add(time.Hour)) + C := timestamppb.New(time.Now().Add(time.Hour * 2)) + + testMatrix := []struct { + was *timestamppb.Timestamp + is *timestamppb.Timestamp + want *timestamppb.Timestamp + expectConflict bool + }{ + {A, B, nil, false}, + {A, B, B, false}, + {A, B, C, true}, + {A, A, C, false}, + {nil, B, C, true}, + {nil, C, C, false}, + } + + for i, o := range testMatrix { + t.Run(t.Name()+"_"+strconv.Itoa(i), func(t *testing.T) { + // WAS + task, err := taskClient.CreateTask(ctx, &pb.CreateTaskRequest{ + Name: t.Name(), + Description: nil, + PatientId: patientId, + Public: nil, + DueAt: o.was, + InitialStatus: nil, + AssignedUserId: nil, + Subtasks: nil, + }) + require.NoError(t, err) + + id := task.Id + initialConsistency := task.Consistency + + // IS + _, err = taskClient.UpdateTask(ctx, &pb.UpdateTaskRequest{ + Id: id, + DueAt: o.is, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // WANT + updateRes, err := taskClient.UpdateTask(ctx, &pb.UpdateTaskRequest{ + Id: id, + DueAt: o.want, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // EXPECT + assert.Equal(t, o.expectConflict, updateRes.Conflict != nil) + if o.expectConflict { + conflict := updateRes.Conflict.ConflictingAttributes["due_at"] + assert.NotNil(t, conflict) + exp := "is:{[type.googleapis.com/google.protobuf.Timestamp]:{" + o.is.String() + "}} " + + "want:{[type.googleapis.com/google.protobuf.Timestamp]:{" + o.want.String() + "}}" + assert.Equal(t, + strings.Replace(exp, " ", " ", math.MaxInt), + strings.Replace(conflict.String(), " ", " ", math.MaxInt), + ) + } + }) + } +} + +func TestUpdateTaskConflict_Status(t *testing.T) { + ctx := context.Background() + taskClient := taskServiceClient() + + patientId := preparePatient(t, ctx, "") + + A := pb.TaskStatus_TASK_STATUS_TODO + B := pb.TaskStatus_TASK_STATUS_IN_PROGRESS + C := pb.TaskStatus_TASK_STATUS_DONE + + testMatrix := []struct { + was pb.TaskStatus + is *pb.TaskStatus + want *pb.TaskStatus + expectConflict bool + }{ + {A, &B, nil, false}, + {A, &B, &B, false}, + {A, &B, &C, true}, + {A, &A, &C, false}, + } + + for i, o := range testMatrix { + t.Run(t.Name()+"_"+strconv.Itoa(i), func(t *testing.T) { + // WAS + task, err := taskClient.CreateTask(ctx, &pb.CreateTaskRequest{ + Name: t.Name(), + Description: nil, + PatientId: patientId, + Public: nil, + DueAt: nil, + InitialStatus: &o.was, + AssignedUserId: nil, + Subtasks: nil, + }) + require.NoError(t, err) + + id := task.Id + initialConsistency := task.Consistency + + // IS + _, err = taskClient.UpdateTask(ctx, &pb.UpdateTaskRequest{ + Id: id, + Status: o.is, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // WANT + updateRes, err := taskClient.UpdateTask(ctx, &pb.UpdateTaskRequest{ + Id: id, + Status: o.want, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // EXPECT + assert.Equal(t, o.expectConflict, updateRes.Conflict != nil) + if o.expectConflict { + conflict := updateRes.Conflict.ConflictingAttributes["status"] + assert.NotNil(t, conflict) + exp := "want:{[type.googleapis.com/google.protobuf.Int32Value]:{value:" + strconv.Itoa(int(*o.want)) + "}}" + + if o.is != nil { + exp = "is:{[type.googleapis.com/google.protobuf.Int32Value]:{value:" + strconv.Itoa(int(*o.is)) + "}} " + + "want:{[type.googleapis.com/google.protobuf.Int32Value]:{value:" + strconv.Itoa(int(*o.want)) + "}}" + } + assert.Equal(t, exp, strings.Replace(conflict.String(), " ", " ", 1)) + } + }) + } +} + +func TestAssignTaskConflict(t *testing.T) { + ctx := context.Background() + taskClient := taskServiceClient() + + patientId := preparePatient(t, ctx, "") + + A := uuid.New().String() + B := uuid.New().String() + C := uuid.New().String() + + testMatrix := []struct { + was *string + is *string + want string + expectConflict bool + }{ + {&A, &B, B, false}, + {&A, &B, C, true}, + {&A, &A, C, false}, + {nil, &A, C, true}, + {&A, nil, C, true}, + } + + for i, o := range testMatrix { + t.Run(t.Name()+"_"+strconv.Itoa(i), func(t *testing.T) { + // WAS + task, err := taskClient.CreateTask(ctx, &pb.CreateTaskRequest{ + Name: t.Name(), + Description: nil, + PatientId: patientId, + Public: nil, + DueAt: nil, + InitialStatus: nil, + AssignedUserId: o.was, + Subtasks: nil, + }) + require.NoError(t, err) + + id := task.Id + initialConsistency := task.Consistency + + // IS + if o.is != nil { + a, err := taskClient.AssignTask(ctx, &pb.AssignTaskRequest{ + TaskId: id, + UserId: *o.is, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, a.Conflict) + } else { + a, err := taskClient.UnassignTask(ctx, &pb.UnassignTaskRequest{ + TaskId: id, + UserId: *o.was, + }) + require.NoError(t, err) + assert.Nil(t, a.Conflict) + } + + // WANT + updateRes, err := taskClient.AssignTask(ctx, &pb.AssignTaskRequest{ + TaskId: id, + UserId: o.want, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + + // EXPECT + assert.Equal(t, o.expectConflict, updateRes.Conflict != nil) + if o.expectConflict { + conflict := updateRes.Conflict.ConflictingAttributes["user_id"] + assert.NotNil(t, conflict) + exp := "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + o.want + "\"}}" + if o.is != nil { + exp = "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + *o.is + "\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + o.want + "\"}}" + } + assert.Equal(t, exp, strings.Replace(conflict.String(), " ", " ", 1)) + } + }) + } +} + +func TestUpdateSubtaskConflict(t *testing.T) { + ctx := context.Background() + taskClient := taskServiceClient() + + patientId := preparePatient(t, ctx, "") + + A := "A" + B := "B" + C := "C" + + testMatrix := []struct { + was string + is string + want string + expectConflict bool + }{ + {A, B, B, false}, + {A, B, C, true}, + {A, A, C, false}, + } + + for i, o := range testMatrix { + t.Run(t.Name()+"_"+strconv.Itoa(i), func(t *testing.T) { + // WAS + task, err := taskClient.CreateTask(ctx, &pb.CreateTaskRequest{ + Name: t.Name(), + Description: nil, + PatientId: patientId, + Public: nil, + DueAt: nil, + InitialStatus: nil, + AssignedUserId: nil, + Subtasks: nil, + }) + require.NoError(t, err) + + subTask, err := taskClient.CreateSubtask(ctx, &pb.CreateSubtaskRequest{ + TaskId: task.Id, + Subtask: &pb.CreateSubtaskRequest_Subtask{ + Name: o.was, + Done: nil, + }, + }) + require.NoError(t, err) + + taskId := task.Id + id := subTask.SubtaskId + initialConsistency := subTask.TaskConsistency + + // IS + a, err := taskClient.UpdateSubtask(ctx, &pb.UpdateSubtaskRequest{ + TaskId: taskId, + SubtaskId: id, + Subtask: &pb.UpdateSubtaskRequest_Subtask{ + Name: &o.is, + }, + TaskConsistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, a.Conflict) + + // WANT + updateRes, err := taskClient.UpdateSubtask(ctx, &pb.UpdateSubtaskRequest{ + TaskId: taskId, + SubtaskId: id, + Subtask: &pb.UpdateSubtaskRequest_Subtask{ + Name: &o.want, + }, + TaskConsistency: &initialConsistency, + }) + require.NoError(t, err) + + // EXPECT + assert.Equal(t, o.expectConflict, updateRes.Conflict != nil) + if o.expectConflict { + conflict := updateRes.Conflict.ConflictingAttributes["name"] + assert.NotNil(t, conflict) + + exp := "is:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + o.is + "\"}} " + + "want:{[type.googleapis.com/google.protobuf.StringValue]:{value:\"" + o.want + "\"}}" + assert.Equal(t, exp, strings.Replace(conflict.String(), " ", " ", 1)) + } + }) + } +} diff --git a/services/tasks-svc/stories/TaskTemplateCRUD_test.go b/services/tasks-svc/stories/TaskTemplateCRUD_test.go index 083e27138..90b1a446f 100644 --- a/services/tasks-svc/stories/TaskTemplateCRUD_test.go +++ b/services/tasks-svc/stories/TaskTemplateCRUD_test.go @@ -8,6 +8,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/wrapperspb" + "github.com/stretchr/testify/require" ) @@ -161,3 +163,124 @@ func TestCreateUpdateGetTaskTemplate(t *testing.T) { require.NoError(t, err) assert.Len(t, templates.Templates, 2) } + +func TestUpdateTaskTemplateConflict(t *testing.T) { + ctx := context.Background() + taskTemplateClient := taskTemplateServiceClient() + + ttRes, err := taskTemplateClient.CreateTaskTemplate(ctx, &pb.CreateTaskTemplateRequest{ + Name: t.Name(), + Description: nil, + WardId: nil, + Subtasks: nil, + }) + require.NoError(t, err) + + ttId := ttRes.Id + initialConsistency := ttRes.Consistency + + name1 := "This came first" + + // update 1 + update1Res, err := taskTemplateClient.UpdateTaskTemplate(ctx, &pb.UpdateTaskTemplateRequest{ + Id: ttId, + Name: &name1, + Description: &name1, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, update1Res.Conflict) + assert.NotEqual(t, initialConsistency, update1Res.Consistency) + + name2 := "This came second" + + // racing update 2 + update2Res, err := taskTemplateClient.UpdateTaskTemplate(ctx, &pb.UpdateTaskTemplateRequest{ + Id: ttId, + Name: &name2, + Description: &name2, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Equal(t, update1Res.Consistency, update2Res.Consistency) + assert.NotNil(t, update2Res.Conflict) + + nameRes := update2Res.Conflict.ConflictingAttributes["name"] + assert.NotNil(t, nameRes) + + nameIs := &wrapperspb.StringValue{} + require.NoError(t, nameRes.Is.UnmarshalTo(nameIs)) + assert.Equal(t, name1, nameIs.Value) + + nameWant := &wrapperspb.StringValue{} + require.NoError(t, nameRes.Want.UnmarshalTo(nameWant)) + assert.Equal(t, name2, nameWant.Value) //nolint:testifylint // false positive + + descrRes := update2Res.Conflict.ConflictingAttributes["description"] + assert.NotNil(t, descrRes) + + descrIs := &wrapperspb.StringValue{} + require.NoError(t, descrRes.Is.UnmarshalTo(descrIs)) + assert.Equal(t, name1, descrIs.Value) + + descrWant := &wrapperspb.StringValue{} + require.NoError(t, descrRes.Want.UnmarshalTo(descrWant)) + assert.Equal(t, name2, descrWant.Value) //nolint:testifylint // false positive +} + +func TestUpdateTaskTemplateSubTaskConflict(t *testing.T) { + ctx := context.Background() + taskTemplateClient := taskTemplateServiceClient() + + ttRes, err := taskTemplateClient.CreateTaskTemplate(ctx, &pb.CreateTaskTemplateRequest{ + Name: t.Name(), + Description: nil, + WardId: nil, + Subtasks: nil, + }) + require.NoError(t, err) + + stRes, err := taskTemplateClient.CreateTaskTemplateSubTask(ctx, &pb.CreateTaskTemplateSubTaskRequest{ + TaskTemplateId: ttRes.Id, + Name: t.Name(), + }) + require.NoError(t, err) + + stId := stRes.Id + initialConsistency := stRes.TaskTemplateConsistency + + name1 := "This came first" + + // update 1 + update1Res, err := taskTemplateClient.UpdateTaskTemplateSubTask(ctx, &pb.UpdateTaskTemplateSubTaskRequest{ + SubtaskId: stId, + Name: &name1, + TaskTemplateConsistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, update1Res.Conflict) + assert.NotEqual(t, initialConsistency, update1Res.TaskTemplateConsistency) + + name2 := "This came second" + + // racing update 2 + update2Res, err := taskTemplateClient.UpdateTaskTemplateSubTask(ctx, &pb.UpdateTaskTemplateSubTaskRequest{ + SubtaskId: stId, + Name: &name2, + TaskTemplateConsistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Equal(t, update1Res.TaskTemplateConsistency, update2Res.TaskTemplateConsistency) + assert.NotNil(t, update2Res.Conflict) + + nameRes := update2Res.Conflict.ConflictingAttributes["name"] + assert.NotNil(t, nameRes) + + nameIs := &wrapperspb.StringValue{} + require.NoError(t, nameRes.Is.UnmarshalTo(nameIs)) + assert.Equal(t, name1, nameIs.Value) + + nameWant := &wrapperspb.StringValue{} + require.NoError(t, nameRes.Want.UnmarshalTo(nameWant)) + assert.Equal(t, name2, nameWant.Value) //nolint:testifylint // false positive +} diff --git a/services/tasks-svc/stories/WardCRUD_test.go b/services/tasks-svc/stories/WardCRUD_test.go index ed608bd20..a13d288b9 100644 --- a/services/tasks-svc/stories/WardCRUD_test.go +++ b/services/tasks-svc/stories/WardCRUD_test.go @@ -11,6 +11,8 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/wrapperspb" + "github.com/stretchr/testify/require" ) @@ -89,9 +91,9 @@ func prepareWards(t *testing.T, ctx context.Context, client pb.WardServiceClient func TestGetRecentWards(t *testing.T) { userID := uuid.New() // new user for this test, to prevent interference with other tests - wardClient := pb.NewWardServiceClient(hwtesting.GetGrpcConn(userID.String())) - taskClient := pb.NewTaskServiceClient(hwtesting.GetGrpcConn(userID.String())) - patientClient := pb.NewPatientServiceClient(hwtesting.GetGrpcConn(userID.String())) + wardClient := pb.NewWardServiceClient(hwtesting.GetGrpcConn(userID.String(), "")) + taskClient := pb.NewTaskServiceClient(hwtesting.GetGrpcConn(userID.String(), "")) + patientClient := pb.NewPatientServiceClient(hwtesting.GetGrpcConn(userID.String(), "")) ctx := context.Background() wardIds := prepareWards(t, ctx, wardClient, 11) @@ -114,6 +116,8 @@ func TestGetRecentWards(t *testing.T) { Id: patientID, BedId: bedId, }) + hwtesting.WaitForProjectionsToSettle() + require.NoError(t, err, "could not assign bed to patient") _, err = taskClient.CreateTask(ctx, &pb.CreateTaskRequest{ Name: t.Name() + " Patient " + bedSuffix + " Task ", @@ -387,3 +391,46 @@ func TestGetWardDetails(t *testing.T) { assert.Equal(t, expected, actual) } + +func TestUpdateWardConflict(t *testing.T) { + ctx := context.Background() + wardClient := wardServiceClient() + + // prepare + wardId, initialConsistency := prepareWard(t, ctx, "") + + name1 := "This came first" + + // update 1 + update1Res, err := wardClient.UpdateWard(ctx, &pb.UpdateWardRequest{ + Id: wardId, + Name: &name1, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Nil(t, update1Res.Conflict) + assert.NotEqual(t, initialConsistency, update1Res.Consistency) + + name2 := "This came second" + + // racing update 2 + update2Res, err := wardClient.UpdateWard(ctx, &pb.UpdateWardRequest{ + Id: wardId, + Name: &name2, + Consistency: &initialConsistency, + }) + require.NoError(t, err) + assert.Equal(t, update1Res.Consistency, update2Res.Consistency) + assert.NotNil(t, update2Res.Conflict) + + nameRes := update2Res.Conflict.ConflictingAttributes["name"] + assert.NotNil(t, nameRes) + + nameIs := &wrapperspb.StringValue{} + require.NoError(t, nameRes.Is.UnmarshalTo(nameIs)) + assert.Equal(t, name1, nameIs.Value) + + nameWant := &wrapperspb.StringValue{} + require.NoError(t, nameRes.Want.UnmarshalTo(nameWant)) + assert.Equal(t, name2, nameWant.Value) //nolint:testifylint // false positive +} diff --git a/services/tasks-svc/stories/setup_test.go b/services/tasks-svc/stories/setup_test.go index b9c2a570e..86a9159da 100644 --- a/services/tasks-svc/stories/setup_test.go +++ b/services/tasks-svc/stories/setup_test.go @@ -71,27 +71,27 @@ func TestMain(m *testing.M) { } func bedServiceClient() pb.BedServiceClient { - return pb.NewBedServiceClient(hwtesting.GetGrpcConn("")) + return pb.NewBedServiceClient(hwtesting.GetGrpcConn("", "")) } func roomServiceClient() pb.RoomServiceClient { - return pb.NewRoomServiceClient(hwtesting.GetGrpcConn("")) + return pb.NewRoomServiceClient(hwtesting.GetGrpcConn("", "")) } func patientServiceClient() pb.PatientServiceClient { - return pb.NewPatientServiceClient(hwtesting.GetGrpcConn("")) + return pb.NewPatientServiceClient(hwtesting.GetGrpcConn("", "")) } func taskServiceClient() pb.TaskServiceClient { - return pb.NewTaskServiceClient(hwtesting.GetGrpcConn("")) + return pb.NewTaskServiceClient(hwtesting.GetGrpcConn("", "")) } func taskTemplateServiceClient() pb.TaskTemplateServiceClient { - return pb.NewTaskTemplateServiceClient(hwtesting.GetGrpcConn("")) + return pb.NewTaskTemplateServiceClient(hwtesting.GetGrpcConn("", "")) } func wardServiceClient() pb.WardServiceClient { - return pb.NewWardServiceClient(hwtesting.GetGrpcConn("")) + return pb.NewWardServiceClient(hwtesting.GetGrpcConn("", "")) } func prepareWard(t *testing.T, ctx context.Context, suffix string) (wardID, wardConsistency string) { diff --git a/services/updates-svc/stories/setup_test.go b/services/updates-svc/stories/setup_test.go index 66c14499e..5bfad4c9a 100644 --- a/services/updates-svc/stories/setup_test.go +++ b/services/updates-svc/stories/setup_test.go @@ -54,5 +54,5 @@ func TestMain(m *testing.M) { } func updatesServiceClient() pb.UpdatesServiceClient { - return pb.NewUpdatesServiceClient(hwtesting.GetGrpcConn("")) + return pb.NewUpdatesServiceClient(hwtesting.GetGrpcConn("", "")) }