@powersync/service-module-mongodb-storage 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/storage/MongoBucketStorage.d.ts +6 -4
  3. package/dist/storage/MongoBucketStorage.js +110 -36
  4. package/dist/storage/MongoBucketStorage.js.map +1 -1
  5. package/dist/storage/implementation/BucketDefinitionMapping.d.ts +4 -6
  6. package/dist/storage/implementation/BucketDefinitionMapping.js +3 -3
  7. package/dist/storage/implementation/BucketDefinitionMapping.js.map +1 -1
  8. package/dist/storage/implementation/CheckpointState.d.ts +20 -0
  9. package/dist/storage/implementation/CheckpointState.js +31 -0
  10. package/dist/storage/implementation/CheckpointState.js.map +1 -0
  11. package/dist/storage/implementation/MongoBucketBatch.d.ts +33 -22
  12. package/dist/storage/implementation/MongoBucketBatch.js +45 -271
  13. package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
  14. package/dist/storage/implementation/MongoChecksums.d.ts +2 -1
  15. package/dist/storage/implementation/MongoChecksums.js.map +1 -1
  16. package/dist/storage/implementation/MongoCompactor.d.ts +1 -1
  17. package/dist/storage/implementation/MongoPersistedSyncRules.d.ts +4 -4
  18. package/dist/storage/implementation/MongoPersistedSyncRules.js +11 -8
  19. package/dist/storage/implementation/MongoPersistedSyncRules.js.map +1 -1
  20. package/dist/storage/implementation/MongoPersistedSyncRulesContent.d.ts +19 -5
  21. package/dist/storage/implementation/MongoPersistedSyncRulesContent.js +53 -19
  22. package/dist/storage/implementation/MongoPersistedSyncRulesContent.js.map +1 -1
  23. package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +21 -10
  24. package/dist/storage/implementation/MongoSyncBucketStorage.js +18 -163
  25. package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
  26. package/dist/storage/implementation/MongoSyncRulesLock.d.ts +5 -1
  27. package/dist/storage/implementation/MongoSyncRulesLock.js +7 -3
  28. package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
  29. package/dist/storage/implementation/SyncRuleStateUpdate.d.ts +14 -0
  30. package/dist/storage/implementation/SyncRuleStateUpdate.js +36 -0
  31. package/dist/storage/implementation/SyncRuleStateUpdate.js.map +1 -0
  32. package/dist/storage/implementation/common/BucketDataDoc.d.ts +1 -1
  33. package/dist/storage/implementation/common/PersistedBatch.d.ts +2 -2
  34. package/dist/storage/implementation/common/SourceRecordStore.d.ts +1 -2
  35. package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.d.ts +1 -1
  36. package/dist/storage/implementation/createMongoSyncBucketStorage.d.ts +2 -2
  37. package/dist/storage/implementation/createMongoSyncBucketStorage.js.map +1 -1
  38. package/dist/storage/implementation/db.d.ts +10 -2
  39. package/dist/storage/implementation/db.js.map +1 -1
  40. package/dist/storage/implementation/models.d.ts +31 -47
  41. package/dist/storage/implementation/models.js.map +1 -1
  42. package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +15 -1
  43. package/dist/storage/implementation/v1/MongoBucketBatchV1.js +385 -0
  44. package/dist/storage/implementation/v1/MongoBucketBatchV1.js.map +1 -1
  45. package/dist/storage/implementation/v1/MongoCompactorV1.d.ts +1 -1
  46. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.d.ts +16 -7
  47. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +77 -6
  48. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js.map +1 -1
  49. package/dist/storage/implementation/v1/PersistedBatchV1.d.ts +1 -2
  50. package/dist/storage/implementation/v1/PersistedBatchV1.js.map +1 -1
  51. package/dist/storage/implementation/v1/models.d.ts +12 -1
  52. package/dist/storage/implementation/v1/models.js.map +1 -1
  53. package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +17 -0
  54. package/dist/storage/implementation/v3/MongoBucketBatchV3.js +429 -0
  55. package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -1
  56. package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +1 -1
  57. package/dist/storage/implementation/v3/MongoParameterLookupV3.d.ts +1 -2
  58. package/dist/storage/implementation/v3/MongoParameterLookupV3.js.map +1 -1
  59. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.d.ts +29 -7
  60. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +117 -16
  61. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -1
  62. package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +1 -2
  63. package/dist/storage/implementation/v3/PersistedBatchV3.js.map +1 -1
  64. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.d.ts +3 -2
  65. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +3 -0
  66. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js.map +1 -1
  67. package/dist/storage/implementation/v3/models.d.ts +61 -3
  68. package/dist/storage/implementation/v3/models.js.map +1 -1
  69. package/package.json +6 -6
  70. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +1 -1
  71. package/src/storage/MongoBucketStorage.ts +166 -44
  72. package/src/storage/implementation/BucketDefinitionMapping.ts +12 -9
  73. package/src/storage/implementation/CheckpointState.ts +59 -0
  74. package/src/storage/implementation/MongoBucketBatch.ts +81 -355
  75. package/src/storage/implementation/MongoChecksums.ts +2 -1
  76. package/src/storage/implementation/MongoCompactor.ts +1 -1
  77. package/src/storage/implementation/MongoPersistedSyncRules.ts +13 -7
  78. package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +69 -24
  79. package/src/storage/implementation/MongoSyncBucketStorage.ts +40 -215
  80. package/src/storage/implementation/MongoSyncRulesLock.ts +9 -3
  81. package/src/storage/implementation/SyncRuleStateUpdate.ts +38 -0
  82. package/src/storage/implementation/common/BucketDataDoc.ts +1 -1
  83. package/src/storage/implementation/common/PersistedBatch.ts +2 -2
  84. package/src/storage/implementation/common/SourceRecordStore.ts +1 -2
  85. package/src/storage/implementation/createMongoSyncBucketStorage.ts +2 -2
  86. package/src/storage/implementation/db.ts +5 -2
  87. package/src/storage/implementation/models.ts +35 -58
  88. package/src/storage/implementation/v1/MongoBucketBatchV1.ts +478 -1
  89. package/src/storage/implementation/v1/MongoCompactorV1.ts +1 -1
  90. package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +111 -16
  91. package/src/storage/implementation/v1/PersistedBatchV1.ts +1 -2
  92. package/src/storage/implementation/v1/models.ts +15 -0
  93. package/src/storage/implementation/v3/MongoBucketBatchV3.ts +564 -1
  94. package/src/storage/implementation/v3/MongoCompactorV3.ts +1 -1
  95. package/src/storage/implementation/v3/MongoParameterLookupV3.ts +1 -2
  96. package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +150 -22
  97. package/src/storage/implementation/v3/PersistedBatchV3.ts +1 -2
  98. package/src/storage/implementation/v3/VersionedPowerSyncMongoV3.ts +7 -2
  99. package/src/storage/implementation/v3/models.ts +70 -2
  100. package/test/src/storage_sync.test.ts +422 -6
  101. package/test/src/storeCurrentData.test.ts +211 -0
  102. package/tsconfig.tsbuildinfo +1 -1
@@ -1,10 +1,12 @@
1
1
  import * as lib_mongo from '@powersync/lib-service-mongodb';
2
2
  import { mongo } from '@powersync/lib-service-mongodb';
3
+ import { ServiceAssertionError } from '@powersync/lib-services-framework';
3
4
  import {
4
5
  CheckpointChanges,
5
6
  GetCheckpointChangesOptions,
6
7
  InternalOpId,
7
8
  internalToExternalOpId,
9
+ maxLsn,
8
10
  ParameterSetLimitExceededError,
9
11
  ProtocolOpId,
10
12
  storage,
@@ -19,14 +21,22 @@ import {
19
21
  MongoSyncBucketStorageCheckpoint,
20
22
  MongoSyncBucketStorageContext
21
23
  } from '../common/MongoSyncBucketStorageContext.js';
22
- import { CommonSourceTableDocument } from '../models.js';
23
24
  import { MongoBucketBatchOptions } from '../MongoBucketBatch.js';
24
25
  import { MongoChecksums } from '../MongoChecksums.js';
25
26
  import { MongoCompactOptions, MongoCompactor } from '../MongoCompactor.js';
26
27
  import { MongoParameterCompactor } from '../MongoParameterCompactor.js';
27
- import { MongoPersistedSyncRulesContent } from '../MongoPersistedSyncRulesContent.js';
28
+ import {
29
+ MongoPersistedSyncRulesContentV1,
30
+ MongoPersistedSyncRulesContentV3
31
+ } from '../MongoPersistedSyncRulesContent.js';
28
32
  import { MongoSyncBucketStorage, MongoSyncBucketStorageOptions } from '../MongoSyncBucketStorage.js';
29
- import { BucketDataDocumentV3, BucketParameterDocumentV3, loadBucketDataDocumentV3 } from './models.js';
33
+ import {
34
+ BucketDataDocumentV3,
35
+ BucketParameterDocumentV3,
36
+ loadBucketDataDocumentV3,
37
+ ReplicationStreamDocumentV3,
38
+ SyncRuleConfigStateV3
39
+ } from './models.js';
30
40
  import { MongoBucketBatchV3 } from './MongoBucketBatchV3.js';
31
41
  import { MongoChecksumsV3 } from './MongoChecksumsV3.js';
32
42
  import { MongoCompactorV3 } from './MongoCompactorV3.js';
@@ -39,15 +49,67 @@ export class MongoSyncBucketStorageV3 extends MongoSyncBucketStorage {
39
49
  declare readonly db: VersionedPowerSyncMongoV3;
40
50
  declare readonly checksums: MongoChecksumsV3;
41
51
 
52
+ private readonly syncRulesV3: MongoPersistedSyncRulesContentV3;
53
+
42
54
  constructor(
43
55
  factory: MongoBucketStorage,
44
56
  group_id: number,
45
- sync_rules: MongoPersistedSyncRulesContent,
57
+ sync_rules: MongoPersistedSyncRulesContentV1,
46
58
  slot_name: string,
47
59
  writeCheckpointMode: storage.WriteCheckpointMode | undefined,
48
60
  options: MongoSyncBucketStorageOptions
49
61
  ) {
50
62
  super(factory, group_id, sync_rules, slot_name, writeCheckpointMode, options);
63
+ if (!(sync_rules instanceof MongoPersistedSyncRulesContentV3)) {
64
+ throw new ServiceAssertionError('Missing sync config id for storage v3');
65
+ }
66
+ this.syncRulesV3 = sync_rules;
67
+ }
68
+
69
+ private get syncConfigId(): bson.ObjectId {
70
+ return this.syncRulesV3.syncConfigId;
71
+ }
72
+
73
+ private get syncRulesCollection(): mongo.Collection<ReplicationStreamDocumentV3> {
74
+ return this.db.sync_rules as unknown as mongo.Collection<ReplicationStreamDocumentV3>;
75
+ }
76
+
77
+ private syncConfigMatch(extra: mongo.Document = {}): mongo.Filter<ReplicationStreamDocumentV3> {
78
+ return {
79
+ _id: this.group_id,
80
+ sync_configs: {
81
+ $elemMatch: {
82
+ _id: this.syncConfigId,
83
+ ...extra
84
+ }
85
+ }
86
+ };
87
+ }
88
+
89
+ private syncConfigProjection(extra: mongo.Document = {}): mongo.Document {
90
+ return {
91
+ ...extra,
92
+ sync_configs: {
93
+ $elemMatch: {
94
+ _id: this.syncConfigId
95
+ }
96
+ }
97
+ };
98
+ }
99
+
100
+ private syncConfigArrayFilters(): mongo.UpdateOptions['arrayFilters'] {
101
+ return [{ 'config._id': this.syncConfigId }];
102
+ }
103
+
104
+ /**
105
+ * For now, we only support a single sync config per replication stream.
106
+ *
107
+ * In the future we'll add support for multiple.
108
+ */
109
+ private selectedSyncConfig(
110
+ doc: Pick<ReplicationStreamDocumentV3, 'sync_configs'> | null
111
+ ): SyncRuleConfigStateV3 | null {
112
+ return doc?.sync_configs?.[0] ?? null;
51
113
  }
52
114
 
53
115
  protected async initializeVersionStorage(): Promise<void> {
@@ -100,30 +162,96 @@ export class MongoSyncBucketStorageV3 extends MongoSyncBucketStorage {
100
162
  return new MongoBucketBatchV3(batchOptions);
101
163
  }
102
164
 
103
- protected sourceTableBaseId(): Partial<CommonSourceTableDocument> {
104
- return {};
165
+ protected async fetchCheckpointState(
166
+ session: mongo.ClientSession
167
+ ): Promise<{ checkpoint: bigint; lsn: string | null } | null> {
168
+ const doc = await this.syncRulesCollection.findOne(
169
+ this.syncConfigMatch({
170
+ state: { $in: [storage.SyncRuleState.ACTIVE, storage.SyncRuleState.ERRORED] }
171
+ }),
172
+ {
173
+ session,
174
+ projection: this.syncConfigProjection()
175
+ }
176
+ );
177
+ const syncConfig = this.selectedSyncConfig(doc);
178
+ if (!syncConfig?.snapshot_done) {
179
+ return null;
180
+ }
181
+ return {
182
+ checkpoint: syncConfig.last_checkpoint ?? 0n,
183
+ lsn: syncConfig.last_checkpoint_lsn ?? null
184
+ };
185
+ }
186
+
187
+ protected async getWriterSyncState() {
188
+ const doc = await this.syncRulesCollection.findOne(this.syncConfigMatch(), {
189
+ projection: this.syncConfigProjection({ snapshot_lsn: 1 })
190
+ });
191
+ const syncConfig = this.selectedSyncConfig(doc);
192
+ const checkpointLsn = syncConfig?.last_checkpoint_lsn ?? null;
193
+ return {
194
+ lastCheckpointLsn: checkpointLsn,
195
+ resumeFromLsn: maxLsn(checkpointLsn, doc?.snapshot_lsn),
196
+ keepaliveOp: syncConfig?.keepalive_op ?? null,
197
+ syncConfigId: this.syncConfigId
198
+ };
105
199
  }
106
200
 
107
- protected augmentCreatedSourceTableDocument(
108
- createDoc: CommonSourceTableDocument,
109
- options: storage.ResolveTableOptions,
110
- candidateSourceTable: storage.SourceTable
111
- ): void {
112
- const bucketDataSourceIds = options.sync_rules.definition.bucketDataSources
113
- .filter((source) => source.tableSyncsData(candidateSourceTable))
114
- .map((source) => this.mapping.bucketSourceId(source));
115
- const parameterLookupSourceIds = options.sync_rules.definition.bucketParameterLookupSources
116
- .filter((source) => source.tableSyncsParameters(candidateSourceTable))
117
- .map((source) => this.mapping.parameterLookupId(source));
201
+ protected async terminateSyncRuleState(): Promise<void> {
202
+ await this.db.sync_rules.updateOne(
203
+ {
204
+ _id: this.group_id
205
+ },
206
+ {
207
+ $set: {
208
+ state: storage.SyncRuleState.TERMINATED,
209
+ persisted_lsn: null,
210
+ sync_configs: []
211
+ }
212
+ }
213
+ );
214
+ }
118
215
 
119
- Object.assign(createDoc, {
120
- bucket_data_source_ids: bucketDataSourceIds,
121
- parameter_lookup_source_ids: parameterLookupSourceIds
216
+ protected async getStatusImpl(): Promise<storage.SyncRuleStatus> {
217
+ const doc = await this.syncRulesCollection.findOne(this.syncConfigMatch(), {
218
+ projection: this.syncConfigProjection({ state: 1, snapshot_lsn: 1, keepalive_op: 1 })
122
219
  });
220
+ const syncConfig = this.selectedSyncConfig(doc);
221
+ if (doc == null || syncConfig == null) {
222
+ throw new ServiceAssertionError('Cannot find replication stream status');
223
+ }
224
+
225
+ return {
226
+ snapshot_done: syncConfig.snapshot_done ?? false,
227
+ snapshot_lsn: doc.snapshot_lsn ?? null,
228
+ active: doc.state == storage.SyncRuleState.ACTIVE && syncConfig.state == storage.SyncRuleState.ACTIVE,
229
+ checkpoint_lsn: syncConfig.last_checkpoint_lsn ?? null,
230
+ keepalive_op: syncConfig.keepalive_op ?? null
231
+ };
123
232
  }
124
233
 
125
- protected async initializeResolvedSourceRecords(sourceTableId: bson.ObjectId): Promise<void> {
126
- await this.db.initializeSourceRecordsCollection(this.group_id, sourceTableId);
234
+ protected async clearSyncRuleState(): Promise<void> {
235
+ await this.syncRulesCollection.updateOne(
236
+ this.syncConfigMatch(),
237
+ {
238
+ $set: {
239
+ persisted_lsn: null,
240
+ 'sync_configs.$[config].snapshot_done': false,
241
+ 'sync_configs.$[config].last_checkpoint_lsn': null,
242
+ 'sync_configs.$[config].last_checkpoint': null,
243
+ 'sync_configs.$[config].no_checkpoint_before': null,
244
+ 'sync_configs.$[config].keepalive_op': null
245
+ },
246
+ $unset: {
247
+ snapshot_lsn: 1
248
+ }
249
+ },
250
+ {
251
+ maxTimeMS: lib_mongo.db.MONGO_CLEAR_OPERATION_TIMEOUT_MS,
252
+ arrayFilters: this.syncConfigArrayFilters()
253
+ }
254
+ );
127
255
  }
128
256
 
129
257
  protected override get versionContext(): MongoSyncBucketStorageContext<VersionedPowerSyncMongoV3> {
@@ -1,10 +1,9 @@
1
1
  import { mongo } from '@powersync/lib-service-mongodb';
2
2
  import { ReplicationAssertionError } from '@powersync/lib-services-framework';
3
3
  import { InternalOpId, storage } from '@powersync/service-core';
4
- import { BucketDataSource } from '@powersync/service-sync-rules';
4
+ import { BucketDataSource, BucketDefinitionId } from '@powersync/service-sync-rules';
5
5
  import * as bson from 'bson';
6
6
  import { mongoTableId } from '../../../utils/util.js';
7
- import { BucketDefinitionId } from '../BucketDefinitionMapping.js';
8
7
  import {
9
8
  BucketStateUpdate,
10
9
  PersistedBatch,
@@ -1,5 +1,5 @@
1
1
  import { mongo } from '@powersync/lib-service-mongodb';
2
- import { BucketDefinitionId, ParameterIndexId } from '../BucketDefinitionMapping.js';
2
+ import { BucketDefinitionId, ParameterIndexId } from '@powersync/service-sync-rules';
3
3
  import { BaseVersionedPowerSyncMongo } from '../common/VersionedPowerSyncMongoBase.js';
4
4
  import { CommonSourceTableDocument } from '../models.js';
5
5
  import {
@@ -7,10 +7,15 @@ import {
7
7
  BucketParameterDocumentV3,
8
8
  BucketStateDocumentV3,
9
9
  CurrentDataDocumentV3,
10
- SourceTableDocumentV3
10
+ SourceTableDocumentV3,
11
+ SyncConfigDefinition
11
12
  } from './models.js';
12
13
 
13
14
  export class VersionedPowerSyncMongoV3 extends BaseVersionedPowerSyncMongo {
15
+ get syncConfigDefinitions() {
16
+ return this.db.collection<SyncConfigDefinition>('sync_config');
17
+ }
18
+
14
19
  sourceRecordsV3(replicationStreamId: number, sourceTableId: mongo.ObjectId): mongo.Collection<CurrentDataDocumentV3> {
15
20
  const collectionName = this.sourceRecordsCollectionName(replicationStreamId, sourceTableId);
16
21
  return this.db.collection<CurrentDataDocumentV3>(collectionName);
@@ -1,6 +1,6 @@
1
- import { InternalOpId } from '@powersync/service-core';
1
+ import { InternalOpId, SerializedSyncPlan, SyncRuleState } from '@powersync/service-core';
2
+ import { BucketDefinitionId, ParameterIndexId } from '@powersync/service-sync-rules';
2
3
  import * as bson from 'bson';
3
- import { BucketDefinitionId, ParameterIndexId } from '../BucketDefinitionMapping.js';
4
4
  import { BucketDataDoc, BucketKey } from '../common/BucketDataDoc.js';
5
5
  import {
6
6
  BucketDataDocumentBase,
@@ -11,9 +11,77 @@ import {
11
11
  ReplicaId,
12
12
  SourceTableDocument,
13
13
  SourceTableKey,
14
+ SyncRuleCheckpointFields,
15
+ SyncRuleDocumentBase,
14
16
  TaggedBucketParameterDocument
15
17
  } from '../models.js';
16
18
 
19
+ /**
20
+ * Embedded in sync_rules.sync_configs.
21
+ */
22
+ export interface SyncRuleConfigStateV3 extends SyncRuleCheckpointFields<bigint | null> {
23
+ _id: bson.ObjectId;
24
+
25
+ /**
26
+ * If false, we cannot create any checkpoints.
27
+ */
28
+ snapshot_done: boolean;
29
+
30
+ state: SyncRuleState;
31
+ }
32
+
33
+ /**
34
+ * Represents the state of a replication stream, in the sync_rules collection.
35
+ *
36
+ * Differences from V1:
37
+ * 1. The static config is moved into a separate sync_configs collection.
38
+ * 2. The same replication stream may be shared by multiple sync config instances.
39
+ */
40
+ export interface ReplicationStreamDocumentV3 extends SyncRuleDocumentBase {
41
+ storage_version: number;
42
+
43
+ /**
44
+ * These contain the checkpoint/state per sync config.
45
+ *
46
+ * In common cases we'd have one active config or one active + one processing config,
47
+ * but the model allows multiple configs in any state.
48
+ */
49
+ sync_configs: SyncRuleConfigStateV3[];
50
+ }
51
+
52
+ /**
53
+ * Static sync config definition.
54
+ *
55
+ * This should be treated as immutable - we don't update this after initial creation.
56
+ */
57
+ export interface SyncConfigDefinition {
58
+ _id: bson.ObjectId;
59
+ created_at: Date;
60
+ storage_version: number;
61
+ /**
62
+ * The related SyncRuleDocumentV3.
63
+ *
64
+ * Note that a specific sync config definition never moves between replication streams. Instead, we can create a new copy for the new replication stream.
65
+ *
66
+ * When terminating a specific sync config definition, we remove the reference from replication stream -> sync config, but this reference here remains as a historical record.
67
+ */
68
+ replication_stream_id: number;
69
+
70
+ content: string;
71
+ serialized_plan?: SerializedSyncPlan | null;
72
+
73
+ rule_mapping: {
74
+ /**
75
+ * Map of uniqueName -> id, unique per replication stream.
76
+ */
77
+ definitions: Record<string, string>;
78
+ /**
79
+ * Map of (lookupName, queryId) -> id, unique per replication stream.
80
+ */
81
+ parameter_indexes: Record<string, string>;
82
+ };
83
+ }
84
+
17
85
  export interface CurrentBucketV3 extends CurrentBucket {
18
86
  def: BucketDefinitionId;
19
87
  }