@powersync/service-module-mongodb-storage 0.15.4 → 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 (202) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js +1 -1
  3. package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js.map +1 -1
  4. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +2 -2
  5. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
  6. package/dist/storage/MongoBucketStorage.d.ts +8 -6
  7. package/dist/storage/MongoBucketStorage.js +153 -66
  8. package/dist/storage/MongoBucketStorage.js.map +1 -1
  9. package/dist/storage/implementation/BucketDefinitionMapping.d.ts +15 -0
  10. package/dist/storage/implementation/BucketDefinitionMapping.js +58 -0
  11. package/dist/storage/implementation/BucketDefinitionMapping.js.map +1 -0
  12. package/dist/storage/implementation/CheckpointState.d.ts +20 -0
  13. package/dist/storage/implementation/CheckpointState.js +31 -0
  14. package/dist/storage/implementation/CheckpointState.js.map +1 -0
  15. package/dist/storage/implementation/MongoBucketBatch.d.ts +48 -35
  16. package/dist/storage/implementation/MongoBucketBatch.js +118 -379
  17. package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
  18. package/dist/storage/implementation/MongoBucketBatchShared.d.ts +5 -0
  19. package/dist/storage/implementation/MongoBucketBatchShared.js +8 -0
  20. package/dist/storage/implementation/MongoBucketBatchShared.js.map +1 -0
  21. package/dist/storage/implementation/MongoChecksums.d.ts +29 -17
  22. package/dist/storage/implementation/MongoChecksums.js +13 -72
  23. package/dist/storage/implementation/MongoChecksums.js.map +1 -1
  24. package/dist/storage/implementation/MongoCompactor.d.ts +98 -58
  25. package/dist/storage/implementation/MongoCompactor.js +229 -296
  26. package/dist/storage/implementation/MongoCompactor.js.map +1 -1
  27. package/dist/storage/implementation/MongoParameterCompactor.d.ts +11 -6
  28. package/dist/storage/implementation/MongoParameterCompactor.js +11 -8
  29. package/dist/storage/implementation/MongoParameterCompactor.js.map +1 -1
  30. package/dist/storage/implementation/MongoPersistedSyncRules.d.ts +14 -0
  31. package/dist/storage/implementation/MongoPersistedSyncRules.js +67 -0
  32. package/dist/storage/implementation/MongoPersistedSyncRules.js.map +1 -0
  33. package/dist/storage/implementation/MongoPersistedSyncRulesContent.d.ts +22 -5
  34. package/dist/storage/implementation/MongoPersistedSyncRulesContent.js +56 -13
  35. package/dist/storage/implementation/MongoPersistedSyncRulesContent.js.map +1 -1
  36. package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +61 -32
  37. package/dist/storage/implementation/MongoSyncBucketStorage.js +85 -523
  38. package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
  39. package/dist/storage/implementation/MongoSyncRulesLock.d.ts +10 -4
  40. package/dist/storage/implementation/MongoSyncRulesLock.js +19 -13
  41. package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
  42. package/dist/storage/implementation/MongoWriteCheckpointAPI.js +1 -1
  43. package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
  44. package/dist/storage/implementation/OperationBatch.js +1 -1
  45. package/dist/storage/implementation/SyncRuleStateUpdate.d.ts +14 -0
  46. package/dist/storage/implementation/SyncRuleStateUpdate.js +36 -0
  47. package/dist/storage/implementation/SyncRuleStateUpdate.js.map +1 -0
  48. package/dist/storage/implementation/common/BucketDataDoc.d.ts +35 -0
  49. package/dist/storage/implementation/common/BucketDataDoc.js +2 -0
  50. package/dist/storage/implementation/common/BucketDataDoc.js.map +1 -0
  51. package/dist/storage/implementation/common/MongoSyncBucketStorageContext.d.ts +13 -0
  52. package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js +2 -0
  53. package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js.map +1 -0
  54. package/dist/storage/implementation/common/PersistedBatch.d.ts +108 -0
  55. package/dist/storage/implementation/common/PersistedBatch.js +237 -0
  56. package/dist/storage/implementation/common/PersistedBatch.js.map +1 -0
  57. package/dist/storage/implementation/common/SingleBucketStore.d.ts +54 -0
  58. package/dist/storage/implementation/common/SingleBucketStore.js +3 -0
  59. package/dist/storage/implementation/common/SingleBucketStore.js.map +1 -0
  60. package/dist/storage/implementation/common/SourceRecordStore.d.ts +35 -0
  61. package/dist/storage/implementation/common/SourceRecordStore.js +2 -0
  62. package/dist/storage/implementation/common/SourceRecordStore.js.map +1 -0
  63. package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.d.ts +27 -0
  64. package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js +57 -0
  65. package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js.map +1 -0
  66. package/dist/storage/implementation/createMongoSyncBucketStorage.d.ts +7 -0
  67. package/dist/storage/implementation/createMongoSyncBucketStorage.js +9 -0
  68. package/dist/storage/implementation/createMongoSyncBucketStorage.js.map +1 -0
  69. package/dist/storage/implementation/db.d.ts +41 -36
  70. package/dist/storage/implementation/db.js +77 -99
  71. package/dist/storage/implementation/db.js.map +1 -1
  72. package/dist/storage/implementation/models.d.ts +79 -66
  73. package/dist/storage/implementation/models.js +20 -1
  74. package/dist/storage/implementation/models.js.map +1 -1
  75. package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +27 -0
  76. package/dist/storage/implementation/v1/MongoBucketBatchV1.js +407 -0
  77. package/dist/storage/implementation/v1/MongoBucketBatchV1.js.map +1 -0
  78. package/dist/storage/implementation/v1/MongoChecksumsV1.d.ts +12 -0
  79. package/dist/storage/implementation/v1/MongoChecksumsV1.js +56 -0
  80. package/dist/storage/implementation/v1/MongoChecksumsV1.js.map +1 -0
  81. package/dist/storage/implementation/v1/MongoCompactorV1.d.ts +23 -0
  82. package/dist/storage/implementation/v1/MongoCompactorV1.js +52 -0
  83. package/dist/storage/implementation/v1/MongoCompactorV1.js.map +1 -0
  84. package/dist/storage/implementation/v1/MongoParameterCompactorV1.d.ts +9 -0
  85. package/dist/storage/implementation/v1/MongoParameterCompactorV1.js +20 -0
  86. package/dist/storage/implementation/v1/MongoParameterCompactorV1.js.map +1 -0
  87. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.d.ts +50 -0
  88. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +354 -0
  89. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js.map +1 -0
  90. package/dist/storage/implementation/v1/PersistedBatchV1.d.ts +25 -0
  91. package/dist/storage/implementation/v1/PersistedBatchV1.js +183 -0
  92. package/dist/storage/implementation/v1/PersistedBatchV1.js.map +1 -0
  93. package/dist/storage/implementation/v1/SingleBucketStoreV1.d.ts +18 -0
  94. package/dist/storage/implementation/v1/SingleBucketStoreV1.js +57 -0
  95. package/dist/storage/implementation/v1/SingleBucketStoreV1.js.map +1 -0
  96. package/dist/storage/implementation/v1/SourceRecordStoreV1.d.ts +19 -0
  97. package/dist/storage/implementation/v1/SourceRecordStoreV1.js +105 -0
  98. package/dist/storage/implementation/v1/SourceRecordStoreV1.js.map +1 -0
  99. package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.d.ts +12 -0
  100. package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js +20 -0
  101. package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js.map +1 -0
  102. package/dist/storage/implementation/v1/models.d.ts +45 -0
  103. package/dist/storage/implementation/v1/models.js +37 -0
  104. package/dist/storage/implementation/v1/models.js.map +1 -0
  105. package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +30 -0
  106. package/dist/storage/implementation/v3/MongoBucketBatchV3.js +463 -0
  107. package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -0
  108. package/dist/storage/implementation/v3/MongoChecksumsV3.d.ts +15 -0
  109. package/dist/storage/implementation/v3/MongoChecksumsV3.js +84 -0
  110. package/dist/storage/implementation/v3/MongoChecksumsV3.js.map +1 -0
  111. package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +23 -0
  112. package/dist/storage/implementation/v3/MongoCompactorV3.js +68 -0
  113. package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -0
  114. package/dist/storage/implementation/v3/MongoParameterCompactorV3.d.ts +9 -0
  115. package/dist/storage/implementation/v3/MongoParameterCompactorV3.js +18 -0
  116. package/dist/storage/implementation/v3/MongoParameterCompactorV3.js.map +1 -0
  117. package/dist/storage/implementation/v3/MongoParameterLookupV3.d.ts +4 -0
  118. package/dist/storage/implementation/v3/MongoParameterLookupV3.js +9 -0
  119. package/dist/storage/implementation/v3/MongoParameterLookupV3.js.map +1 -0
  120. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.d.ts +63 -0
  121. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +508 -0
  122. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -0
  123. package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +28 -0
  124. package/dist/storage/implementation/v3/PersistedBatchV3.js +259 -0
  125. package/dist/storage/implementation/v3/PersistedBatchV3.js.map +1 -0
  126. package/dist/storage/implementation/v3/SingleBucketStoreV3.d.ts +18 -0
  127. package/dist/storage/implementation/v3/SingleBucketStoreV3.js +48 -0
  128. package/dist/storage/implementation/v3/SingleBucketStoreV3.js.map +1 -0
  129. package/dist/storage/implementation/v3/SourceRecordStoreV3.d.ts +22 -0
  130. package/dist/storage/implementation/v3/SourceRecordStoreV3.js +164 -0
  131. package/dist/storage/implementation/v3/SourceRecordStoreV3.js.map +1 -0
  132. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.d.ts +22 -0
  133. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +74 -0
  134. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js.map +1 -0
  135. package/dist/storage/implementation/v3/models.d.ts +101 -0
  136. package/dist/storage/implementation/v3/models.js +34 -0
  137. package/dist/storage/implementation/v3/models.js.map +1 -0
  138. package/dist/storage/storage-index.d.ts +6 -3
  139. package/dist/storage/storage-index.js +6 -3
  140. package/dist/storage/storage-index.js.map +1 -1
  141. package/dist/utils/util.d.ts +10 -3
  142. package/dist/utils/util.js +24 -3
  143. package/dist/utils/util.js.map +1 -1
  144. package/package.json +9 -9
  145. package/src/migrations/db/migrations/1688556755264-initial-sync-rules.ts +1 -1
  146. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -7
  147. package/src/storage/MongoBucketStorage.ts +254 -99
  148. package/src/storage/implementation/BucketDefinitionMapping.ts +75 -0
  149. package/src/storage/implementation/CheckpointState.ts +59 -0
  150. package/src/storage/implementation/MongoBucketBatch.ts +182 -490
  151. package/src/storage/implementation/MongoBucketBatchShared.ts +11 -0
  152. package/src/storage/implementation/MongoChecksums.ts +53 -75
  153. package/src/storage/implementation/MongoCompactor.ts +374 -404
  154. package/src/storage/implementation/MongoParameterCompactor.ts +37 -24
  155. package/src/storage/implementation/MongoPersistedSyncRules.ts +82 -0
  156. package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +78 -16
  157. package/src/storage/implementation/MongoSyncBucketStorage.ts +179 -628
  158. package/src/storage/implementation/MongoSyncRulesLock.ts +20 -16
  159. package/src/storage/implementation/MongoWriteCheckpointAPI.ts +3 -1
  160. package/src/storage/implementation/OperationBatch.ts +1 -1
  161. package/src/storage/implementation/SyncRuleStateUpdate.ts +38 -0
  162. package/src/storage/implementation/common/BucketDataDoc.ts +37 -0
  163. package/src/storage/implementation/common/MongoSyncBucketStorageContext.ts +15 -0
  164. package/src/storage/implementation/common/PersistedBatch.ts +364 -0
  165. package/src/storage/implementation/common/SingleBucketStore.ts +63 -0
  166. package/src/storage/implementation/common/SourceRecordStore.ts +48 -0
  167. package/src/storage/implementation/common/VersionedPowerSyncMongoBase.ts +80 -0
  168. package/src/storage/implementation/createMongoSyncBucketStorage.ts +25 -0
  169. package/src/storage/implementation/db.ts +110 -131
  170. package/src/storage/implementation/models.ts +102 -79
  171. package/src/storage/implementation/v1/MongoBucketBatchV1.ts +509 -0
  172. package/src/storage/implementation/v1/MongoChecksumsV1.ts +75 -0
  173. package/src/storage/implementation/v1/MongoCompactorV1.ts +93 -0
  174. package/src/storage/implementation/v1/MongoParameterCompactorV1.ts +26 -0
  175. package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +543 -0
  176. package/src/storage/implementation/v1/PersistedBatchV1.ts +229 -0
  177. package/src/storage/implementation/v1/SingleBucketStoreV1.ts +74 -0
  178. package/src/storage/implementation/v1/SourceRecordStoreV1.ts +156 -0
  179. package/src/storage/implementation/v1/VersionedPowerSyncMongoV1.ts +28 -0
  180. package/src/storage/implementation/v1/models.ts +99 -0
  181. package/src/storage/implementation/v3/MongoBucketBatchV3.ts +607 -0
  182. package/src/storage/implementation/v3/MongoChecksumsV3.ts +120 -0
  183. package/src/storage/implementation/v3/MongoCompactorV3.ts +107 -0
  184. package/src/storage/implementation/v3/MongoParameterCompactorV3.ts +24 -0
  185. package/src/storage/implementation/v3/MongoParameterLookupV3.ts +11 -0
  186. package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +678 -0
  187. package/src/storage/implementation/v3/PersistedBatchV3.ts +317 -0
  188. package/src/storage/implementation/v3/SingleBucketStoreV3.ts +68 -0
  189. package/src/storage/implementation/v3/SourceRecordStoreV3.ts +226 -0
  190. package/src/storage/implementation/v3/VersionedPowerSyncMongoV3.ts +117 -0
  191. package/src/storage/implementation/v3/models.ts +164 -0
  192. package/src/storage/storage-index.ts +6 -3
  193. package/src/utils/util.ts +34 -5
  194. package/test/src/storage_compacting.test.ts +57 -29
  195. package/test/src/storage_sync.test.ts +767 -5
  196. package/test/src/storeCurrentData.test.ts +211 -0
  197. package/test/tsconfig.json +0 -1
  198. package/tsconfig.tsbuildinfo +1 -1
  199. package/dist/storage/implementation/PersistedBatch.d.ts +0 -71
  200. package/dist/storage/implementation/PersistedBatch.js +0 -354
  201. package/dist/storage/implementation/PersistedBatch.js.map +0 -1
  202. package/src/storage/implementation/PersistedBatch.ts +0 -432
@@ -2,8 +2,14 @@ import { mongo } from '@powersync/lib-service-mongodb';
2
2
  import { logger } from '@powersync/lib-services-framework';
3
3
  import { bson, CompactOptions, InternalOpId } from '@powersync/service-core';
4
4
  import { LRUCache } from 'lru-cache';
5
- import { VersionedPowerSyncMongo } from './db.js';
6
- import { BucketParameterDocument } from './models.js';
5
+ import type { VersionedPowerSyncMongo } from './db.js';
6
+
7
+ type ParameterCompactionReadDocument = {
8
+ _id: InternalOpId;
9
+ key: mongo.Document;
10
+ lookup: unknown;
11
+ bucket_parameters?: unknown[] | null;
12
+ };
7
13
 
8
14
  /**
9
15
  * Compacts parameter lookup data (the bucket_parameters collection).
@@ -12,16 +18,28 @@ import { BucketParameterDocument } from './models.js';
12
18
  *
13
19
  * For background, see the `/docs/parameters-lookups.md` file.
14
20
  */
15
- export class MongoParameterCompactor {
21
+ export abstract class MongoParameterCompactor {
16
22
  constructor(
17
- private db: VersionedPowerSyncMongo,
18
- private group_id: number,
19
- private checkpoint: InternalOpId,
20
- private options: CompactOptions
23
+ protected readonly db: VersionedPowerSyncMongo,
24
+ protected readonly group_id: number,
25
+ protected readonly checkpoint: InternalOpId,
26
+ protected readonly options: CompactOptions
21
27
  ) {}
22
28
 
23
29
  async compact() {
24
30
  logger.info(`Compacting parameters for sync config ${this.group_id} up to checkpoint ${this.checkpoint}`);
31
+ for (const collection of await this.getCollections()) {
32
+ await this.compactCollection(collection);
33
+ }
34
+ }
35
+
36
+ protected abstract getCollections(): Promise<mongo.Collection<mongo.Document>[]>;
37
+
38
+ protected abstract collectionFilter(): mongo.Document;
39
+
40
+ protected abstract deleteFilter(doc: mongo.Document): mongo.Document;
41
+
42
+ protected async compactCollection(collection: mongo.Collection<mongo.Document>) {
25
43
  // This is the currently-active checkpoint.
26
44
  // We do not remove any data that may be used by this checkpoint.
27
45
  // snapshot queries ensure that if any clients are still using older checkpoints, they would
@@ -32,43 +50,38 @@ export class MongoParameterCompactor {
32
50
  // In theory, we could let MongoDB do more of the work here, by grouping by (key, lookup)
33
51
  // in MongoDB already. However, that risks running into cases where MongoDB needs to process
34
52
  // very large amounts of data before returning results, which could lead to timeouts.
35
- const cursor = this.db.bucket_parameters.find(
36
- {
37
- 'key.g': this.group_id
38
- },
39
- {
40
- sort: { lookup: 1, _id: 1 },
41
- batchSize: 10_000,
42
- projection: { _id: 1, key: 1, lookup: 1, bucket_parameters: 1 }
43
- }
44
- );
53
+ const cursor = collection.find(this.collectionFilter(), {
54
+ sort: { lookup: 1, _id: 1 },
55
+ batchSize: 10_000,
56
+ projection: { _id: 1, key: 1, lookup: 1, bucket_parameters: 1 }
57
+ });
45
58
 
46
59
  // The index doesn't cover sorting by key, so we keep our own cache of the last seen key.
47
60
  let lastByKey = new LRUCache<string, InternalOpId>({
48
61
  max: this.options.compactParameterCacheLimit ?? 10_000
49
62
  });
50
63
  let removeIds: InternalOpId[] = [];
51
- let removeDeleted: mongo.AnyBulkWriteOperation<BucketParameterDocument>[] = [];
64
+ let removeDeleted: mongo.AnyBulkWriteOperation<mongo.Document>[] = [];
52
65
  let checkedEntries = 0;
53
66
  let checkedEntriesAtLastLog = 0;
54
67
  let lastProgressLogTime = Date.now();
55
68
 
56
69
  const flush = async (force: boolean) => {
57
70
  if (removeIds.length >= 1000 || (force && removeIds.length > 0)) {
58
- const results = await this.db.bucket_parameters.deleteMany({ _id: { $in: removeIds } });
71
+ const results = await collection.deleteMany({ _id: { $in: removeIds } } as any);
59
72
  logger.info(`Removed ${results.deletedCount} (${removeIds.length}) superseded parameter entries`);
60
73
  removeIds = [];
61
74
  }
62
75
 
63
76
  if (removeDeleted.length > 10 || (force && removeDeleted.length > 0)) {
64
- const results = await this.db.bucket_parameters.bulkWrite(removeDeleted);
77
+ const results = await collection.bulkWrite(removeDeleted);
65
78
  logger.info(`Removed ${results.deletedCount} (${removeDeleted.length}) deleted parameter entries`);
66
79
  removeDeleted = [];
67
80
  }
68
81
  };
69
82
 
70
83
  while (await cursor.hasNext()) {
71
- const batch = cursor.readBufferedDocuments();
84
+ const batch = cursor.readBufferedDocuments() as unknown as ParameterCompactionReadDocument[];
72
85
  checkedEntries += batch.length;
73
86
  const now = Date.now();
74
87
  if (now - lastProgressLogTime >= 60_000) {
@@ -79,7 +92,7 @@ export class MongoParameterCompactor {
79
92
  checkedEntriesAtLastLog = checkedEntries;
80
93
  }
81
94
 
82
- for (let doc of batch) {
95
+ for (const doc of batch) {
83
96
  if (doc._id >= checkpoint) {
84
97
  continue;
85
98
  }
@@ -103,7 +116,7 @@ export class MongoParameterCompactor {
103
116
  // in the cache due to cache size limits. So we need to explicitly remove all earlier operations.
104
117
  removeDeleted.push({
105
118
  deleteMany: {
106
- filter: { 'key.g': doc.key.g, lookup: doc.lookup, _id: { $lte: doc._id }, key: doc.key }
119
+ filter: this.deleteFilter(doc)
107
120
  }
108
121
  });
109
122
  }
@@ -113,6 +126,6 @@ export class MongoParameterCompactor {
113
126
  }
114
127
 
115
128
  await flush(true);
116
- logger.info('Parameter compaction completed');
129
+ logger.info(`Parameter compaction completed for ${collection.collectionName}`);
117
130
  }
118
131
  }
@@ -0,0 +1,82 @@
1
+ import * as sqlite from 'node:sqlite';
2
+
3
+ import { ServiceAssertionError } from '@powersync/lib-services-framework';
4
+ import { storage } from '@powersync/service-core';
5
+ import {
6
+ BucketDataScope,
7
+ BucketDataSource,
8
+ CompatibilityOption,
9
+ DEFAULT_HYDRATION_STATE,
10
+ HydratedSyncConfig,
11
+ HydrationState,
12
+ nodeSqlite,
13
+ ParameterIndexLookupCreator,
14
+ ParameterLookupScope,
15
+ SyncConfigWithErrors,
16
+ versionedHydrationState
17
+ } from '@powersync/service-sync-rules';
18
+ import { BucketDefinitionMapping } from './BucketDefinitionMapping.js';
19
+ import { StorageConfig } from './models.js';
20
+
21
+ export class MongoPersistedSyncRules implements storage.PersistedSyncRules {
22
+ public readonly hydrationState: HydrationState;
23
+
24
+ constructor(
25
+ public readonly id: number,
26
+ public readonly syncConfigWithErrors: SyncConfigWithErrors,
27
+ public readonly slot_name: string,
28
+ private readonly mapping: BucketDefinitionMapping | null,
29
+ private readonly storageConfig: StorageConfig
30
+ ) {
31
+ if (this.storageConfig.incrementalReprocessing) {
32
+ if (this.mapping == null) {
33
+ throw new ServiceAssertionError(`mapping is required for v3 storage`);
34
+ }
35
+ this.hydrationState = new MongoHydrationState(this.mapping, this.id);
36
+ } else if (
37
+ !this.syncConfigWithErrors.config.compatibility.isEnabled(CompatibilityOption.versionedBucketIds) &&
38
+ !this.storageConfig.versionedBuckets
39
+ ) {
40
+ this.hydrationState = DEFAULT_HYDRATION_STATE;
41
+ } else {
42
+ this.hydrationState = versionedHydrationState(this.id);
43
+ }
44
+ }
45
+
46
+ hydratedSyncConfig(): HydratedSyncConfig {
47
+ return this.syncConfigWithErrors.config.hydrate({
48
+ hydrationState: this.hydrationState,
49
+ sqlite: nodeSqlite(sqlite)
50
+ });
51
+ }
52
+ }
53
+
54
+ class MongoHydrationState implements HydrationState {
55
+ constructor(
56
+ private readonly mapping: BucketDefinitionMapping,
57
+ private readonly version: number
58
+ ) {}
59
+
60
+ getBucketSourceScope(source: BucketDataSource): BucketDataScope {
61
+ // Keep this aligned with versionedHydrationState() for now.
62
+ //
63
+ // Previous Mongo-specific behavior:
64
+ // return {
65
+ // bucketPrefix: defId,
66
+ // source
67
+ // };
68
+ return {
69
+ bucketPrefix: `${this.version}#${source.uniqueName}`,
70
+ source
71
+ };
72
+ }
73
+
74
+ getParameterIndexLookupScope(source: ParameterIndexLookupCreator): ParameterLookupScope {
75
+ const defId = this.mapping.parameterLookupId(source);
76
+ return {
77
+ lookupName: defId,
78
+ queryId: '',
79
+ source
80
+ };
81
+ }
82
+ }
@@ -1,17 +1,60 @@
1
1
  import { mongo } from '@powersync/lib-service-mongodb';
2
- import { storage } from '@powersync/service-core';
2
+ import { ServiceAssertionError } from '@powersync/lib-services-framework';
3
+ import { storage, SyncRuleState } from '@powersync/service-core';
4
+ import * as bson from 'bson';
5
+ import { ReplicationStreamDocumentV3, SyncConfigDefinition } from '../storage-index.js';
6
+ import { BucketDefinitionMapping } from './BucketDefinitionMapping.js';
7
+ import { MongoPersistedSyncRules } from './MongoPersistedSyncRules.js';
3
8
  import { MongoSyncRulesLock } from './MongoSyncRulesLock.js';
4
9
  import { PowerSyncMongo } from './db.js';
5
- import { getMongoStorageConfig, SyncRuleDocument } from './models.js';
10
+ import { getMongoStorageConfig } from './models.js';
11
+ import { SyncRuleDocumentV1 } from './v1/models.js';
6
12
 
7
- export class MongoPersistedSyncRulesContent extends storage.PersistedSyncRulesContent {
13
+ abstract class MongoPersistedSyncRulesContentBase extends storage.PersistedSyncRulesContent {
8
14
  public current_lock: MongoSyncRulesLock | null = null;
15
+ public readonly mapping: BucketDefinitionMapping;
16
+ public readonly syncConfigId: bson.ObjectId | null;
9
17
 
10
- constructor(
11
- private db: PowerSyncMongo,
12
- doc: mongo.WithId<SyncRuleDocument>
18
+ protected constructor(
19
+ protected readonly db: PowerSyncMongo,
20
+ options: ConstructorParameters<typeof storage.PersistedSyncRulesContent>[0] & {
21
+ mapping: BucketDefinitionMapping;
22
+ syncConfigId: bson.ObjectId | null;
23
+ }
13
24
  ) {
14
- super({
25
+ const { mapping, syncConfigId, ...base } = options;
26
+ super(base);
27
+ this.mapping = mapping;
28
+ this.syncConfigId = syncConfigId;
29
+ }
30
+
31
+ getStorageConfig() {
32
+ return getMongoStorageConfig(this.storageVersion);
33
+ }
34
+
35
+ parsed(options: storage.ParseSyncRulesOptions): storage.PersistedSyncRules {
36
+ const parsed = super.parsed(options);
37
+ const storageConfig = this.getStorageConfig();
38
+
39
+ return new MongoPersistedSyncRules(
40
+ parsed.id,
41
+ parsed.syncConfigWithErrors,
42
+ parsed.slot_name,
43
+ storageConfig.incrementalReprocessing ? this.mapping : null,
44
+ storageConfig
45
+ );
46
+ }
47
+
48
+ async lock(session?: mongo.ClientSession) {
49
+ const lock = await MongoSyncRulesLock.createLock(this.db.versioned(this.getStorageConfig()), this, session);
50
+ this.current_lock = lock;
51
+ return lock;
52
+ }
53
+ }
54
+
55
+ export class MongoPersistedSyncRulesContentV1 extends MongoPersistedSyncRulesContentBase {
56
+ constructor(db: PowerSyncMongo, doc: SyncRuleDocumentV1) {
57
+ super(db, {
15
58
  id: doc._id,
16
59
  sync_rules_content: doc.content,
17
60
  compiled_plan: doc.serialized_plan ?? null,
@@ -22,18 +65,37 @@ export class MongoPersistedSyncRulesContent extends storage.PersistedSyncRulesCo
22
65
  last_fatal_error_ts: doc.last_fatal_error_ts,
23
66
  last_checkpoint_ts: doc.last_checkpoint_ts,
24
67
  last_keepalive_ts: doc.last_keepalive_ts,
25
- active: doc.state == 'ACTIVE',
26
- storageVersion: doc.storage_version ?? storage.LEGACY_STORAGE_VERSION
68
+ active: doc.state == SyncRuleState.ACTIVE,
69
+ storageVersion: doc.storage_version ?? storage.LEGACY_STORAGE_VERSION,
70
+ mapping: new BucketDefinitionMapping(),
71
+ syncConfigId: null
27
72
  });
28
73
  }
74
+ }
29
75
 
30
- getStorageConfig() {
31
- return getMongoStorageConfig(this.storageVersion);
32
- }
76
+ export class MongoPersistedSyncRulesContentV3 extends MongoPersistedSyncRulesContentBase {
77
+ declare public readonly syncConfigId: bson.ObjectId;
33
78
 
34
- async lock() {
35
- const lock = await MongoSyncRulesLock.createLock(this.db.versioned(this.getStorageConfig()), this);
36
- this.current_lock = lock;
37
- return lock;
79
+ constructor(db: PowerSyncMongo, doc: ReplicationStreamDocumentV3, config: SyncConfigDefinition) {
80
+ const state = doc.sync_configs.find((c) => c._id.equals(config._id));
81
+ if (state == null) {
82
+ throw new ServiceAssertionError(`Cannot find sync config ${config._id} in replication stream ${doc._id}`);
83
+ }
84
+ super(db, {
85
+ id: doc._id,
86
+ sync_rules_content: config.content,
87
+ compiled_plan: config.serialized_plan ?? null,
88
+
89
+ last_checkpoint_lsn: state?.last_checkpoint_lsn ?? null,
90
+ slot_name: doc.slot_name ?? `powersync_${doc._id}`,
91
+ last_fatal_error: doc.last_fatal_error,
92
+ last_fatal_error_ts: doc.last_fatal_error_ts,
93
+ last_checkpoint_ts: doc.last_checkpoint_ts,
94
+ last_keepalive_ts: doc.last_keepalive_ts,
95
+ active: doc.state == SyncRuleState.ACTIVE && state.state == SyncRuleState.ACTIVE,
96
+ storageVersion: doc.storage_version,
97
+ mapping: BucketDefinitionMapping.fromSyncConfig(config),
98
+ syncConfigId: config._id
99
+ });
38
100
  }
39
101
  }