@powersync/service-module-mongodb-storage 0.0.0-dev-20251015143910 → 0.0.0-dev-20251030082344

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 (73) hide show
  1. package/CHANGELOG.md +26 -12
  2. package/dist/index.d.ts +0 -1
  3. package/dist/index.js +0 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/migrations/db/migrations/1760433882550-bucket-state-index2.js +25 -0
  6. package/dist/migrations/db/migrations/1760433882550-bucket-state-index2.js.map +1 -0
  7. package/dist/storage/MongoBucketStorage.js +1 -1
  8. package/dist/storage/MongoBucketStorage.js.map +1 -1
  9. package/dist/storage/implementation/MongoBucketBatch.js +1 -1
  10. package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
  11. package/dist/storage/implementation/MongoCompactor.d.ts +13 -3
  12. package/dist/storage/implementation/MongoCompactor.js +86 -90
  13. package/dist/storage/implementation/MongoCompactor.js.map +1 -1
  14. package/dist/storage/implementation/MongoStorageProvider.d.ts +1 -1
  15. package/dist/storage/implementation/MongoStorageProvider.js +3 -7
  16. package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
  17. package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +2 -2
  18. package/dist/storage/implementation/MongoSyncBucketStorage.js +16 -5
  19. package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
  20. package/dist/storage/implementation/MongoTestStorageFactoryGenerator.d.ts +9 -0
  21. package/dist/storage/implementation/MongoTestStorageFactoryGenerator.js +20 -0
  22. package/dist/storage/implementation/MongoTestStorageFactoryGenerator.js.map +1 -0
  23. package/dist/storage/implementation/MongoWriteCheckpointAPI.js +6 -2
  24. package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
  25. package/dist/storage/implementation/PersistedBatch.js +1 -1
  26. package/dist/storage/implementation/PersistedBatch.js.map +1 -1
  27. package/dist/storage/implementation/db.d.ts +3 -4
  28. package/dist/storage/implementation/db.js +9 -14
  29. package/dist/storage/implementation/db.js.map +1 -1
  30. package/dist/storage/implementation/models.d.ts +0 -3
  31. package/dist/{utils → storage/implementation}/util.d.ts +7 -2
  32. package/dist/{utils → storage/implementation}/util.js +16 -1
  33. package/dist/storage/implementation/util.js.map +1 -0
  34. package/dist/storage/storage-index.d.ts +2 -3
  35. package/dist/storage/storage-index.js +2 -3
  36. package/dist/storage/storage-index.js.map +1 -1
  37. package/package.json +9 -9
  38. package/src/index.ts +0 -1
  39. package/src/migrations/db/migrations/{1752661449910-connection-reporting.ts → 1760433882550-bucket-state-index2.ts} +6 -30
  40. package/src/storage/MongoBucketStorage.ts +1 -1
  41. package/src/storage/implementation/MongoBucketBatch.ts +1 -1
  42. package/src/storage/implementation/MongoCompactor.ts +100 -96
  43. package/src/storage/implementation/MongoStorageProvider.ts +4 -9
  44. package/src/storage/implementation/MongoSyncBucketStorage.ts +19 -7
  45. package/src/storage/implementation/MongoTestStorageFactoryGenerator.ts +32 -0
  46. package/src/storage/implementation/MongoWriteCheckpointAPI.ts +6 -2
  47. package/src/storage/implementation/PersistedBatch.ts +1 -1
  48. package/src/storage/implementation/db.ts +12 -16
  49. package/src/storage/implementation/models.ts +0 -3
  50. package/src/{utils → storage/implementation}/util.ts +19 -3
  51. package/src/storage/storage-index.ts +2 -3
  52. package/test/src/storage.test.ts +51 -3
  53. package/test/src/storage_compacting.test.ts +17 -2
  54. package/test/src/util.ts +2 -6
  55. package/tsconfig.tsbuildinfo +1 -1
  56. package/dist/migrations/db/migrations/1752661449910-connection-reporting.js +0 -36
  57. package/dist/migrations/db/migrations/1752661449910-connection-reporting.js.map +0 -1
  58. package/dist/storage/MongoReportStorage.d.ts +0 -17
  59. package/dist/storage/MongoReportStorage.js +0 -152
  60. package/dist/storage/MongoReportStorage.js.map +0 -1
  61. package/dist/utils/test-utils.d.ts +0 -13
  62. package/dist/utils/test-utils.js +0 -40
  63. package/dist/utils/test-utils.js.map +0 -1
  64. package/dist/utils/util.js.map +0 -1
  65. package/dist/utils/utils-index.d.ts +0 -2
  66. package/dist/utils/utils-index.js +0 -3
  67. package/dist/utils/utils-index.js.map +0 -1
  68. package/src/storage/MongoReportStorage.ts +0 -174
  69. package/src/utils/test-utils.ts +0 -57
  70. package/src/utils/utils-index.ts +0 -2
  71. package/test/src/__snapshots__/connection-report-storage.test.ts.snap +0 -215
  72. package/test/src/connection-report-storage.test.ts +0 -133
  73. /package/dist/migrations/db/migrations/{1752661449910-connection-reporting.d.ts → 1760433882550-bucket-state-index2.d.ts} +0 -0
@@ -3,9 +3,11 @@ import * as crypto from 'crypto';
3
3
  import * as uuid from 'uuid';
4
4
 
5
5
  import { mongo } from '@powersync/lib-service-mongodb';
6
- import { storage, utils } from '@powersync/service-core';
6
+ import { BucketChecksum, PartialChecksum, PartialOrFullChecksum, storage, utils } from '@powersync/service-core';
7
+
8
+ import { PowerSyncMongo } from './db.js';
9
+ import { BucketDataDocument } from './models.js';
7
10
  import { ServiceAssertionError } from '@powersync/lib-services-framework';
8
- import { BucketDataDocument } from '../storage/implementation/models.js';
9
11
 
10
12
  export function idPrefixFilter<T>(prefix: Partial<T>, rest: (keyof T)[]): mongo.Condition<T> {
11
13
  let filter = {
@@ -39,7 +41,7 @@ export function generateSlotName(prefix: string, sync_rules_id: number) {
39
41
  * However, that makes `has_more` detection very difficult, since the cursor is always closed
40
42
  * after the first batch. Instead, we do a workaround to only fetch a single batch below.
41
43
  *
42
- * For this to be effective, set batchSize = limit in the find command.
44
+ * For this to be effective, set batchSize = limit + 1 in the find command.
43
45
  */
44
46
  export async function readSingleBatch<T>(cursor: mongo.AbstractCursor<T>): Promise<{ data: T[]; hasMore: boolean }> {
45
47
  try {
@@ -103,6 +105,20 @@ export function replicaIdToSubkey(table: bson.ObjectId, id: storage.ReplicaId):
103
105
  }
104
106
  }
105
107
 
108
+ /**
109
+ * Helper for unit tests
110
+ */
111
+ export const connectMongoForTests = (url: string, isCI: boolean) => {
112
+ // Short timeout for tests, to fail fast when the server is not available.
113
+ // Slightly longer timeouts for CI, to avoid arbitrary test failures
114
+ const client = new mongo.MongoClient(url, {
115
+ connectTimeoutMS: isCI ? 15_000 : 5_000,
116
+ socketTimeoutMS: isCI ? 15_000 : 5_000,
117
+ serverSelectionTimeoutMS: isCI ? 15_000 : 2_500
118
+ });
119
+ return new PowerSyncMongo(client);
120
+ };
121
+
106
122
  export function setSessionSnapshotTime(session: mongo.ClientSession, time: bson.Timestamp) {
107
123
  // This is a workaround for the lack of direct support for snapshot reads in the MongoDB driver.
108
124
  if (!session.snapshotEnabled) {
@@ -7,9 +7,8 @@ export * from './implementation/MongoPersistedSyncRulesContent.js';
7
7
  export * from './implementation/MongoStorageProvider.js';
8
8
  export * from './implementation/MongoSyncBucketStorage.js';
9
9
  export * from './implementation/MongoSyncRulesLock.js';
10
+ export * from './implementation/MongoTestStorageFactoryGenerator.js';
10
11
  export * from './implementation/OperationBatch.js';
11
12
  export * from './implementation/PersistedBatch.js';
12
- export * from '../utils/util.js';
13
+ export * from './implementation/util.js';
13
14
  export * from './MongoBucketStorage.js';
14
- export * from './MongoReportStorage.js';
15
- export * as test_utils from '../utils/test-utils.js';
@@ -2,7 +2,8 @@ import { register } from '@powersync/service-core-tests';
2
2
  import { describe } from 'vitest';
3
3
  import { INITIALIZED_MONGO_STORAGE_FACTORY } from './util.js';
4
4
  import { env } from './env.js';
5
- import { mongoTestStorageFactoryGenerator } from '@module/utils/test-utils.js';
5
+ import { MongoTestStorageFactoryGenerator } from '@module/storage/implementation/MongoTestStorageFactoryGenerator.js';
6
+ import { MongoChecksumOptions } from '@module/storage/implementation/MongoChecksums.js';
6
7
 
7
8
  describe('Mongo Sync Bucket Storage - Parameters', () =>
8
9
  register.registerDataStorageParameterTests(INITIALIZED_MONGO_STORAGE_FACTORY));
@@ -17,7 +18,7 @@ describe('Sync Bucket Validation', register.registerBucketValidationTests);
17
18
 
18
19
  describe('Mongo Sync Bucket Storage - split operations', () =>
19
20
  register.registerDataStorageDataTests(
20
- mongoTestStorageFactoryGenerator({
21
+ MongoTestStorageFactoryGenerator({
21
22
  url: env.MONGO_TEST_URL,
22
23
  isCI: env.CI,
23
24
  internalOptions: {
@@ -31,7 +32,7 @@ describe('Mongo Sync Bucket Storage - split operations', () =>
31
32
 
32
33
  describe('Mongo Sync Bucket Storage - split buckets', () =>
33
34
  register.registerDataStorageDataTests(
34
- mongoTestStorageFactoryGenerator({
35
+ MongoTestStorageFactoryGenerator({
35
36
  url: env.MONGO_TEST_URL,
36
37
  isCI: env.CI,
37
38
  internalOptions: {
@@ -42,3 +43,50 @@ describe('Mongo Sync Bucket Storage - split buckets', () =>
42
43
  }
43
44
  })
44
45
  ));
46
+
47
+ describe('Mongo Sync Bucket Storage - checksum calculations', () => {
48
+ // This test tests 4 buckets x 4 operations in each.
49
+ // We specifically use operationBatchLimit that does not have factors in common with 4,
50
+ // as well some that do.
51
+ const params: MongoChecksumOptions[] = [
52
+ {
53
+ bucketBatchLimit: 100,
54
+ operationBatchLimit: 3
55
+ },
56
+
57
+ {
58
+ bucketBatchLimit: 10,
59
+ operationBatchLimit: 7
60
+ },
61
+
62
+ {
63
+ bucketBatchLimit: 3,
64
+ operationBatchLimit: 1
65
+ },
66
+ {
67
+ bucketBatchLimit: 1,
68
+ operationBatchLimit: 3
69
+ },
70
+ {
71
+ bucketBatchLimit: 2,
72
+ operationBatchLimit: 4
73
+ },
74
+ {
75
+ bucketBatchLimit: 4,
76
+ operationBatchLimit: 12
77
+ }
78
+ ];
79
+ for (let options of params) {
80
+ describe(`${options.bucketBatchLimit}|${options.operationBatchLimit}`, () => {
81
+ register.testChecksumBatching(
82
+ MongoTestStorageFactoryGenerator({
83
+ url: env.MONGO_TEST_URL,
84
+ isCI: env.CI,
85
+ internalOptions: {
86
+ checksumOptions: options
87
+ }
88
+ })
89
+ );
90
+ });
91
+ }
92
+ });
@@ -97,10 +97,25 @@ bucket_definitions:
97
97
  await populate(bucketStorage);
98
98
  const { checkpoint } = await bucketStorage.getCheckpoint();
99
99
 
100
- await bucketStorage.populatePersistentChecksumCache({
100
+ // Default is to small small numbers - should be a no-op
101
+ const result0 = await bucketStorage.populatePersistentChecksumCache({
102
+ maxOpId: checkpoint
103
+ });
104
+ expect(result0.buckets).toEqual(0);
105
+
106
+ // This should cache the checksums for the two buckets
107
+ const result1 = await bucketStorage.populatePersistentChecksumCache({
108
+ maxOpId: checkpoint,
109
+ minBucketChanges: 1
110
+ });
111
+ expect(result1.buckets).toEqual(2);
112
+
113
+ // This should be a no-op, as the checksums are already cached
114
+ const result2 = await bucketStorage.populatePersistentChecksumCache({
101
115
  maxOpId: checkpoint,
102
- signal: new AbortController().signal
116
+ minBucketChanges: 1
103
117
  });
118
+ expect(result2.buckets).toEqual(0);
104
119
 
105
120
  const checksumAfter = await bucketStorage.getChecksums(checkpoint, ['by_user2["u1"]', 'by_user2["u2"]']);
106
121
  expect(checksumAfter.get('by_user2["u1"]')).toEqual({
package/test/src/util.ts CHANGED
@@ -1,12 +1,8 @@
1
1
  import { env } from './env.js';
2
- import { mongoTestReportStorageFactoryGenerator, mongoTestStorageFactoryGenerator } from '@module/utils/test-utils.js';
3
2
 
4
- export const INITIALIZED_MONGO_STORAGE_FACTORY = mongoTestStorageFactoryGenerator({
5
- url: env.MONGO_TEST_URL,
6
- isCI: env.CI
7
- });
3
+ import { MongoTestStorageFactoryGenerator } from '@module/storage/implementation/MongoTestStorageFactoryGenerator.js';
8
4
 
9
- export const INITIALIZED_MONGO_REPORT_STORAGE_FACTORY = mongoTestReportStorageFactoryGenerator({
5
+ export const INITIALIZED_MONGO_STORAGE_FACTORY = MongoTestStorageFactoryGenerator({
10
6
  url: env.MONGO_TEST_URL,
11
7
  isCI: env.CI
12
8
  });