@powersync/service-module-mongodb-storage 0.0.0-dev-20260225160713 → 0.0.0-dev-20260511080634

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 (213) hide show
  1. package/CHANGELOG.md +119 -6
  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 +3 -3
  5. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
  6. package/dist/migrations/db/migrations/1770213298299-storage-version.js.map +1 -1
  7. package/dist/storage/MongoBucketStorage.d.ts +5 -3
  8. package/dist/storage/MongoBucketStorage.js +53 -26
  9. package/dist/storage/MongoBucketStorage.js.map +1 -1
  10. package/dist/storage/MongoReportStorage.js.map +1 -1
  11. package/dist/storage/implementation/BucketDefinitionMapping.d.ts +17 -0
  12. package/dist/storage/implementation/BucketDefinitionMapping.js +58 -0
  13. package/dist/storage/implementation/BucketDefinitionMapping.js.map +1 -0
  14. package/dist/storage/implementation/MongoBucketBatch.d.ts +25 -21
  15. package/dist/storage/implementation/MongoBucketBatch.js +256 -210
  16. package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
  17. package/dist/storage/implementation/MongoBucketBatchShared.d.ts +5 -0
  18. package/dist/storage/implementation/MongoBucketBatchShared.js +8 -0
  19. package/dist/storage/implementation/MongoBucketBatchShared.js.map +1 -0
  20. package/dist/storage/implementation/MongoChecksums.d.ts +30 -19
  21. package/dist/storage/implementation/MongoChecksums.js +13 -71
  22. package/dist/storage/implementation/MongoChecksums.js.map +1 -1
  23. package/dist/storage/implementation/MongoCompactor.d.ts +99 -53
  24. package/dist/storage/implementation/MongoCompactor.js +265 -303
  25. package/dist/storage/implementation/MongoCompactor.js.map +1 -1
  26. package/dist/storage/implementation/MongoParameterCompactor.d.ts +12 -7
  27. package/dist/storage/implementation/MongoParameterCompactor.js +24 -9
  28. package/dist/storage/implementation/MongoParameterCompactor.js.map +1 -1
  29. package/dist/storage/implementation/MongoPersistedSyncRules.d.ts +14 -0
  30. package/dist/storage/implementation/MongoPersistedSyncRules.js +64 -0
  31. package/dist/storage/implementation/MongoPersistedSyncRules.js.map +1 -0
  32. package/dist/storage/implementation/MongoPersistedSyncRulesContent.d.ts +3 -0
  33. package/dist/storage/implementation/MongoPersistedSyncRulesContent.js +11 -7
  34. package/dist/storage/implementation/MongoPersistedSyncRulesContent.js.map +1 -1
  35. package/dist/storage/implementation/MongoStorageProvider.js +1 -1
  36. package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
  37. package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +54 -30
  38. package/dist/storage/implementation/MongoSyncBucketStorage.js +118 -472
  39. package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
  40. package/dist/storage/implementation/MongoSyncRulesLock.d.ts +7 -5
  41. package/dist/storage/implementation/MongoSyncRulesLock.js +12 -10
  42. package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
  43. package/dist/storage/implementation/MongoWriteCheckpointAPI.d.ts +4 -4
  44. package/dist/storage/implementation/MongoWriteCheckpointAPI.js +1 -1
  45. package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
  46. package/dist/storage/implementation/OperationBatch.js +3 -2
  47. package/dist/storage/implementation/OperationBatch.js.map +1 -1
  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 +36 -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 +38 -4
  70. package/dist/storage/implementation/db.js +80 -1
  71. package/dist/storage/implementation/db.js.map +1 -1
  72. package/dist/storage/implementation/models.d.ts +66 -25
  73. package/dist/storage/implementation/models.js +22 -2
  74. package/dist/storage/implementation/models.js.map +1 -1
  75. package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +13 -0
  76. package/dist/storage/implementation/v1/MongoBucketBatchV1.js +22 -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 +41 -0
  88. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +269 -0
  89. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js.map +1 -0
  90. package/dist/storage/implementation/v1/PersistedBatchV1.d.ts +26 -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 +34 -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 +13 -0
  106. package/dist/storage/implementation/v3/MongoBucketBatchV3.js +34 -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 +5 -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 +41 -0
  121. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +404 -0
  122. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -0
  123. package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +29 -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 +21 -0
  133. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +71 -0
  134. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js.map +1 -0
  135. package/dist/storage/implementation/v3/models.d.ts +43 -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 +8 -5
  139. package/dist/storage/storage-index.js +8 -5
  140. package/dist/storage/storage-index.js.map +1 -1
  141. package/dist/utils/test-utils.d.ts +4 -1
  142. package/dist/utils/test-utils.js +15 -12
  143. package/dist/utils/test-utils.js.map +1 -1
  144. package/dist/utils/util.d.ts +13 -5
  145. package/dist/utils/util.js +40 -5
  146. package/dist/utils/util.js.map +1 -1
  147. package/package.json +9 -9
  148. package/src/migrations/db/migrations/1688556755264-initial-sync-rules.ts +1 -1
  149. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -7
  150. package/src/migrations/db/migrations/1770213298299-storage-version.ts +1 -1
  151. package/src/storage/MongoBucketStorage.ts +111 -55
  152. package/src/storage/MongoReportStorage.ts +2 -2
  153. package/src/storage/implementation/BucketDefinitionMapping.ts +72 -0
  154. package/src/storage/implementation/MongoBucketBatch.ts +322 -270
  155. package/src/storage/implementation/MongoBucketBatchShared.ts +11 -0
  156. package/src/storage/implementation/MongoChecksums.ts +54 -75
  157. package/src/storage/implementation/MongoCompactor.ts +411 -412
  158. package/src/storage/implementation/MongoParameterCompactor.ts +52 -26
  159. package/src/storage/implementation/MongoPersistedSyncRules.ts +76 -0
  160. package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +19 -10
  161. package/src/storage/implementation/MongoStorageProvider.ts +1 -1
  162. package/src/storage/implementation/MongoSyncBucketStorage.ts +206 -466
  163. package/src/storage/implementation/MongoSyncRulesLock.ts +14 -16
  164. package/src/storage/implementation/MongoWriteCheckpointAPI.ts +7 -5
  165. package/src/storage/implementation/OperationBatch.ts +3 -2
  166. package/src/storage/implementation/common/BucketDataDoc.ts +37 -0
  167. package/src/storage/implementation/common/MongoSyncBucketStorageContext.ts +15 -0
  168. package/src/storage/implementation/common/PersistedBatch.ts +364 -0
  169. package/src/storage/implementation/common/SingleBucketStore.ts +63 -0
  170. package/src/storage/implementation/common/SourceRecordStore.ts +49 -0
  171. package/src/storage/implementation/common/VersionedPowerSyncMongoBase.ts +80 -0
  172. package/src/storage/implementation/createMongoSyncBucketStorage.ts +25 -0
  173. package/src/storage/implementation/db.ts +115 -8
  174. package/src/storage/implementation/models.ts +88 -28
  175. package/src/storage/implementation/v1/MongoBucketBatchV1.ts +32 -0
  176. package/src/storage/implementation/v1/MongoChecksumsV1.ts +75 -0
  177. package/src/storage/implementation/v1/MongoCompactorV1.ts +93 -0
  178. package/src/storage/implementation/v1/MongoParameterCompactorV1.ts +26 -0
  179. package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +432 -0
  180. package/src/storage/implementation/v1/PersistedBatchV1.ts +230 -0
  181. package/src/storage/implementation/v1/SingleBucketStoreV1.ts +74 -0
  182. package/src/storage/implementation/v1/SourceRecordStoreV1.ts +156 -0
  183. package/src/storage/implementation/v1/VersionedPowerSyncMongoV1.ts +28 -0
  184. package/src/storage/implementation/v1/models.ts +84 -0
  185. package/src/storage/implementation/v3/MongoBucketBatchV3.ts +44 -0
  186. package/src/storage/implementation/v3/MongoChecksumsV3.ts +120 -0
  187. package/src/storage/implementation/v3/MongoCompactorV3.ts +107 -0
  188. package/src/storage/implementation/v3/MongoParameterCompactorV3.ts +24 -0
  189. package/src/storage/implementation/v3/MongoParameterLookupV3.ts +12 -0
  190. package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +545 -0
  191. package/src/storage/implementation/v3/PersistedBatchV3.ts +318 -0
  192. package/src/storage/implementation/v3/SingleBucketStoreV3.ts +68 -0
  193. package/src/storage/implementation/v3/SourceRecordStoreV3.ts +226 -0
  194. package/src/storage/implementation/v3/VersionedPowerSyncMongoV3.ts +112 -0
  195. package/src/storage/implementation/v3/models.ts +96 -0
  196. package/src/storage/storage-index.ts +8 -5
  197. package/src/utils/test-utils.ts +15 -12
  198. package/src/utils/util.ts +53 -9
  199. package/test/src/__snapshots__/storage.test.ts.snap +201 -0
  200. package/test/src/__snapshots__/storage_compacting.test.ts.snap +17 -0
  201. package/test/src/__snapshots__/storage_sync.test.ts.snap +1393 -16
  202. package/test/src/connection-report-storage.test.ts +3 -3
  203. package/test/src/setup.ts +1 -1
  204. package/test/src/storage.test.ts +10 -8
  205. package/test/src/storage_compacting.test.ts +146 -46
  206. package/test/src/storage_sync.test.ts +404 -56
  207. package/test/src/util.ts +3 -3
  208. package/test/tsconfig.json +0 -1
  209. package/tsconfig.tsbuildinfo +1 -1
  210. package/dist/storage/implementation/PersistedBatch.d.ts +0 -64
  211. package/dist/storage/implementation/PersistedBatch.js +0 -323
  212. package/dist/storage/implementation/PersistedBatch.js.map +0 -1
  213. package/src/storage/implementation/PersistedBatch.ts +0 -401
@@ -0,0 +1,112 @@
1
+ import { mongo } from '@powersync/lib-service-mongodb';
2
+ import { BucketDefinitionId, ParameterIndexId } from '../BucketDefinitionMapping.js';
3
+ import { BaseVersionedPowerSyncMongo } from '../common/VersionedPowerSyncMongoBase.js';
4
+ import { CommonSourceTableDocument } from '../models.js';
5
+ import {
6
+ BucketDataDocumentV3,
7
+ BucketParameterDocumentV3,
8
+ BucketStateDocumentV3,
9
+ CurrentDataDocumentV3,
10
+ SourceTableDocumentV3
11
+ } from './models.js';
12
+
13
+ export class VersionedPowerSyncMongoV3 extends BaseVersionedPowerSyncMongo {
14
+ sourceRecordsV3(replicationStreamId: number, sourceTableId: mongo.ObjectId): mongo.Collection<CurrentDataDocumentV3> {
15
+ const collectionName = this.sourceRecordsCollectionName(replicationStreamId, sourceTableId);
16
+ return this.db.collection<CurrentDataDocumentV3>(collectionName);
17
+ }
18
+
19
+ async listSourceRecordCollectionsV3(replicationStreamId: number): Promise<mongo.Collection<CurrentDataDocumentV3>[]> {
20
+ return this.listCollectionsByPrefix<CurrentDataDocumentV3>(`source_records_${replicationStreamId}_`);
21
+ }
22
+
23
+ async initializeSourceRecordsCollection(replicationStreamId: number, sourceTableId: mongo.ObjectId) {
24
+ await this.sourceRecordsV3(replicationStreamId, sourceTableId).createIndex(
25
+ {
26
+ pending_delete: 1
27
+ },
28
+ {
29
+ partialFilterExpression: { pending_delete: { $exists: true } },
30
+ name: 'pending_delete'
31
+ }
32
+ );
33
+ }
34
+
35
+ commonSourceTables(replicationStreamId: number): mongo.Collection<CommonSourceTableDocument> {
36
+ return this.sourceTablesV3(replicationStreamId) as mongo.Collection<CommonSourceTableDocument>;
37
+ }
38
+
39
+ bucketStateV3(replicationStreamId: number): mongo.Collection<BucketStateDocumentV3> {
40
+ return this.db.collection(`bucket_state_${replicationStreamId}`);
41
+ }
42
+
43
+ parameterIndexV3(
44
+ replicationStreamId: number,
45
+ indexId: ParameterIndexId
46
+ ): mongo.Collection<BucketParameterDocumentV3> {
47
+ return this.db.collection(`parameter_index_${replicationStreamId}_${indexId}`);
48
+ }
49
+
50
+ sourceTablesV3(replicationStreamId: number): mongo.Collection<SourceTableDocumentV3> {
51
+ return this.db.collection<SourceTableDocumentV3>(this.sourceTableCollectionName(replicationStreamId));
52
+ }
53
+
54
+ async initializeStreamStorage(replicationStreamId: number) {
55
+ const sourceTables = this.sourceTablesV3(replicationStreamId);
56
+ const bucketState = this.bucketStateV3(replicationStreamId);
57
+ await sourceTables.createIndex(
58
+ {
59
+ connection_id: 1,
60
+ schema_name: 1,
61
+ table_name: 1,
62
+ relation_id: 1
63
+ },
64
+ {
65
+ name: 'source_lookup'
66
+ }
67
+ );
68
+ await sourceTables.createIndex(
69
+ {
70
+ latest_pending_delete: 1
71
+ },
72
+ {
73
+ partialFilterExpression: { latest_pending_delete: { $exists: true } },
74
+ name: 'latest_pending_delete'
75
+ }
76
+ );
77
+ await bucketState.createIndex(
78
+ {
79
+ last_op: 1
80
+ },
81
+ { name: 'bucket_updates', unique: true }
82
+ );
83
+ await bucketState.createIndex(
84
+ {
85
+ 'estimate_since_compact.count': -1
86
+ },
87
+ { name: 'dirty_count' }
88
+ );
89
+ }
90
+
91
+ bucketDataV3(replicationStreamId: number, definitionId: BucketDefinitionId) {
92
+ return this.db.collection<BucketDataDocumentV3>(`bucket_data_${replicationStreamId}_${definitionId}`);
93
+ }
94
+
95
+ listBucketDataCollectionsV3(replicationStreamId: number) {
96
+ return this.upstream.listBucketDataCollectionsV3(replicationStreamId);
97
+ }
98
+
99
+ async listParameterIndexCollectionsV3(
100
+ replicationStreamId: number
101
+ ): Promise<{ collection: mongo.Collection<BucketParameterDocumentV3>; indexId: ParameterIndexId }[]> {
102
+ const prefix = `parameter_index_${replicationStreamId}_`;
103
+ const collections = await this.db.listCollections({ name: new RegExp(`^${prefix}`) }, { nameOnly: true }).toArray();
104
+
105
+ return collections
106
+ .filter((collection) => collection.name.startsWith(prefix))
107
+ .map((collection) => ({
108
+ collection: this.db.collection<BucketParameterDocumentV3>(collection.name),
109
+ indexId: collection.name.slice(prefix.length)
110
+ }));
111
+ }
112
+ }
@@ -0,0 +1,96 @@
1
+ import { InternalOpId } from '@powersync/service-core';
2
+ import * as bson from 'bson';
3
+ import { BucketDefinitionId, ParameterIndexId } from '../BucketDefinitionMapping.js';
4
+ import { BucketDataDoc, BucketKey } from '../common/BucketDataDoc.js';
5
+ import {
6
+ BucketDataDocumentBase,
7
+ BucketDataKey,
8
+ BucketParameterDocumentBase,
9
+ BucketStateDocumentBase,
10
+ CurrentBucket,
11
+ ReplicaId,
12
+ SourceTableDocument,
13
+ SourceTableKey,
14
+ TaggedBucketParameterDocument
15
+ } from '../models.js';
16
+
17
+ export interface CurrentBucketV3 extends CurrentBucket {
18
+ def: BucketDefinitionId;
19
+ }
20
+
21
+ export interface RecordedLookupV3 {
22
+ i: ParameterIndexId;
23
+ l: bson.Binary;
24
+ }
25
+
26
+ export interface CurrentDataDocumentV3 {
27
+ _id: ReplicaId;
28
+ data: bson.Binary | null;
29
+ buckets: CurrentBucketV3[];
30
+ lookups: RecordedLookupV3[];
31
+ /**
32
+ * If set, this can be deleted, once there is a consistent checkpoint >= pending_delete.
33
+ *
34
+ * This must only be set if buckets = [], lookups = [].
35
+ */
36
+ pending_delete?: bigint;
37
+ }
38
+
39
+ export interface BucketParameterDocumentV3 extends BucketParameterDocumentBase<SourceTableKey> {}
40
+
41
+ export type BucketDataKeyV3 = BucketDataKey;
42
+
43
+ export interface BucketDataDocumentV3 extends BucketDataDocumentBase {
44
+ _id: BucketDataKeyV3;
45
+ }
46
+
47
+ export function serializeBucketDataV3(document: BucketDataDoc): BucketDataDocumentV3 {
48
+ const { bucketKey, o } = document;
49
+ return {
50
+ _id: {
51
+ b: bucketKey.bucket,
52
+ o: o
53
+ },
54
+ // List fields directly, so that we don't accidentally persist any unknown fields
55
+ op: document.op,
56
+ source_table: document.source_table,
57
+ source_key: document.source_key,
58
+ table: document.table,
59
+ row_id: document.row_id,
60
+ checksum: document.checksum,
61
+ data: document.data,
62
+ target_op: document.target_op
63
+ };
64
+ }
65
+
66
+ export function loadBucketDataDocumentV3(
67
+ context: Pick<BucketKey, 'replicationStreamId' | 'definitionId'>,
68
+ doc: BucketDataDocumentV3
69
+ ): BucketDataDoc {
70
+ const { _id, ...rest } = doc;
71
+ return {
72
+ bucketKey: {
73
+ ...context,
74
+ bucket: _id.b
75
+ },
76
+ o: _id.o,
77
+ ...rest
78
+ };
79
+ }
80
+
81
+ export function taggedBucketParameterDocumentToV3(document: TaggedBucketParameterDocument): BucketParameterDocumentV3 {
82
+ const { index: _index, ...rest } = document;
83
+ return rest as BucketParameterDocumentV3;
84
+ }
85
+
86
+ export interface SourceTableDocumentV3 extends SourceTableDocument {
87
+ bucket_data_source_ids: BucketDefinitionId[];
88
+ parameter_lookup_source_ids: ParameterIndexId[];
89
+ latest_pending_delete?: InternalOpId | undefined;
90
+ }
91
+
92
+ export interface BucketStateDocumentV3 extends BucketStateDocumentBase {
93
+ _id: BucketStateDocumentBase['_id'] & {
94
+ d: BucketDefinitionId;
95
+ };
96
+ }
@@ -1,14 +1,17 @@
1
+ export * as test_utils from '../utils/test-utils.js';
2
+ export * from '../utils/util.js';
3
+ export * from './implementation/BucketDefinitionMapping.js';
4
+ export * from './implementation/common/PersistedBatch.js';
5
+ export * from './implementation/createMongoSyncBucketStorage.js';
1
6
  export * from './implementation/db.js';
2
7
  export * from './implementation/models.js';
3
- export * from './implementation/MongoBucketBatch.js';
4
8
  export * from './implementation/MongoIdSequence.js';
9
+ export * from './implementation/MongoPersistedSyncRules.js';
5
10
  export * from './implementation/MongoPersistedSyncRulesContent.js';
6
11
  export * from './implementation/MongoStorageProvider.js';
7
- export * from './implementation/MongoSyncBucketStorage.js';
8
12
  export * from './implementation/MongoSyncRulesLock.js';
9
13
  export * from './implementation/OperationBatch.js';
10
- export * from './implementation/PersistedBatch.js';
11
- export * from '../utils/util.js';
14
+ export * from './implementation/v1/models.js';
15
+ export * from './implementation/v3/models.js';
12
16
  export * from './MongoBucketStorage.js';
13
17
  export * from './MongoReportStorage.js';
14
- export * as test_utils from '../utils/test-utils.js';
@@ -11,22 +11,25 @@ export type MongoTestStorageOptions = {
11
11
  };
12
12
 
13
13
  export function mongoTestStorageFactoryGenerator(factoryOptions: MongoTestStorageOptions) {
14
- return async (options?: TestStorageOptions) => {
15
- const db = connectMongoForTests(factoryOptions.url, factoryOptions.isCI);
14
+ return {
15
+ factory: async (options?: TestStorageOptions) => {
16
+ const db = connectMongoForTests(factoryOptions.url, factoryOptions.isCI);
16
17
 
17
- // None of the tests insert data into this collection, so it was never created
18
- if (!(await db.db.listCollections({ name: db.bucket_parameters.collectionName }).hasNext())) {
19
- await db.db.createCollection('bucket_parameters');
20
- }
18
+ // None of the tests insert data into this collection, so it was never created
19
+ if (!(await db.db.listCollections({ name: db.bucket_parameters.collectionName }).hasNext())) {
20
+ await db.db.createCollection('bucket_parameters');
21
+ }
21
22
 
22
- // Full migrations are not currently run for tests, so we manually create this
23
- await db.createCheckpointEventsCollection();
23
+ // Full migrations are not currently run for tests, so we manually create this
24
+ await db.createCheckpointEventsCollection();
24
25
 
25
- if (!options?.doNotClear) {
26
- await db.clear();
27
- }
26
+ if (!options?.doNotClear) {
27
+ await db.clear();
28
+ }
28
29
 
29
- return new MongoBucketStorage(db, { slot_name_prefix: 'test_' }, factoryOptions.internalOptions);
30
+ return new MongoBucketStorage(db, { slot_name_prefix: 'test_' }, factoryOptions.internalOptions);
31
+ },
32
+ tableIdStrings: false
30
33
  };
31
34
  }
32
35
 
package/src/utils/util.ts CHANGED
@@ -1,10 +1,12 @@
1
+ import * as lib_mongo from '@powersync/lib-service-mongodb';
2
+ import { mongo } from '@powersync/lib-service-mongodb';
3
+ import { ReplicationAbortedError, ServiceAssertionError } from '@powersync/lib-services-framework';
4
+ import { storage, utils } from '@powersync/service-core';
1
5
  import * as bson from 'bson';
2
6
  import * as crypto from 'crypto';
7
+ import * as timers from 'node:timers/promises';
3
8
  import * as uuid from 'uuid';
4
- import { mongo } from '@powersync/lib-service-mongodb';
5
- import { storage, utils } from '@powersync/service-core';
6
- import { ServiceAssertionError } from '@powersync/lib-services-framework';
7
- import { BucketDataDocument } from '../storage/implementation/models.js';
9
+ import { BucketDataDoc } from '../storage/implementation/common/BucketDataDoc.js';
8
10
 
9
11
  export function idPrefixFilter<T>(prefix: Partial<T>, rest: (keyof T)[]): mongo.Condition<T> {
10
12
  let filter = {
@@ -69,10 +71,10 @@ export async function readSingleBatch<T>(cursor: mongo.AbstractCursor<T>): Promi
69
71
  }
70
72
  }
71
73
 
72
- export function mapOpEntry(row: BucketDataDocument): utils.OplogEntry {
74
+ export function mapOpEntry(row: BucketDataDoc): utils.OplogEntry {
73
75
  if (row.op == 'PUT' || row.op == 'REMOVE') {
74
76
  return {
75
- op_id: utils.internalToExternalOpId(row._id.o),
77
+ op_id: utils.internalToExternalOpId(row.o),
76
78
  op: row.op,
77
79
  object_type: row.table,
78
80
  object_id: row.row_id,
@@ -84,17 +86,17 @@ export function mapOpEntry(row: BucketDataDocument): utils.OplogEntry {
84
86
  // MOVE, CLEAR
85
87
 
86
88
  return {
87
- op_id: utils.internalToExternalOpId(row._id.o),
89
+ op_id: utils.internalToExternalOpId(row.o),
88
90
  op: row.op,
89
91
  checksum: Number(row.checksum)
90
92
  };
91
93
  }
92
94
  }
93
95
 
94
- export function replicaIdToSubkey(table: bson.ObjectId, id: storage.ReplicaId): string {
96
+ export function replicaIdToSubkey(table: storage.SourceTableId, id: storage.ReplicaId): string {
95
97
  if (storage.isUUID(id)) {
96
98
  // Special case for UUID for backwards-compatiblity
97
- return `${table.toHexString()}/${id.toHexString()}`;
99
+ return `${tableIdString(table)}/${id.toHexString()}`;
98
100
  } else {
99
101
  // Hashed UUID from the table and id
100
102
  const repr = bson.serialize({ table, id });
@@ -102,6 +104,21 @@ export function replicaIdToSubkey(table: bson.ObjectId, id: storage.ReplicaId):
102
104
  }
103
105
  }
104
106
 
107
+ export function mongoTableId(table: storage.SourceTableId): bson.ObjectId {
108
+ if (typeof table == 'string') {
109
+ throw new ServiceAssertionError(`Got string table id, expected ObjectId`);
110
+ }
111
+ return table;
112
+ }
113
+
114
+ function tableIdString(table: storage.SourceTableId) {
115
+ if (typeof table == 'string') {
116
+ return table;
117
+ } else {
118
+ return table.toHexString();
119
+ }
120
+ }
121
+
105
122
  export function setSessionSnapshotTime(session: mongo.ClientSession, time: bson.Timestamp) {
106
123
  // This is a workaround for the lack of direct support for snapshot reads in the MongoDB driver.
107
124
  if (!session.snapshotEnabled) {
@@ -114,6 +131,33 @@ export function setSessionSnapshotTime(session: mongo.ClientSession, time: bson.
114
131
  }
115
132
  }
116
133
 
134
+ export async function retryOnMongoMaxTimeMSExpired<T>(
135
+ operation: () => Promise<T>,
136
+ options: {
137
+ signal?: AbortSignal;
138
+ abortMessage?: string;
139
+ retryDelayMs: number;
140
+ onRetry?: (retryCount: number) => void;
141
+ }
142
+ ): Promise<T> {
143
+ let retryCount = 0;
144
+ while (true) {
145
+ if (options.signal?.aborted) {
146
+ throw new ReplicationAbortedError(options.abortMessage ?? 'Aborted MongoDB operation', options.signal.reason);
147
+ }
148
+ try {
149
+ return await operation();
150
+ } catch (e) {
151
+ if (!lib_mongo.isMongoServerError(e) || e.codeName !== 'MaxTimeMSExpired') {
152
+ throw e;
153
+ }
154
+ retryCount += 1;
155
+ options.onRetry?.(retryCount);
156
+ await timers.setTimeout(options.retryDelayMs);
157
+ }
158
+ }
159
+ }
160
+
117
161
  export const createPaginatedConnectionQuery = async <T extends mongo.Document>(
118
162
  query: mongo.Filter<T>,
119
163
  collection: mongo.Collection<T>,
@@ -0,0 +1,201 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Mongo Sync Bucket Storage - Data > (insert, delete, insert), (delete) 1`] = `
4
+ [
5
+ {
6
+ "checksum": 2871785649,
7
+ "object_id": "test1",
8
+ "op": "PUT",
9
+ },
10
+ {
11
+ "checksum": 2872534815,
12
+ "object_id": "test1",
13
+ "op": "REMOVE",
14
+ },
15
+ {
16
+ "checksum": 2871785649,
17
+ "object_id": "test1",
18
+ "op": "PUT",
19
+ },
20
+ {
21
+ "checksum": 2872534815,
22
+ "object_id": "test1",
23
+ "op": "REMOVE",
24
+ },
25
+ ]
26
+ `;
27
+
28
+ exports[`Mongo Sync Bucket Storage - Data > (insert, delete, insert), (delete) 2`] = `
29
+ [
30
+ {
31
+ "checksum": 2871785649,
32
+ "object_id": "test1",
33
+ "op": "PUT",
34
+ },
35
+ {
36
+ "checksum": 2872534815,
37
+ "object_id": "test1",
38
+ "op": "REMOVE",
39
+ },
40
+ {
41
+ "checksum": 2871785649,
42
+ "object_id": "test1",
43
+ "op": "PUT",
44
+ },
45
+ {
46
+ "checksum": 2872534815,
47
+ "object_id": "test1",
48
+ "op": "REMOVE",
49
+ },
50
+ ]
51
+ `;
52
+
53
+ exports[`Mongo Sync Bucket Storage - Data > (insert, delete, insert), (delete) 3`] = `
54
+ [
55
+ {
56
+ "checksum": 2871785649,
57
+ "object_id": "test1",
58
+ "op": "PUT",
59
+ },
60
+ {
61
+ "checksum": 2872534815,
62
+ "object_id": "test1",
63
+ "op": "REMOVE",
64
+ },
65
+ {
66
+ "checksum": 2871785649,
67
+ "object_id": "test1",
68
+ "op": "PUT",
69
+ },
70
+ {
71
+ "checksum": 2872534815,
72
+ "object_id": "test1",
73
+ "op": "REMOVE",
74
+ },
75
+ ]
76
+ `;
77
+
78
+ exports[`Mongo Sync Bucket Storage - Data - v1 > (insert, delete, insert), (delete) 1`] = `
79
+ [
80
+ {
81
+ "checksum": 2871785649,
82
+ "object_id": "test1",
83
+ "op": "PUT",
84
+ },
85
+ {
86
+ "checksum": 2872534815,
87
+ "object_id": "test1",
88
+ "op": "REMOVE",
89
+ },
90
+ {
91
+ "checksum": 2871785649,
92
+ "object_id": "test1",
93
+ "op": "PUT",
94
+ },
95
+ {
96
+ "checksum": 2872534815,
97
+ "object_id": "test1",
98
+ "op": "REMOVE",
99
+ },
100
+ ]
101
+ `;
102
+
103
+ exports[`Mongo Sync Bucket Storage - Data - v2 > (insert, delete, insert), (delete) 1`] = `
104
+ [
105
+ {
106
+ "checksum": 2871785649,
107
+ "object_id": "test1",
108
+ "op": "PUT",
109
+ },
110
+ {
111
+ "checksum": 2872534815,
112
+ "object_id": "test1",
113
+ "op": "REMOVE",
114
+ },
115
+ {
116
+ "checksum": 2871785649,
117
+ "object_id": "test1",
118
+ "op": "PUT",
119
+ },
120
+ {
121
+ "checksum": 2872534815,
122
+ "object_id": "test1",
123
+ "op": "REMOVE",
124
+ },
125
+ ]
126
+ `;
127
+
128
+ exports[`Mongo Sync Bucket Storage - Data - v3 > (insert, delete, insert), (delete) 1`] = `
129
+ [
130
+ {
131
+ "checksum": 2871785649,
132
+ "object_id": "test1",
133
+ "op": "PUT",
134
+ },
135
+ {
136
+ "checksum": 2872534815,
137
+ "object_id": "test1",
138
+ "op": "REMOVE",
139
+ },
140
+ {
141
+ "checksum": 2871785649,
142
+ "object_id": "test1",
143
+ "op": "PUT",
144
+ },
145
+ {
146
+ "checksum": 2872534815,
147
+ "object_id": "test1",
148
+ "op": "REMOVE",
149
+ },
150
+ ]
151
+ `;
152
+
153
+ exports[`Mongo Sync Bucket Storage - split buckets > (insert, delete, insert), (delete) 1`] = `
154
+ [
155
+ {
156
+ "checksum": 2871785649,
157
+ "object_id": "test1",
158
+ "op": "PUT",
159
+ },
160
+ {
161
+ "checksum": 2872534815,
162
+ "object_id": "test1",
163
+ "op": "REMOVE",
164
+ },
165
+ {
166
+ "checksum": 2871785649,
167
+ "object_id": "test1",
168
+ "op": "PUT",
169
+ },
170
+ {
171
+ "checksum": 2872534815,
172
+ "object_id": "test1",
173
+ "op": "REMOVE",
174
+ },
175
+ ]
176
+ `;
177
+
178
+ exports[`Mongo Sync Bucket Storage - split operations > (insert, delete, insert), (delete) 1`] = `
179
+ [
180
+ {
181
+ "checksum": 2871785649,
182
+ "object_id": "test1",
183
+ "op": "PUT",
184
+ },
185
+ {
186
+ "checksum": 2872534815,
187
+ "object_id": "test1",
188
+ "op": "REMOVE",
189
+ },
190
+ {
191
+ "checksum": 2871785649,
192
+ "object_id": "test1",
193
+ "op": "PUT",
194
+ },
195
+ {
196
+ "checksum": 2872534815,
197
+ "object_id": "test1",
198
+ "op": "REMOVE",
199
+ },
200
+ ]
201
+ `;
@@ -0,0 +1,17 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Mongo Sync Bucket Storage Compact > partial checksums after compacting (2) 1`] = `
4
+ {
5
+ "bucket": "1#global[]",
6
+ "checksum": -1481659821,
7
+ "count": 1,
8
+ }
9
+ `;
10
+
11
+ exports[`Mongo Sync Bucket Storage Compact > partial checksums after compacting 1`] = `
12
+ {
13
+ "bucket": "1#global[]",
14
+ "checksum": 1874612650,
15
+ "count": 4,
16
+ }
17
+ `;