@powersync/service-module-mongodb-storage 0.0.0-dev-20260225160713 → 0.0.0-dev-20260313100403
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.
- package/CHANGELOG.md +47 -6
- package/dist/storage/MongoBucketStorage.js +16 -3
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/MongoReportStorage.d.ts +3 -3
- package/dist/storage/MongoReportStorage.js +5 -5
- package/dist/storage/MongoReportStorage.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatch.d.ts +13 -11
- package/dist/storage/implementation/MongoBucketBatch.js +208 -127
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoChecksums.d.ts +4 -4
- package/dist/storage/implementation/MongoChecksums.js +1 -0
- package/dist/storage/implementation/MongoChecksums.js.map +1 -1
- package/dist/storage/implementation/MongoCompactor.d.ts +2 -2
- package/dist/storage/implementation/MongoCompactor.js +10 -9
- package/dist/storage/implementation/MongoCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoParameterCompactor.d.ts +2 -2
- package/dist/storage/implementation/MongoParameterCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js +2 -7
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +9 -4
- package/dist/storage/implementation/MongoSyncBucketStorage.js +35 -33
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.d.ts +3 -3
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.d.ts +4 -4
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
- package/dist/storage/implementation/OperationBatch.js +3 -2
- package/dist/storage/implementation/OperationBatch.js.map +1 -1
- package/dist/storage/implementation/PersistedBatch.d.ts +11 -4
- package/dist/storage/implementation/PersistedBatch.js +42 -11
- package/dist/storage/implementation/PersistedBatch.js.map +1 -1
- package/dist/storage/implementation/db.d.ts +35 -1
- package/dist/storage/implementation/db.js +99 -0
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +13 -1
- package/dist/storage/implementation/models.js +2 -1
- package/dist/storage/implementation/models.js.map +1 -1
- package/dist/utils/test-utils.d.ts +4 -1
- package/dist/utils/test-utils.js +15 -12
- package/dist/utils/test-utils.js.map +1 -1
- package/dist/utils/util.d.ts +2 -1
- package/dist/utils/util.js +15 -1
- package/dist/utils/util.js.map +1 -1
- package/package.json +7 -7
- package/src/storage/MongoBucketStorage.ts +29 -8
- package/src/storage/MongoReportStorage.ts +5 -5
- package/src/storage/implementation/MongoBucketBatch.ts +263 -177
- package/src/storage/implementation/MongoChecksums.ts +5 -3
- package/src/storage/implementation/MongoCompactor.ts +13 -12
- package/src/storage/implementation/MongoParameterCompactor.ts +3 -3
- package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +3 -11
- package/src/storage/implementation/MongoSyncBucketStorage.ts +33 -26
- package/src/storage/implementation/MongoSyncRulesLock.ts +3 -3
- package/src/storage/implementation/MongoWriteCheckpointAPI.ts +4 -4
- package/src/storage/implementation/OperationBatch.ts +3 -2
- package/src/storage/implementation/PersistedBatch.ts +42 -11
- package/src/storage/implementation/db.ts +129 -1
- package/src/storage/implementation/models.ts +16 -2
- package/src/utils/test-utils.ts +15 -12
- package/src/utils/util.ts +17 -2
- package/test/src/__snapshots__/{connection-report-storage.test.ts.snap → client-connections-storage.test.ts.snap} +68 -68
- package/test/src/__snapshots__/storage.test.ts.snap +201 -0
- package/test/src/__snapshots__/storage_compacting.test.ts.snap +17 -0
- package/test/src/__snapshots__/storage_sync.test.ts.snap +1111 -16
- package/test/src/{connection-report-storage.test.ts → client-connections-storage.test.ts} +1 -1
- package/test/src/storage.test.ts +9 -7
- package/test/src/storage_compacting.test.ts +54 -45
- package/test/src/storage_sync.test.ts +53 -51
- package/test/src/util.ts +3 -3
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -128,7 +128,7 @@ describe('Connection reporting storage', async () => {
|
|
|
128
128
|
await factory.deleteOldConnectionData({
|
|
129
129
|
date: dates.weekAgo
|
|
130
130
|
});
|
|
131
|
-
const connection = await factory.
|
|
131
|
+
const connection = await factory.getClientConnectionsSummary({
|
|
132
132
|
start: dates.monthAgo,
|
|
133
133
|
end: dates.now
|
|
134
134
|
});
|
package/test/src/storage.test.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { register } from '@powersync/service-core-tests';
|
|
2
2
|
import { describe } from 'vitest';
|
|
3
|
-
import { INITIALIZED_MONGO_STORAGE_FACTORY } from './util.js';
|
|
3
|
+
import { INITIALIZED_MONGO_STORAGE_FACTORY, TEST_STORAGE_VERSIONS } from './util.js';
|
|
4
4
|
import { env } from './env.js';
|
|
5
5
|
import { mongoTestStorageFactoryGenerator } from '@module/utils/test-utils.js';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
for (let storageVersion of TEST_STORAGE_VERSIONS) {
|
|
8
|
+
describe(`Mongo Sync Bucket Storage - Parameters - v${storageVersion}`, () =>
|
|
9
|
+
register.registerDataStorageParameterTests({ ...INITIALIZED_MONGO_STORAGE_FACTORY, storageVersion }));
|
|
9
10
|
|
|
10
|
-
describe(
|
|
11
|
-
|
|
11
|
+
describe(`Mongo Sync Bucket Storage - Data - v${storageVersion}`, () =>
|
|
12
|
+
register.registerDataStorageDataTests({ ...INITIALIZED_MONGO_STORAGE_FACTORY, storageVersion }));
|
|
12
13
|
|
|
13
|
-
describe(
|
|
14
|
-
|
|
14
|
+
describe(`Mongo Sync Bucket Storage - Checkpoints - v${storageVersion}`, () =>
|
|
15
|
+
register.registerDataStorageCheckpointTests({ ...INITIALIZED_MONGO_STORAGE_FACTORY, storageVersion }));
|
|
16
|
+
}
|
|
15
17
|
|
|
16
18
|
describe('Sync Bucket Validation', register.registerBucketValidationTests);
|
|
17
19
|
|
|
@@ -1,43 +1,52 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { storage, SyncRulesBucketStorage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
2
|
+
import { bucketRequest, register, test_utils } from '@powersync/service-core-tests';
|
|
2
3
|
import { describe, expect, test } from 'vitest';
|
|
3
4
|
import { INITIALIZED_MONGO_STORAGE_FACTORY } from './util.js';
|
|
4
|
-
import { storage, SyncRulesBucketStorage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
5
5
|
|
|
6
6
|
describe('Mongo Sync Bucket Storage Compact', () => {
|
|
7
7
|
register.registerCompactTests(INITIALIZED_MONGO_STORAGE_FACTORY);
|
|
8
8
|
|
|
9
9
|
describe('with blank bucket_state', () => {
|
|
10
10
|
// This can happen when migrating from older service versions, that did not populate bucket_state yet.
|
|
11
|
-
const populate = async (bucketStorage: SyncRulesBucketStorage) => {
|
|
12
|
-
await bucketStorage.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
11
|
+
const populate = async (bucketStorage: SyncRulesBucketStorage, sourceTableIndex: number) => {
|
|
12
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
13
|
+
|
|
14
|
+
const sourceTable = await test_utils.resolveTestTable(
|
|
15
|
+
writer,
|
|
16
|
+
'test',
|
|
17
|
+
['id'],
|
|
18
|
+
INITIALIZED_MONGO_STORAGE_FACTORY,
|
|
19
|
+
sourceTableIndex
|
|
20
|
+
);
|
|
21
|
+
await writer.markAllSnapshotDone('1/1');
|
|
22
|
+
|
|
23
|
+
await writer.save({
|
|
24
|
+
sourceTable,
|
|
25
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
26
|
+
after: {
|
|
27
|
+
id: 't1',
|
|
28
|
+
owner_id: 'u1'
|
|
29
|
+
},
|
|
30
|
+
afterReplicaId: test_utils.rid('t1')
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
await writer.save({
|
|
34
|
+
sourceTable,
|
|
35
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
36
|
+
after: {
|
|
37
|
+
id: 't2',
|
|
38
|
+
owner_id: 'u2'
|
|
39
|
+
},
|
|
40
|
+
afterReplicaId: test_utils.rid('t2')
|
|
34
41
|
});
|
|
35
42
|
|
|
43
|
+
await writer.commit('1/1');
|
|
44
|
+
|
|
36
45
|
return bucketStorage.getCheckpoint();
|
|
37
46
|
};
|
|
38
47
|
|
|
39
48
|
const setup = async () => {
|
|
40
|
-
await using factory = await INITIALIZED_MONGO_STORAGE_FACTORY();
|
|
49
|
+
await using factory = await INITIALIZED_MONGO_STORAGE_FACTORY.factory();
|
|
41
50
|
const syncRules = await factory.updateSyncRules(
|
|
42
51
|
updateSyncRulesFromYaml(`
|
|
43
52
|
bucket_definitions:
|
|
@@ -47,7 +56,7 @@ bucket_definitions:
|
|
|
47
56
|
`)
|
|
48
57
|
);
|
|
49
58
|
const bucketStorage = factory.getInstance(syncRules);
|
|
50
|
-
const { checkpoint } = await populate(bucketStorage);
|
|
59
|
+
const { checkpoint } = await populate(bucketStorage, 1);
|
|
51
60
|
|
|
52
61
|
return { bucketStorage, checkpoint, factory, syncRules };
|
|
53
62
|
};
|
|
@@ -68,17 +77,17 @@ bucket_definitions:
|
|
|
68
77
|
signal: null as any
|
|
69
78
|
});
|
|
70
79
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
);
|
|
75
|
-
expect(checksumAfter.get(
|
|
76
|
-
bucket:
|
|
80
|
+
const users = ['u1', 'u2'];
|
|
81
|
+
const userRequests = users.map((user) => bucketRequest(syncRules, `by_user["${user}"]`));
|
|
82
|
+
const [u1Request, u2Request] = userRequests;
|
|
83
|
+
const checksumAfter = await bucketStorage.getChecksums(checkpoint, userRequests);
|
|
84
|
+
expect(checksumAfter.get(u1Request.bucket)).toEqual({
|
|
85
|
+
bucket: u1Request.bucket,
|
|
77
86
|
checksum: -659469718,
|
|
78
87
|
count: 1
|
|
79
88
|
});
|
|
80
|
-
expect(checksumAfter.get(
|
|
81
|
-
bucket:
|
|
89
|
+
expect(checksumAfter.get(u2Request.bucket)).toEqual({
|
|
90
|
+
bucket: u2Request.bucket,
|
|
82
91
|
checksum: 430217650,
|
|
83
92
|
count: 1
|
|
84
93
|
});
|
|
@@ -88,7 +97,7 @@ bucket_definitions:
|
|
|
88
97
|
// Populate old sync rules version
|
|
89
98
|
const { factory } = await setup();
|
|
90
99
|
|
|
91
|
-
//
|
|
100
|
+
// Now populate another version (bucket definition name changed)
|
|
92
101
|
const syncRules = await factory.updateSyncRules(
|
|
93
102
|
updateSyncRulesFromYaml(`
|
|
94
103
|
bucket_definitions:
|
|
@@ -99,7 +108,7 @@ bucket_definitions:
|
|
|
99
108
|
);
|
|
100
109
|
const bucketStorage = factory.getInstance(syncRules);
|
|
101
110
|
|
|
102
|
-
await populate(bucketStorage);
|
|
111
|
+
await populate(bucketStorage, 2);
|
|
103
112
|
const { checkpoint } = await bucketStorage.getCheckpoint();
|
|
104
113
|
|
|
105
114
|
// Default is to small small numbers - should be a no-op
|
|
@@ -122,17 +131,17 @@ bucket_definitions:
|
|
|
122
131
|
});
|
|
123
132
|
expect(result2.buckets).toEqual(0);
|
|
124
133
|
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
);
|
|
129
|
-
expect(checksumAfter.get(
|
|
130
|
-
bucket:
|
|
134
|
+
const users = ['u1', 'u2'];
|
|
135
|
+
const userRequests = users.map((user) => bucketRequest(syncRules, `by_user2["${user}"]`));
|
|
136
|
+
const [u1Request, u2Request] = userRequests;
|
|
137
|
+
const checksumAfter = await bucketStorage.getChecksums(checkpoint, userRequests);
|
|
138
|
+
expect(checksumAfter.get(u1Request.bucket)).toEqual({
|
|
139
|
+
bucket: u1Request.bucket,
|
|
131
140
|
checksum: -659469718,
|
|
132
141
|
count: 1
|
|
133
142
|
});
|
|
134
|
-
expect(checksumAfter.get(
|
|
135
|
-
bucket:
|
|
143
|
+
expect(checksumAfter.get(u2Request.bucket)).toEqual({
|
|
144
|
+
bucket: u2Request.bucket,
|
|
136
145
|
checksum: 430217650,
|
|
137
146
|
count: 1
|
|
138
147
|
});
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
2
|
-
import { bucketRequest, register,
|
|
2
|
+
import { bucketRequest, register, test_utils } from '@powersync/service-core-tests';
|
|
3
3
|
import { describe, expect, test } from 'vitest';
|
|
4
4
|
import { INITIALIZED_MONGO_STORAGE_FACTORY, TEST_STORAGE_VERSIONS } from './util.js';
|
|
5
5
|
|
|
6
|
-
function registerSyncStorageTests(
|
|
7
|
-
register.registerSyncTests(
|
|
8
|
-
|
|
6
|
+
function registerSyncStorageTests(storageConfig: storage.TestStorageConfig, storageVersion: number) {
|
|
7
|
+
register.registerSyncTests(storageConfig.factory, {
|
|
8
|
+
storageVersion,
|
|
9
|
+
tableIdStrings: storageConfig.tableIdStrings
|
|
10
|
+
});
|
|
9
11
|
// The split of returned results can vary depending on storage drivers
|
|
10
12
|
test('large batch (2)', async () => {
|
|
11
13
|
// Test syncing a batch of data that is small in count,
|
|
12
14
|
// but large enough in size to be split over multiple returned chunks.
|
|
13
15
|
// Similar to the above test, but splits over 1MB chunks.
|
|
14
|
-
await using factory = await
|
|
16
|
+
await using factory = await storageConfig.factory();
|
|
15
17
|
const syncRules = await factory.updateSyncRules(
|
|
16
18
|
updateSyncRulesFromYaml(
|
|
17
19
|
`
|
|
@@ -24,61 +26,61 @@ function registerSyncStorageTests(storageFactory: storage.TestStorageFactory, st
|
|
|
24
26
|
)
|
|
25
27
|
);
|
|
26
28
|
const bucketStorage = factory.getInstance(syncRules);
|
|
27
|
-
const globalBucket = bucketRequest(syncRules, 'global[]');
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
const sourceTable = TEST_TABLE;
|
|
30
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], INITIALIZED_MONGO_STORAGE_FACTORY);
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
34
|
+
const largeDescription = '0123456789'.repeat(2_000_00);
|
|
35
|
+
|
|
36
|
+
await writer.save({
|
|
37
|
+
sourceTable,
|
|
38
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
39
|
+
after: {
|
|
40
|
+
id: 'test1',
|
|
41
|
+
description: 'test1'
|
|
42
|
+
},
|
|
43
|
+
afterReplicaId: test_utils.rid('test1')
|
|
44
|
+
});
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
await writer.save({
|
|
47
|
+
sourceTable,
|
|
48
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
49
|
+
after: {
|
|
50
|
+
id: 'large1',
|
|
51
|
+
description: largeDescription
|
|
52
|
+
},
|
|
53
|
+
afterReplicaId: test_utils.rid('large1')
|
|
54
|
+
});
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
// Large enough to split the returned batch
|
|
57
|
+
await writer.save({
|
|
58
|
+
sourceTable,
|
|
59
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
60
|
+
after: {
|
|
61
|
+
id: 'large2',
|
|
62
|
+
description: largeDescription
|
|
63
|
+
},
|
|
64
|
+
afterReplicaId: test_utils.rid('large2')
|
|
65
|
+
});
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
});
|
|
67
|
+
await writer.save({
|
|
68
|
+
sourceTable,
|
|
69
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
70
|
+
after: {
|
|
71
|
+
id: 'test3',
|
|
72
|
+
description: 'test3'
|
|
73
|
+
},
|
|
74
|
+
afterReplicaId: test_utils.rid('test3')
|
|
74
75
|
});
|
|
75
76
|
|
|
76
|
-
const
|
|
77
|
+
const flushResult = await writer.flush();
|
|
77
78
|
|
|
78
|
-
const
|
|
79
|
+
const checkpoint = flushResult!.flushed_op;
|
|
79
80
|
|
|
81
|
+
const options: storage.BucketDataBatchOptions = {};
|
|
80
82
|
const batch1 = await test_utils.fromAsync(
|
|
81
|
-
bucketStorage.getBucketDataBatch(checkpoint,
|
|
83
|
+
bucketStorage.getBucketDataBatch(checkpoint, [bucketRequest(syncRules, 'global[]', 0n)], options)
|
|
82
84
|
);
|
|
83
85
|
expect(test_utils.getBatchData(batch1)).toEqual([
|
|
84
86
|
{ op_id: '1', op: 'PUT', object_id: 'test1', checksum: 2871785649 },
|
|
@@ -93,7 +95,7 @@ function registerSyncStorageTests(storageFactory: storage.TestStorageFactory, st
|
|
|
93
95
|
const batch2 = await test_utils.fromAsync(
|
|
94
96
|
bucketStorage.getBucketDataBatch(
|
|
95
97
|
checkpoint,
|
|
96
|
-
|
|
98
|
+
[bucketRequest(syncRules, 'global[]', batch1[0].chunkData.next_after)],
|
|
97
99
|
options
|
|
98
100
|
)
|
|
99
101
|
);
|
|
@@ -109,7 +111,7 @@ function registerSyncStorageTests(storageFactory: storage.TestStorageFactory, st
|
|
|
109
111
|
const batch3 = await test_utils.fromAsync(
|
|
110
112
|
bucketStorage.getBucketDataBatch(
|
|
111
113
|
checkpoint,
|
|
112
|
-
|
|
114
|
+
[bucketRequest(syncRules, 'global[]', batch2[0].chunkData.next_after)],
|
|
113
115
|
options
|
|
114
116
|
)
|
|
115
117
|
);
|
package/test/src/util.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { env } from './env.js';
|
|
2
1
|
import { mongoTestReportStorageFactoryGenerator, mongoTestStorageFactoryGenerator } from '@module/utils/test-utils.js';
|
|
3
|
-
import {
|
|
2
|
+
import { SUPPORTED_STORAGE_VERSIONS } from '@powersync/service-core';
|
|
3
|
+
import { env } from './env.js';
|
|
4
4
|
|
|
5
5
|
export const INITIALIZED_MONGO_STORAGE_FACTORY = mongoTestStorageFactoryGenerator({
|
|
6
6
|
url: env.MONGO_TEST_URL,
|
|
@@ -12,4 +12,4 @@ export const INITIALIZED_MONGO_REPORT_STORAGE_FACTORY = mongoTestReportStorageFa
|
|
|
12
12
|
isCI: env.CI
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
export const TEST_STORAGE_VERSIONS =
|
|
15
|
+
export const TEST_STORAGE_VERSIONS = SUPPORTED_STORAGE_VERSIONS;
|