@powersync/service-module-mongodb-storage 0.15.3 → 0.16.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 (204) hide show
  1. package/CHANGELOG.md +54 -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 +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 +50 -36
  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 +16 -14
  15. package/dist/storage/implementation/MongoBucketBatch.js +80 -115
  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 +28 -17
  21. package/dist/storage/implementation/MongoChecksums.js +13 -72
  22. package/dist/storage/implementation/MongoChecksums.js.map +1 -1
  23. package/dist/storage/implementation/MongoCompactor.d.ts +98 -58
  24. package/dist/storage/implementation/MongoCompactor.js +229 -296
  25. package/dist/storage/implementation/MongoCompactor.js.map +1 -1
  26. package/dist/storage/implementation/MongoParameterCompactor.d.ts +11 -6
  27. package/dist/storage/implementation/MongoParameterCompactor.js +11 -8
  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 +9 -0
  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 +49 -30
  38. package/dist/storage/implementation/MongoSyncBucketStorage.js +96 -388
  39. package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
  40. package/dist/storage/implementation/MongoSyncRulesLock.d.ts +5 -3
  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.js +1 -1
  44. package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
  45. package/dist/storage/implementation/OperationBatch.js +1 -1
  46. package/dist/storage/implementation/common/BucketDataDoc.d.ts +35 -0
  47. package/dist/storage/implementation/common/BucketDataDoc.js +2 -0
  48. package/dist/storage/implementation/common/BucketDataDoc.js.map +1 -0
  49. package/dist/storage/implementation/common/MongoSyncBucketStorageContext.d.ts +13 -0
  50. package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js +2 -0
  51. package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js.map +1 -0
  52. package/dist/storage/implementation/common/PersistedBatch.d.ts +108 -0
  53. package/dist/storage/implementation/common/PersistedBatch.js +237 -0
  54. package/dist/storage/implementation/common/PersistedBatch.js.map +1 -0
  55. package/dist/storage/implementation/common/SingleBucketStore.d.ts +54 -0
  56. package/dist/storage/implementation/common/SingleBucketStore.js +3 -0
  57. package/dist/storage/implementation/common/SingleBucketStore.js.map +1 -0
  58. package/dist/storage/implementation/common/SourceRecordStore.d.ts +36 -0
  59. package/dist/storage/implementation/common/SourceRecordStore.js +2 -0
  60. package/dist/storage/implementation/common/SourceRecordStore.js.map +1 -0
  61. package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.d.ts +27 -0
  62. package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js +57 -0
  63. package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js.map +1 -0
  64. package/dist/storage/implementation/createMongoSyncBucketStorage.d.ts +7 -0
  65. package/dist/storage/implementation/createMongoSyncBucketStorage.js +9 -0
  66. package/dist/storage/implementation/createMongoSyncBucketStorage.js.map +1 -0
  67. package/dist/storage/implementation/db.d.ts +34 -34
  68. package/dist/storage/implementation/db.js +78 -98
  69. package/dist/storage/implementation/db.js.map +1 -1
  70. package/dist/storage/implementation/models.d.ts +63 -34
  71. package/dist/storage/implementation/models.js +21 -2
  72. package/dist/storage/implementation/models.js.map +1 -1
  73. package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +13 -0
  74. package/dist/storage/implementation/v1/MongoBucketBatchV1.js +22 -0
  75. package/dist/storage/implementation/v1/MongoBucketBatchV1.js.map +1 -0
  76. package/dist/storage/implementation/v1/MongoChecksumsV1.d.ts +12 -0
  77. package/dist/storage/implementation/v1/MongoChecksumsV1.js +56 -0
  78. package/dist/storage/implementation/v1/MongoChecksumsV1.js.map +1 -0
  79. package/dist/storage/implementation/v1/MongoCompactorV1.d.ts +23 -0
  80. package/dist/storage/implementation/v1/MongoCompactorV1.js +52 -0
  81. package/dist/storage/implementation/v1/MongoCompactorV1.js.map +1 -0
  82. package/dist/storage/implementation/v1/MongoParameterCompactorV1.d.ts +9 -0
  83. package/dist/storage/implementation/v1/MongoParameterCompactorV1.js +20 -0
  84. package/dist/storage/implementation/v1/MongoParameterCompactorV1.js.map +1 -0
  85. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.d.ts +41 -0
  86. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +283 -0
  87. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js.map +1 -0
  88. package/dist/storage/implementation/v1/PersistedBatchV1.d.ts +26 -0
  89. package/dist/storage/implementation/v1/PersistedBatchV1.js +183 -0
  90. package/dist/storage/implementation/v1/PersistedBatchV1.js.map +1 -0
  91. package/dist/storage/implementation/v1/SingleBucketStoreV1.d.ts +18 -0
  92. package/dist/storage/implementation/v1/SingleBucketStoreV1.js +57 -0
  93. package/dist/storage/implementation/v1/SingleBucketStoreV1.js.map +1 -0
  94. package/dist/storage/implementation/v1/SourceRecordStoreV1.d.ts +19 -0
  95. package/dist/storage/implementation/v1/SourceRecordStoreV1.js +105 -0
  96. package/dist/storage/implementation/v1/SourceRecordStoreV1.js.map +1 -0
  97. package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.d.ts +12 -0
  98. package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js +20 -0
  99. package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js.map +1 -0
  100. package/dist/storage/implementation/v1/models.d.ts +34 -0
  101. package/dist/storage/implementation/v1/models.js +37 -0
  102. package/dist/storage/implementation/v1/models.js.map +1 -0
  103. package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +13 -0
  104. package/dist/storage/implementation/v3/MongoBucketBatchV3.js +34 -0
  105. package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -0
  106. package/dist/storage/implementation/v3/MongoChecksumsV3.d.ts +15 -0
  107. package/dist/storage/implementation/v3/MongoChecksumsV3.js +84 -0
  108. package/dist/storage/implementation/v3/MongoChecksumsV3.js.map +1 -0
  109. package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +23 -0
  110. package/dist/storage/implementation/v3/MongoCompactorV3.js +68 -0
  111. package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -0
  112. package/dist/storage/implementation/v3/MongoParameterCompactorV3.d.ts +9 -0
  113. package/dist/storage/implementation/v3/MongoParameterCompactorV3.js +18 -0
  114. package/dist/storage/implementation/v3/MongoParameterCompactorV3.js.map +1 -0
  115. package/dist/storage/implementation/v3/MongoParameterLookupV3.d.ts +5 -0
  116. package/dist/storage/implementation/v3/MongoParameterLookupV3.js +9 -0
  117. package/dist/storage/implementation/v3/MongoParameterLookupV3.js.map +1 -0
  118. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.d.ts +41 -0
  119. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +407 -0
  120. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -0
  121. package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +29 -0
  122. package/dist/storage/implementation/v3/PersistedBatchV3.js +259 -0
  123. package/dist/storage/implementation/v3/PersistedBatchV3.js.map +1 -0
  124. package/dist/storage/implementation/v3/SingleBucketStoreV3.d.ts +18 -0
  125. package/dist/storage/implementation/v3/SingleBucketStoreV3.js +48 -0
  126. package/dist/storage/implementation/v3/SingleBucketStoreV3.js.map +1 -0
  127. package/dist/storage/implementation/v3/SourceRecordStoreV3.d.ts +22 -0
  128. package/dist/storage/implementation/v3/SourceRecordStoreV3.js +164 -0
  129. package/dist/storage/implementation/v3/SourceRecordStoreV3.js.map +1 -0
  130. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.d.ts +21 -0
  131. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +71 -0
  132. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js.map +1 -0
  133. package/dist/storage/implementation/v3/models.d.ts +43 -0
  134. package/dist/storage/implementation/v3/models.js +34 -0
  135. package/dist/storage/implementation/v3/models.js.map +1 -0
  136. package/dist/storage/storage-index.d.ts +8 -5
  137. package/dist/storage/storage-index.js +8 -5
  138. package/dist/storage/storage-index.js.map +1 -1
  139. package/dist/utils/util.d.ts +11 -4
  140. package/dist/utils/util.js +25 -4
  141. package/dist/utils/util.js.map +1 -1
  142. package/package.json +9 -9
  143. package/src/migrations/db/migrations/1688556755264-initial-sync-rules.ts +1 -1
  144. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -7
  145. package/src/migrations/db/migrations/1770213298299-storage-version.ts +1 -1
  146. package/src/storage/MongoBucketStorage.ts +97 -62
  147. package/src/storage/MongoReportStorage.ts +2 -2
  148. package/src/storage/implementation/BucketDefinitionMapping.ts +72 -0
  149. package/src/storage/implementation/MongoBucketBatch.ts +110 -144
  150. package/src/storage/implementation/MongoBucketBatchShared.ts +11 -0
  151. package/src/storage/implementation/MongoChecksums.ts +53 -76
  152. package/src/storage/implementation/MongoCompactor.ts +374 -404
  153. package/src/storage/implementation/MongoParameterCompactor.ts +37 -24
  154. package/src/storage/implementation/MongoPersistedSyncRules.ts +76 -0
  155. package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +18 -1
  156. package/src/storage/implementation/MongoStorageProvider.ts +1 -1
  157. package/src/storage/implementation/MongoSyncBucketStorage.ts +190 -457
  158. package/src/storage/implementation/MongoSyncRulesLock.ts +12 -14
  159. package/src/storage/implementation/MongoWriteCheckpointAPI.ts +4 -2
  160. package/src/storage/implementation/OperationBatch.ts +1 -1
  161. package/src/storage/implementation/common/BucketDataDoc.ts +37 -0
  162. package/src/storage/implementation/common/MongoSyncBucketStorageContext.ts +15 -0
  163. package/src/storage/implementation/common/PersistedBatch.ts +364 -0
  164. package/src/storage/implementation/common/SingleBucketStore.ts +63 -0
  165. package/src/storage/implementation/common/SourceRecordStore.ts +49 -0
  166. package/src/storage/implementation/common/VersionedPowerSyncMongoBase.ts +80 -0
  167. package/src/storage/implementation/createMongoSyncBucketStorage.ts +25 -0
  168. package/src/storage/implementation/db.ts +107 -128
  169. package/src/storage/implementation/models.ts +84 -38
  170. package/src/storage/implementation/v1/MongoBucketBatchV1.ts +32 -0
  171. package/src/storage/implementation/v1/MongoChecksumsV1.ts +75 -0
  172. package/src/storage/implementation/v1/MongoCompactorV1.ts +93 -0
  173. package/src/storage/implementation/v1/MongoParameterCompactorV1.ts +26 -0
  174. package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +448 -0
  175. package/src/storage/implementation/v1/PersistedBatchV1.ts +230 -0
  176. package/src/storage/implementation/v1/SingleBucketStoreV1.ts +74 -0
  177. package/src/storage/implementation/v1/SourceRecordStoreV1.ts +156 -0
  178. package/src/storage/implementation/v1/VersionedPowerSyncMongoV1.ts +28 -0
  179. package/src/storage/implementation/v1/models.ts +84 -0
  180. package/src/storage/implementation/v3/MongoBucketBatchV3.ts +44 -0
  181. package/src/storage/implementation/v3/MongoChecksumsV3.ts +120 -0
  182. package/src/storage/implementation/v3/MongoCompactorV3.ts +107 -0
  183. package/src/storage/implementation/v3/MongoParameterCompactorV3.ts +24 -0
  184. package/src/storage/implementation/v3/MongoParameterLookupV3.ts +12 -0
  185. package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +550 -0
  186. package/src/storage/implementation/v3/PersistedBatchV3.ts +318 -0
  187. package/src/storage/implementation/v3/SingleBucketStoreV3.ts +68 -0
  188. package/src/storage/implementation/v3/SourceRecordStoreV3.ts +226 -0
  189. package/src/storage/implementation/v3/VersionedPowerSyncMongoV3.ts +112 -0
  190. package/src/storage/implementation/v3/models.ts +96 -0
  191. package/src/storage/storage-index.ts +8 -5
  192. package/src/utils/util.ts +36 -7
  193. package/test/src/__snapshots__/storage_sync.test.ts.snap +282 -0
  194. package/test/src/connection-report-storage.test.ts +3 -3
  195. package/test/src/setup.ts +1 -1
  196. package/test/src/storage.test.ts +2 -2
  197. package/test/src/storage_compacting.test.ts +57 -29
  198. package/test/src/storage_sync.test.ts +351 -5
  199. package/test/tsconfig.json +0 -1
  200. package/tsconfig.tsbuildinfo +1 -1
  201. package/dist/storage/implementation/PersistedBatch.d.ts +0 -71
  202. package/dist/storage/implementation/PersistedBatch.js +0 -354
  203. package/dist/storage/implementation/PersistedBatch.js.map +0 -1
  204. package/src/storage/implementation/PersistedBatch.ts +0 -432
@@ -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';
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,7 +86,7 @@ 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
  };
@@ -129,6 +131,33 @@ export function setSessionSnapshotTime(session: mongo.ClientSession, time: bson.
129
131
  }
130
132
  }
131
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
+
132
161
  export const createPaginatedConnectionQuery = async <T extends mongo.Document>(
133
162
  query: mongo.Filter<T>,
134
163
  collection: mongo.Collection<T>,
@@ -1,5 +1,99 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
+ exports[`sync - mongodb > storage v1 > can override priority when subscribing to stream 1`] = `
4
+ [
5
+ {
6
+ "checkpoint": {
7
+ "buckets": [
8
+ {
9
+ "bucket": "1#todos|0["a"]",
10
+ "checksum": -1712802421,
11
+ "count": 1,
12
+ "priority": 0,
13
+ "subscriptions": [
14
+ {
15
+ "sub": 0,
16
+ },
17
+ {
18
+ "sub": 1,
19
+ },
20
+ ],
21
+ },
22
+ {
23
+ "bucket": "1#todos|0["b"]",
24
+ "checksum": -1291414318,
25
+ "count": 1,
26
+ "priority": 3,
27
+ "subscriptions": [
28
+ {
29
+ "sub": 1,
30
+ },
31
+ ],
32
+ },
33
+ ],
34
+ "last_op_id": "2",
35
+ "streams": [
36
+ {
37
+ "errors": [],
38
+ "is_default": false,
39
+ "name": "todos",
40
+ },
41
+ ],
42
+ "write_checkpoint": undefined,
43
+ },
44
+ },
45
+ {
46
+ "data": {
47
+ "after": "0",
48
+ "bucket": "1#todos|0["a"]",
49
+ "data": [
50
+ {
51
+ "checksum": 2582164875,
52
+ "data": "{"id":"a","description":"Test 1"}",
53
+ "object_id": "a",
54
+ "object_type": "test",
55
+ "op": "PUT",
56
+ "op_id": "1",
57
+ "subkey": "e5aa2ddc-1328-58fa-a000-0b5ed31eaf1a",
58
+ },
59
+ ],
60
+ "has_more": false,
61
+ "next_after": "1",
62
+ },
63
+ },
64
+ {
65
+ "partial_checkpoint_complete": {
66
+ "last_op_id": "2",
67
+ "priority": 0,
68
+ },
69
+ },
70
+ {
71
+ "data": {
72
+ "after": "0",
73
+ "bucket": "1#todos|0["b"]",
74
+ "data": [
75
+ {
76
+ "checksum": 3003552978,
77
+ "data": "{"id":"b","description":"Test 2"}",
78
+ "object_id": "b",
79
+ "object_type": "test",
80
+ "op": "PUT",
81
+ "op_id": "2",
82
+ "subkey": "0dfe86bd-d15b-5fd0-9c7b-a31693030ee0",
83
+ },
84
+ ],
85
+ "has_more": false,
86
+ "next_after": "2",
87
+ },
88
+ },
89
+ {
90
+ "checkpoint_complete": {
91
+ "last_op_id": "2",
92
+ },
93
+ },
94
+ ]
95
+ `;
96
+
3
97
  exports[`sync - mongodb > storage v1 > compacting data - invalidate checkpoint 1`] = `
4
98
  [
5
99
  {
@@ -1095,6 +1189,100 @@ exports[`sync - mongodb > storage v1 > sync updates to parameter query only 2`]
1095
1189
  ]
1096
1190
  `;
1097
1191
 
1192
+ exports[`sync - mongodb > storage v2 > can override priority when subscribing to stream 1`] = `
1193
+ [
1194
+ {
1195
+ "checkpoint": {
1196
+ "buckets": [
1197
+ {
1198
+ "bucket": "1#todos|0["a"]",
1199
+ "checksum": -1712802421,
1200
+ "count": 1,
1201
+ "priority": 0,
1202
+ "subscriptions": [
1203
+ {
1204
+ "sub": 0,
1205
+ },
1206
+ {
1207
+ "sub": 1,
1208
+ },
1209
+ ],
1210
+ },
1211
+ {
1212
+ "bucket": "1#todos|0["b"]",
1213
+ "checksum": -1291414318,
1214
+ "count": 1,
1215
+ "priority": 3,
1216
+ "subscriptions": [
1217
+ {
1218
+ "sub": 1,
1219
+ },
1220
+ ],
1221
+ },
1222
+ ],
1223
+ "last_op_id": "2",
1224
+ "streams": [
1225
+ {
1226
+ "errors": [],
1227
+ "is_default": false,
1228
+ "name": "todos",
1229
+ },
1230
+ ],
1231
+ "write_checkpoint": undefined,
1232
+ },
1233
+ },
1234
+ {
1235
+ "data": {
1236
+ "after": "0",
1237
+ "bucket": "1#todos|0["a"]",
1238
+ "data": [
1239
+ {
1240
+ "checksum": 2582164875,
1241
+ "data": "{"id":"a","description":"Test 1"}",
1242
+ "object_id": "a",
1243
+ "object_type": "test",
1244
+ "op": "PUT",
1245
+ "op_id": "1",
1246
+ "subkey": "e5aa2ddc-1328-58fa-a000-0b5ed31eaf1a",
1247
+ },
1248
+ ],
1249
+ "has_more": false,
1250
+ "next_after": "1",
1251
+ },
1252
+ },
1253
+ {
1254
+ "partial_checkpoint_complete": {
1255
+ "last_op_id": "2",
1256
+ "priority": 0,
1257
+ },
1258
+ },
1259
+ {
1260
+ "data": {
1261
+ "after": "0",
1262
+ "bucket": "1#todos|0["b"]",
1263
+ "data": [
1264
+ {
1265
+ "checksum": 3003552978,
1266
+ "data": "{"id":"b","description":"Test 2"}",
1267
+ "object_id": "b",
1268
+ "object_type": "test",
1269
+ "op": "PUT",
1270
+ "op_id": "2",
1271
+ "subkey": "0dfe86bd-d15b-5fd0-9c7b-a31693030ee0",
1272
+ },
1273
+ ],
1274
+ "has_more": false,
1275
+ "next_after": "2",
1276
+ },
1277
+ },
1278
+ {
1279
+ "checkpoint_complete": {
1280
+ "last_op_id": "2",
1281
+ },
1282
+ },
1283
+ ]
1284
+ `;
1285
+
1098
1286
  exports[`sync - mongodb > storage v2 > compacting data - invalidate checkpoint 1`] = `
1099
1287
  [
1100
1288
  {
@@ -2190,6 +2378,100 @@ exports[`sync - mongodb > storage v2 > sync updates to parameter query only 2`]
2190
2378
  ]
2191
2379
  `;
2192
2380
 
2381
+ exports[`sync - mongodb > storage v3 > can override priority when subscribing to stream 1`] = `
2382
+ [
2383
+ {
2384
+ "checkpoint": {
2385
+ "buckets": [
2386
+ {
2387
+ "bucket": "1#todos|0["a"]",
2388
+ "checksum": -1712802421,
2389
+ "count": 1,
2390
+ "priority": 0,
2391
+ "subscriptions": [
2392
+ {
2393
+ "sub": 0,
2394
+ },
2395
+ {
2396
+ "sub": 1,
2397
+ },
2398
+ ],
2399
+ },
2400
+ {
2401
+ "bucket": "1#todos|0["b"]",
2402
+ "checksum": -1291414318,
2403
+ "count": 1,
2404
+ "priority": 3,
2405
+ "subscriptions": [
2406
+ {
2407
+ "sub": 1,
2408
+ },
2409
+ ],
2410
+ },
2411
+ ],
2412
+ "last_op_id": "2",
2413
+ "streams": [
2414
+ {
2415
+ "errors": [],
2416
+ "is_default": false,
2417
+ "name": "todos",
2418
+ },
2419
+ ],
2420
+ "write_checkpoint": undefined,
2421
+ },
2422
+ },
2423
+ {
2424
+ "data": {
2425
+ "after": "0",
2426
+ "bucket": "1#todos|0["a"]",
2427
+ "data": [
2428
+ {
2429
+ "checksum": 2582164875,
2430
+ "data": "{"id":"a","description":"Test 1"}",
2431
+ "object_id": "a",
2432
+ "object_type": "test",
2433
+ "op": "PUT",
2434
+ "op_id": "1",
2435
+ "subkey": "e5aa2ddc-1328-58fa-a000-0b5ed31eaf1a",
2436
+ },
2437
+ ],
2438
+ "has_more": false,
2439
+ "next_after": "1",
2440
+ },
2441
+ },
2442
+ {
2443
+ "partial_checkpoint_complete": {
2444
+ "last_op_id": "2",
2445
+ "priority": 0,
2446
+ },
2447
+ },
2448
+ {
2449
+ "data": {
2450
+ "after": "0",
2451
+ "bucket": "1#todos|0["b"]",
2452
+ "data": [
2453
+ {
2454
+ "checksum": 3003552978,
2455
+ "data": "{"id":"b","description":"Test 2"}",
2456
+ "object_id": "b",
2457
+ "object_type": "test",
2458
+ "op": "PUT",
2459
+ "op_id": "2",
2460
+ "subkey": "0dfe86bd-d15b-5fd0-9c7b-a31693030ee0",
2461
+ },
2462
+ ],
2463
+ "has_more": false,
2464
+ "next_after": "2",
2465
+ },
2466
+ },
2467
+ {
2468
+ "checkpoint_complete": {
2469
+ "last_op_id": "2",
2470
+ },
2471
+ },
2472
+ ]
2473
+ `;
2474
+
2193
2475
  exports[`sync - mongodb > storage v3 > compacting data - invalidate checkpoint 1`] = `
2194
2476
  [
2195
2477
  {
@@ -1,8 +1,8 @@
1
- import { afterAll, beforeAll, describe, expect, it } from 'vitest';
2
- import { INITIALIZED_MONGO_REPORT_STORAGE_FACTORY } from './util.js';
1
+ import { MongoReportStorage } from '@module/storage/MongoReportStorage.js';
3
2
  import { register, ReportUserData } from '@powersync/service-core-tests';
4
3
  import { event_types } from '@powersync/service-types';
5
- import { MongoReportStorage } from '@module/storage/MongoReportStorage.js';
4
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
5
+ import { INITIALIZED_MONGO_REPORT_STORAGE_FACTORY } from './util.js';
6
6
 
7
7
  const userData = register.REPORT_TEST_USERS;
8
8
  const dates = register.REPORT_TEST_DATES;
package/test/src/setup.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { container } from '@powersync/lib-services-framework';
2
- import { beforeAll, beforeEach } from 'vitest';
3
2
  import { METRICS_HELPER } from '@powersync/service-core-tests';
3
+ import { beforeAll, beforeEach } from 'vitest';
4
4
 
5
5
  beforeAll(async () => {
6
6
  // Executes for every test file
@@ -1,8 +1,8 @@
1
+ import { mongoTestStorageFactoryGenerator } from '@module/utils/test-utils.js';
1
2
  import { register } from '@powersync/service-core-tests';
2
3
  import { describe } from 'vitest';
3
- import { INITIALIZED_MONGO_STORAGE_FACTORY, TEST_STORAGE_VERSIONS } from './util.js';
4
4
  import { env } from './env.js';
5
- import { mongoTestStorageFactoryGenerator } from '@module/utils/test-utils.js';
5
+ import { INITIALIZED_MONGO_STORAGE_FACTORY, TEST_STORAGE_VERSIONS } from './util.js';
6
6
 
7
7
  for (let storageVersion of TEST_STORAGE_VERSIONS) {
8
8
  describe(`Mongo Sync Bucket Storage - Parameters - v${storageVersion}`, () =>