@powersync/service-module-mongodb-storage 0.0.0-dev-20250618131818 → 0.0.0-dev-20250714115156

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 (28) hide show
  1. package/CHANGELOG.md +40 -5
  2. package/dist/storage/implementation/MongoBucketBatch.js +6 -6
  3. package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
  4. package/dist/storage/implementation/MongoCompactor.js +2 -2
  5. package/dist/storage/implementation/MongoCompactor.js.map +1 -1
  6. package/dist/storage/implementation/MongoStorageProvider.js +2 -0
  7. package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
  8. package/dist/storage/implementation/MongoSyncBucketStorage.js +4 -1
  9. package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
  10. package/dist/storage/implementation/PersistedBatch.js +2 -2
  11. package/dist/storage/implementation/PersistedBatch.js.map +1 -1
  12. package/dist/storage/implementation/db.js +5 -2
  13. package/dist/storage/implementation/db.js.map +1 -1
  14. package/dist/storage/implementation/models.d.ts +1 -1
  15. package/dist/storage/implementation/util.d.ts +0 -4
  16. package/dist/storage/implementation/util.js +1 -7
  17. package/dist/storage/implementation/util.js.map +1 -1
  18. package/package.json +6 -6
  19. package/src/storage/implementation/MongoBucketBatch.ts +6 -7
  20. package/src/storage/implementation/MongoCompactor.ts +2 -2
  21. package/src/storage/implementation/MongoStorageProvider.ts +2 -1
  22. package/src/storage/implementation/MongoSyncBucketStorage.ts +4 -1
  23. package/src/storage/implementation/PersistedBatch.ts +2 -2
  24. package/src/storage/implementation/db.ts +8 -2
  25. package/src/storage/implementation/models.ts +1 -1
  26. package/src/storage/implementation/util.ts +1 -8
  27. package/test/src/storage_sync.test.ts +7 -0
  28. package/tsconfig.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@powersync/service-module-mongodb-storage",
3
3
  "repository": "https://github.com/powersync-ja/powersync-service",
4
4
  "types": "dist/index.d.ts",
5
- "version": "0.0.0-dev-20250618131818",
5
+ "version": "0.0.0-dev-20250714115156",
6
6
  "main": "dist/index.js",
7
7
  "license": "FSL-1.1-Apache-2.0",
8
8
  "type": "module",
@@ -27,15 +27,15 @@
27
27
  "lru-cache": "^10.2.2",
28
28
  "ts-codec": "^1.3.0",
29
29
  "uuid": "^11.1.0",
30
- "@powersync/lib-service-mongodb": "0.0.0-dev-20250618131818",
31
- "@powersync/lib-services-framework": "0.0.0-dev-20250618131818",
32
- "@powersync/service-core": "0.0.0-dev-20250618131818",
30
+ "@powersync/lib-service-mongodb": "0.0.0-dev-20250714115156",
31
+ "@powersync/lib-services-framework": "0.7.0",
32
+ "@powersync/service-core": "0.0.0-dev-20250714115156",
33
33
  "@powersync/service-jsonbig": "0.17.10",
34
34
  "@powersync/service-sync-rules": "0.27.0",
35
- "@powersync/service-types": "0.0.0-dev-20250618131818"
35
+ "@powersync/service-types": "0.0.0-dev-20250714115156"
36
36
  },
37
37
  "devDependencies": {
38
- "@powersync/service-core-tests": "0.0.0-dev-20250618131818"
38
+ "@powersync/service-core-tests": "0.0.0-dev-20250714115156"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsc -b",
@@ -133,7 +133,7 @@ export class MongoBucketBatch
133
133
  let result: storage.FlushedResult | null = null;
134
134
  // One flush may be split over multiple transactions.
135
135
  // Each flushInner() is one transaction.
136
- while (this.batch != null) {
136
+ while (this.batch != null || this.write_checkpoint_batch.length > 0) {
137
137
  let r = await this.flushInner(options);
138
138
  if (r) {
139
139
  result = r;
@@ -144,17 +144,16 @@ export class MongoBucketBatch
144
144
 
145
145
  private async flushInner(options?: storage.BatchBucketFlushOptions): Promise<storage.FlushedResult | null> {
146
146
  const batch = this.batch;
147
- if (batch == null) {
148
- return null;
149
- }
150
-
151
147
  let last_op: InternalOpId | null = null;
152
148
  let resumeBatch: OperationBatch | null = null;
153
149
 
154
- await this.withReplicationTransaction(`Flushing ${batch.length} ops`, async (session, opSeq) => {
155
- resumeBatch = await this.replicateBatch(session, batch, opSeq, options);
150
+ await this.withReplicationTransaction(`Flushing ${batch?.length ?? 0} ops`, async (session, opSeq) => {
151
+ if (batch != null) {
152
+ resumeBatch = await this.replicateBatch(session, batch, opSeq, options);
153
+ }
156
154
 
157
155
  if (this.write_checkpoint_batch.length > 0) {
156
+ this.logger.info(`Writing ${this.write_checkpoint_batch.length} custom write checkpoints`);
158
157
  await batchCreateCustomWriteCheckpoints(this.db, session, this.write_checkpoint_batch, opSeq.next());
159
158
  this.write_checkpoint_batch = [];
160
159
  }
@@ -317,7 +317,7 @@ export class MongoCompactor {
317
317
  let numberOfOpsToClear = 0;
318
318
  for await (let op of query.stream()) {
319
319
  if (op.op == 'MOVE' || op.op == 'REMOVE' || op.op == 'CLEAR') {
320
- checksum = utils.addChecksums(checksum, op.checksum);
320
+ checksum = utils.addChecksums(checksum, Number(op.checksum));
321
321
  lastOpId = op._id;
322
322
  numberOfOpsToClear += 1;
323
323
  if (op.op != 'CLEAR') {
@@ -358,7 +358,7 @@ export class MongoCompactor {
358
358
  {
359
359
  _id: lastOpId!,
360
360
  op: 'CLEAR',
361
- checksum: checksum,
361
+ checksum: BigInt(checksum),
362
362
  data: null,
363
363
  target_op: targetOp
364
364
  },
@@ -1,6 +1,6 @@
1
1
  import * as lib_mongo from '@powersync/lib-service-mongodb';
2
2
  import { ErrorCode, logger, ServiceAssertionError, ServiceError } from '@powersync/lib-services-framework';
3
- import { storage } from '@powersync/service-core';
3
+ import { POWERSYNC_VERSION, storage } from '@powersync/service-core';
4
4
  import { MongoStorageConfig } from '../../types/types.js';
5
5
  import { MongoBucketStorage } from '../MongoBucketStorage.js';
6
6
  import { PowerSyncMongo } from './db.js';
@@ -23,6 +23,7 @@ export class MongoStorageProvider implements storage.BucketStorageProvider {
23
23
 
24
24
  const decodedConfig = MongoStorageConfig.decode(storage as any);
25
25
  const client = lib_mongo.db.createMongoClient(decodedConfig, {
26
+ powersyncVersion: POWERSYNC_VERSION,
26
27
  maxPoolSize: resolvedConfig.storage.max_pool_size ?? 8
27
28
  });
28
29
 
@@ -473,7 +473,10 @@ export class MongoSyncBucketStorage
473
473
  {
474
474
  $group: {
475
475
  _id: '$_id.b',
476
- checksum_total: { $sum: '$checksum' },
476
+ // Historically, checksum may be stored as 'int' or 'double'.
477
+ // More recently, this should be a 'long'.
478
+ // $toLong ensures that we always sum it as a long, avoiding inaccuracies in the calculations.
479
+ checksum_total: { $sum: { $toLong: '$checksum' } },
477
480
  count: { $sum: 1 },
478
481
  has_clear_op: {
479
482
  $max: {
@@ -97,7 +97,7 @@ export class PersistedBatch {
97
97
  remaining_buckets.set(key, b);
98
98
  }
99
99
 
100
- const dchecksum = utils.hashDelete(replicaIdToSubkey(options.table.id, options.sourceKey));
100
+ const dchecksum = BigInt(utils.hashDelete(replicaIdToSubkey(options.table.id, options.sourceKey)));
101
101
 
102
102
  for (const k of options.evaluated) {
103
103
  const key = currentBucketKey(k);
@@ -133,7 +133,7 @@ export class PersistedBatch {
133
133
  source_key: options.sourceKey,
134
134
  table: k.table,
135
135
  row_id: k.id,
136
- checksum: checksum,
136
+ checksum: BigInt(checksum),
137
137
  data: recordData
138
138
  }
139
139
  }
@@ -1,6 +1,6 @@
1
1
  import * as lib_mongo from '@powersync/lib-service-mongodb';
2
2
  import { mongo } from '@powersync/lib-service-mongodb';
3
- import { storage } from '@powersync/service-core';
3
+ import { POWERSYNC_VERSION, storage } from '@powersync/service-core';
4
4
 
5
5
  import { MongoStorageConfig } from '../../types/types.js';
6
6
  import {
@@ -130,5 +130,11 @@ export class PowerSyncMongo {
130
130
  }
131
131
 
132
132
  export function createPowerSyncMongo(config: MongoStorageConfig, options?: lib_mongo.MongoConnectionOptions) {
133
- return new PowerSyncMongo(lib_mongo.createMongoClient(config, options), { database: config.database });
133
+ return new PowerSyncMongo(
134
+ lib_mongo.createMongoClient(config, {
135
+ powersyncVersion: POWERSYNC_VERSION,
136
+ ...options
137
+ }),
138
+ { database: config.database }
139
+ );
134
140
  }
@@ -56,7 +56,7 @@ export interface BucketDataDocument {
56
56
  source_key?: ReplicaId;
57
57
  table?: string;
58
58
  row_id?: string;
59
- checksum: number;
59
+ checksum: bigint;
60
60
  data: string | null;
61
61
  target_op?: bigint | null;
62
62
  }
@@ -104,20 +104,13 @@ export function replicaIdToSubkey(table: bson.ObjectId, id: storage.ReplicaId):
104
104
  }
105
105
  }
106
106
 
107
- /**
108
- * Helper function for creating a MongoDB client from consumers of this package
109
- */
110
- export const createMongoClient = (url: string, options?: mongo.MongoClientOptions) => {
111
- return new mongo.MongoClient(url, options);
112
- };
113
-
114
107
  /**
115
108
  * Helper for unit tests
116
109
  */
117
110
  export const connectMongoForTests = (url: string, isCI: boolean) => {
118
111
  // Short timeout for tests, to fail fast when the server is not available.
119
112
  // Slightly longer timeouts for CI, to avoid arbitrary test failures
120
- const client = createMongoClient(url, {
113
+ const client = new mongo.MongoClient(url, {
121
114
  connectTimeoutMS: isCI ? 15_000 : 5_000,
122
115
  socketTimeoutMS: isCI ? 15_000 : 5_000,
123
116
  serverSelectionTimeoutMS: isCI ? 15_000 : 2_500
@@ -117,5 +117,12 @@ describe('sync - mongodb', () => {
117
117
  has_more: false,
118
118
  next_after: '4'
119
119
  });
120
+
121
+ // Test that the checksum type is correct.
122
+ // Specifically, test that it never persisted as double.
123
+ const checksumTypes = await factory.db.bucket_data
124
+ .aggregate([{ $group: { _id: { $type: '$checksum' }, count: { $sum: 1 } } }])
125
+ .toArray();
126
+ expect(checksumTypes).toEqual([{ _id: 'long', count: 4 }]);
120
127
  });
121
128
  });