@powersync/service-module-mongodb-storage 0.22.0 → 0.23.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.
- package/CHANGELOG.md +26 -0
- package/dist/storage/MongoBucketStorage.d.ts +5 -1
- package/dist/storage/MongoBucketStorage.js +30 -6
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatch.d.ts +23 -10
- package/dist/storage/implementation/MongoBucketBatch.js +132 -88
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoCompactor.d.ts +2 -0
- package/dist/storage/implementation/MongoCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoIdSequence.d.ts +10 -1
- package/dist/storage/implementation/MongoIdSequence.js +14 -1
- package/dist/storage/implementation/MongoIdSequence.js.map +1 -1
- package/dist/storage/implementation/MongoOpIdAllocator.d.ts +27 -0
- package/dist/storage/implementation/MongoOpIdAllocator.js +97 -0
- package/dist/storage/implementation/MongoOpIdAllocator.js.map +1 -0
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +5 -0
- package/dist/storage/implementation/MongoSyncBucketStorage.js +17 -0
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.d.ts +26 -2
- package/dist/storage/implementation/MongoSyncRulesLock.js +38 -1
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/implementation/db.js +1 -0
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +5 -0
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js +136 -133
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js.map +1 -1
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +1 -1
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js.map +1 -1
- package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +5 -1
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js +131 -148
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +4 -3
- package/dist/storage/implementation/v3/MongoCompactorV3.js +14 -10
- package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -1
- package/dist/storage/implementation/v3/compact-utils.d.ts +3 -2
- package/dist/storage/implementation/v3/compact-utils.js +12 -5
- package/dist/storage/implementation/v3/compact-utils.js.map +1 -1
- package/dist/storage/implementation/v3/models.d.ts +1 -1
- package/dist/utils/test-utils.d.ts +2 -1
- package/dist/utils/test-utils.js +4 -3
- package/dist/utils/test-utils.js.map +1 -1
- package/package.json +7 -7
- package/src/storage/MongoBucketStorage.ts +35 -7
- package/src/storage/implementation/MongoBucketBatch.ts +201 -110
- package/src/storage/implementation/MongoCompactor.ts +2 -0
- package/src/storage/implementation/MongoIdSequence.ts +21 -1
- package/src/storage/implementation/MongoOpIdAllocator.ts +105 -0
- package/src/storage/implementation/MongoSyncBucketStorage.ts +19 -0
- package/src/storage/implementation/MongoSyncRulesLock.ts +56 -3
- package/src/storage/implementation/db.ts +1 -0
- package/src/storage/implementation/models.ts +1 -0
- package/src/storage/implementation/v1/MongoBucketBatchV1.ts +150 -152
- package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +1 -1
- package/src/storage/implementation/v3/MongoBucketBatchV3.ts +167 -194
- package/src/storage/implementation/v3/MongoCompactorV3.ts +19 -22
- package/src/storage/implementation/v3/compact-utils.ts +16 -7
- package/src/storage/implementation/v3/models.ts +1 -1
- package/src/utils/test-utils.ts +5 -3
- package/test/src/__snapshots__/storage.test.ts.snap +102 -2
- package/test/src/__snapshots__/storage_compacting.test.ts.snap +2 -2
- package/test/src/__snapshots__/storage_sync.test.ts.snap +12 -12
- package/test/src/cleanup-stopped-sync-configs.test.ts +19 -13
- package/test/src/compact-utils.test.ts +33 -8
- package/test/src/concurrent_writers.test.ts +599 -0
- package/test/src/helpers/concurrentWriter.mjs +29 -0
- package/test/src/helpers/s3TestFactory.ts +12 -12
- package/test/src/object_storage_usage.test.ts +2 -1
- package/test/src/parameter_compacting_v1.test.ts +2 -2
- package/test/src/parameter_compacting_v3.test.ts +2 -2
- package/test/src/parameter_compaction_fence.test.ts +3 -3
- package/test/src/storage.test.ts +32 -33
- package/test/src/storage_compacting.test.ts +147 -21
- package/test/src/storage_object_storage_inline_threshold.test.ts +3 -3
- package/test/src/storage_s3_checksums.test.ts +4 -4
- package/test/src/storage_s3_compaction_lifecycle.test.ts +8 -8
- package/test/src/storage_s3_reading.test.ts +4 -4
- package/test/src/storage_s3_writing.test.ts +3 -3
- package/test/src/storage_sync.test.ts +52 -46
- package/test/src/storeCurrentData.test.ts +5 -5
- package/tsconfig.tsbuildinfo +1 -1
package/src/utils/test-utils.ts
CHANGED
|
@@ -7,12 +7,13 @@ import { PowerSyncMongo } from '../storage/implementation/db.js';
|
|
|
7
7
|
export type MongoTestStorageOptions = {
|
|
8
8
|
url: string;
|
|
9
9
|
isCI: boolean;
|
|
10
|
+
monitorCommands?: boolean;
|
|
10
11
|
} & Omit<MongoBucketStorageOptions, 'replicationStreamNamePrefix'>;
|
|
11
12
|
|
|
12
13
|
export function mongoTestStorageFactoryGenerator(factoryOptions: MongoTestStorageOptions) {
|
|
13
14
|
return {
|
|
14
15
|
factory: async (options?: TestStorageOptions) => {
|
|
15
|
-
const db = connectMongoForTests(factoryOptions.url, factoryOptions.isCI);
|
|
16
|
+
const db = connectMongoForTests(factoryOptions.url, factoryOptions.isCI, factoryOptions.monitorCommands);
|
|
16
17
|
|
|
17
18
|
// None of the tests insert data into this collection, so it was never created
|
|
18
19
|
if (!(await db.db.listCollections({ name: db.bucket_parameters.collectionName }).hasNext())) {
|
|
@@ -41,7 +42,7 @@ export function mongoTestStorageFactoryGenerator(factoryOptions: MongoTestStorag
|
|
|
41
42
|
|
|
42
43
|
export function mongoTestReportStorageFactoryGenerator(factoryOptions: MongoTestStorageOptions) {
|
|
43
44
|
return async (options?: TestStorageOptions) => {
|
|
44
|
-
const db = connectMongoForTests(factoryOptions.url, factoryOptions.isCI);
|
|
45
|
+
const db = connectMongoForTests(factoryOptions.url, factoryOptions.isCI, factoryOptions.monitorCommands);
|
|
45
46
|
|
|
46
47
|
await db.createConnectionReportingCollection();
|
|
47
48
|
|
|
@@ -53,10 +54,11 @@ export function mongoTestReportStorageFactoryGenerator(factoryOptions: MongoTest
|
|
|
53
54
|
};
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
export const connectMongoForTests = (url: string, isCI: boolean) => {
|
|
57
|
+
export const connectMongoForTests = (url: string, isCI: boolean, monitorCommands = false) => {
|
|
57
58
|
// Short timeout for tests, to fail fast when the server is not available.
|
|
58
59
|
// Slightly longer timeouts for CI, to avoid arbitrary test failures
|
|
59
60
|
const client = new mongo.MongoClient(url, {
|
|
61
|
+
monitorCommands,
|
|
60
62
|
connectTimeoutMS: isCI ? 15_000 : 5_000,
|
|
61
63
|
socketTimeoutMS: isCI ? 15_000 : 5_000,
|
|
62
64
|
serverSelectionTimeoutMS: isCI ? 15_000 : 2_500
|
|
@@ -100,7 +100,7 @@ exports[`Mongo Sync Bucket Storage - Data - v4 > (insert, delete, insert), (dele
|
|
|
100
100
|
]
|
|
101
101
|
`;
|
|
102
102
|
|
|
103
|
-
exports[`Mongo Sync Bucket Storage - split buckets > (insert, delete, insert), (delete) 1`] = `
|
|
103
|
+
exports[`Mongo Sync Bucket Storage - split buckets - v1 > (insert, delete, insert), (delete) 1`] = `
|
|
104
104
|
[
|
|
105
105
|
{
|
|
106
106
|
"checksum": 2871785649,
|
|
@@ -125,7 +125,107 @@ exports[`Mongo Sync Bucket Storage - split buckets > (insert, delete, insert), (
|
|
|
125
125
|
]
|
|
126
126
|
`;
|
|
127
127
|
|
|
128
|
-
exports[`Mongo Sync Bucket Storage - split
|
|
128
|
+
exports[`Mongo Sync Bucket Storage - split buckets - v2 > (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 - v4 > (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 - v1 > (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
|
+
`;
|
|
202
|
+
|
|
203
|
+
exports[`Mongo Sync Bucket Storage - split operations - v2 > (insert, delete, insert), (delete) 1`] = `
|
|
204
|
+
[
|
|
205
|
+
{
|
|
206
|
+
"checksum": 2871785649,
|
|
207
|
+
"object_id": "test1",
|
|
208
|
+
"op": "PUT",
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"checksum": 2872534815,
|
|
212
|
+
"object_id": "test1",
|
|
213
|
+
"op": "REMOVE",
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"checksum": 2871785649,
|
|
217
|
+
"object_id": "test1",
|
|
218
|
+
"op": "PUT",
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"checksum": 2872534815,
|
|
222
|
+
"object_id": "test1",
|
|
223
|
+
"op": "REMOVE",
|
|
224
|
+
},
|
|
225
|
+
]
|
|
226
|
+
`;
|
|
227
|
+
|
|
228
|
+
exports[`Mongo Sync Bucket Storage - split operations - v4 > (insert, delete, insert), (delete) 1`] = `
|
|
129
229
|
[
|
|
130
230
|
{
|
|
131
231
|
"checksum": 2871785649,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`Mongo Sync Bucket Storage Compact > partial checksums after compacting (2) 1`] = `
|
|
4
4
|
{
|
|
5
|
-
"bucket": "1
|
|
5
|
+
"bucket": "global.1.1[]",
|
|
6
6
|
"checksum": -1481659821,
|
|
7
7
|
"count": 1,
|
|
8
8
|
}
|
|
@@ -10,7 +10,7 @@ exports[`Mongo Sync Bucket Storage Compact > partial checksums after compacting
|
|
|
10
10
|
|
|
11
11
|
exports[`Mongo Sync Bucket Storage Compact > partial checksums after compacting 1`] = `
|
|
12
12
|
{
|
|
13
|
-
"bucket": "1
|
|
13
|
+
"bucket": "global.1.1[]",
|
|
14
14
|
"checksum": 1874612650,
|
|
15
15
|
"count": 4,
|
|
16
16
|
}
|
|
@@ -270,7 +270,7 @@ exports[`sync - mongodb > storage v1 > encodes sync rules id in buckets for stre
|
|
|
270
270
|
],
|
|
271
271
|
},
|
|
272
272
|
],
|
|
273
|
-
"last_op_id": "
|
|
273
|
+
"last_op_id": "65537",
|
|
274
274
|
"streams": [
|
|
275
275
|
{
|
|
276
276
|
"errors": [],
|
|
@@ -292,17 +292,17 @@ exports[`sync - mongodb > storage v1 > encodes sync rules id in buckets for stre
|
|
|
292
292
|
"object_id": "t1",
|
|
293
293
|
"object_type": "test",
|
|
294
294
|
"op": "PUT",
|
|
295
|
-
"op_id": "
|
|
295
|
+
"op_id": "65537",
|
|
296
296
|
"subkey": "bfe6a7fc-1a36-5a95-877f-518ff63ecb56",
|
|
297
297
|
},
|
|
298
298
|
],
|
|
299
299
|
"has_more": false,
|
|
300
|
-
"next_after": "
|
|
300
|
+
"next_after": "65537",
|
|
301
301
|
},
|
|
302
302
|
},
|
|
303
303
|
{
|
|
304
304
|
"checkpoint_complete": {
|
|
305
|
-
"last_op_id": "
|
|
305
|
+
"last_op_id": "65537",
|
|
306
306
|
},
|
|
307
307
|
},
|
|
308
308
|
]
|
|
@@ -1265,7 +1265,7 @@ exports[`sync - mongodb > storage v2 > encodes sync rules id in buckets for stre
|
|
|
1265
1265
|
],
|
|
1266
1266
|
},
|
|
1267
1267
|
],
|
|
1268
|
-
"last_op_id": "
|
|
1268
|
+
"last_op_id": "65537",
|
|
1269
1269
|
"streams": [
|
|
1270
1270
|
{
|
|
1271
1271
|
"errors": [],
|
|
@@ -1287,17 +1287,17 @@ exports[`sync - mongodb > storage v2 > encodes sync rules id in buckets for stre
|
|
|
1287
1287
|
"object_id": "t1",
|
|
1288
1288
|
"object_type": "test",
|
|
1289
1289
|
"op": "PUT",
|
|
1290
|
-
"op_id": "
|
|
1290
|
+
"op_id": "65537",
|
|
1291
1291
|
"subkey": "bfe6a7fc-1a36-5a95-877f-518ff63ecb56",
|
|
1292
1292
|
},
|
|
1293
1293
|
],
|
|
1294
1294
|
"has_more": false,
|
|
1295
|
-
"next_after": "
|
|
1295
|
+
"next_after": "65537",
|
|
1296
1296
|
},
|
|
1297
1297
|
},
|
|
1298
1298
|
{
|
|
1299
1299
|
"checkpoint_complete": {
|
|
1300
|
-
"last_op_id": "
|
|
1300
|
+
"last_op_id": "65537",
|
|
1301
1301
|
},
|
|
1302
1302
|
},
|
|
1303
1303
|
]
|
|
@@ -2849,7 +2849,7 @@ exports[`sync - mongodb > storage v4 > encodes sync rules id in buckets for stre
|
|
|
2849
2849
|
],
|
|
2850
2850
|
},
|
|
2851
2851
|
],
|
|
2852
|
-
"last_op_id": "
|
|
2852
|
+
"last_op_id": "65537",
|
|
2853
2853
|
"streams": [
|
|
2854
2854
|
{
|
|
2855
2855
|
"errors": [],
|
|
@@ -2871,17 +2871,17 @@ exports[`sync - mongodb > storage v4 > encodes sync rules id in buckets for stre
|
|
|
2871
2871
|
"object_id": "t1",
|
|
2872
2872
|
"object_type": "test",
|
|
2873
2873
|
"op": "PUT",
|
|
2874
|
-
"op_id": "
|
|
2874
|
+
"op_id": "65537",
|
|
2875
2875
|
"subkey": "bfe6a7fc-1a36-5a95-877f-518ff63ecb56",
|
|
2876
2876
|
},
|
|
2877
2877
|
],
|
|
2878
2878
|
"has_more": false,
|
|
2879
|
-
"next_after": "
|
|
2879
|
+
"next_after": "65537",
|
|
2880
2880
|
},
|
|
2881
2881
|
},
|
|
2882
2882
|
{
|
|
2883
2883
|
"checkpoint_complete": {
|
|
2884
|
-
"last_op_id": "
|
|
2884
|
+
"last_op_id": "65537",
|
|
2885
2885
|
},
|
|
2886
2886
|
},
|
|
2887
2887
|
]
|
|
@@ -2,7 +2,7 @@ import { MongoSyncBucketStorageV3 } from '@module/storage/implementation/v3/Mong
|
|
|
2
2
|
import { ObjectStorageLifecycle } from '@module/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js';
|
|
3
3
|
import { mongoTestStorageFactoryGenerator } from '@module/utils/test-utils.js';
|
|
4
4
|
import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
5
|
-
import { test_utils } from '@powersync/service-core-tests';
|
|
5
|
+
import { getTestStorage, test_utils } from '@powersync/service-core-tests';
|
|
6
6
|
import * as bson from 'bson';
|
|
7
7
|
import { describe, expect, test } from 'vitest';
|
|
8
8
|
import { VersionedPowerSyncMongoV3 } from '../../src/storage/implementation/v3/VersionedPowerSyncMongoV3.js';
|
|
@@ -78,7 +78,7 @@ streams:
|
|
|
78
78
|
{ storageVersion: 3 }
|
|
79
79
|
)
|
|
80
80
|
);
|
|
81
|
-
const firstStorage = factory
|
|
81
|
+
const firstStorage = (await getTestStorage(factory, first)) as MongoSyncBucketStorageV3;
|
|
82
82
|
const db = firstStorage.db as VersionedPowerSyncMongoV3;
|
|
83
83
|
await using firstWriter = await firstStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
84
84
|
|
|
@@ -155,7 +155,7 @@ streams:
|
|
|
155
155
|
);
|
|
156
156
|
expect(second.replicationStreamId).toBe(first.replicationStreamId);
|
|
157
157
|
const replicatingStreams = await factory.getReplicatingReplicationStreams();
|
|
158
|
-
const secondStorage = factory
|
|
158
|
+
const secondStorage = (await getTestStorage(factory, replicatingStreams[0])) as MongoSyncBucketStorageV3;
|
|
159
159
|
await using secondWriter = await secondStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
160
160
|
await secondWriter.markAllSnapshotDone('2/1');
|
|
161
161
|
await secondWriter.commit('2/1');
|
|
@@ -218,7 +218,7 @@ streams:
|
|
|
218
218
|
{ storageVersion: 3 }
|
|
219
219
|
)
|
|
220
220
|
);
|
|
221
|
-
const firstStorage = factory
|
|
221
|
+
const firstStorage = (await getTestStorage(factory, first)) as MongoSyncBucketStorageV3;
|
|
222
222
|
const db = firstStorage.db as VersionedPowerSyncMongoV3;
|
|
223
223
|
await using firstWriter = await firstStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
224
224
|
const resolved = await firstWriter.resolveTables({
|
|
@@ -266,7 +266,7 @@ streams:
|
|
|
266
266
|
expect(secondDefinitionId).toBe(projectDefinitionId);
|
|
267
267
|
|
|
268
268
|
const replicatingStreams = await factory.getReplicatingReplicationStreams();
|
|
269
|
-
const secondStorage = factory
|
|
269
|
+
const secondStorage = (await getTestStorage(factory, replicatingStreams[0])) as MongoSyncBucketStorageV3;
|
|
270
270
|
await using secondWriter = await secondStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
271
271
|
await secondWriter.markAllSnapshotDone('2/1');
|
|
272
272
|
await secondWriter.commit('2/1');
|
|
@@ -289,7 +289,10 @@ streams:
|
|
|
289
289
|
expect(await collectionExists(db, ownerBucketDataCollection)).toBe(false);
|
|
290
290
|
expect(await collectionExists(db, sourceRecordsCollection)).toBe(true);
|
|
291
291
|
|
|
292
|
-
const activeStorage = (await
|
|
292
|
+
const activeStorage = (await getTestStorage(
|
|
293
|
+
factory,
|
|
294
|
+
(await factory.getActiveSyncConfig())!.replicationStream
|
|
295
|
+
)) as MongoSyncBucketStorageV3;
|
|
293
296
|
await using activeWriter = await activeStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
294
297
|
const activeTable = (
|
|
295
298
|
await activeWriter.resolveTables({
|
|
@@ -343,7 +346,7 @@ event_definitions:
|
|
|
343
346
|
{ storageVersion: 3 }
|
|
344
347
|
)
|
|
345
348
|
);
|
|
346
|
-
const firstStorage = factory
|
|
349
|
+
const firstStorage = (await getTestStorage(factory, first)) as MongoSyncBucketStorageV3;
|
|
347
350
|
const db = firstStorage.db as VersionedPowerSyncMongoV3;
|
|
348
351
|
await using firstWriter = await firstStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
349
352
|
const resolved = await firstWriter.resolveTables({
|
|
@@ -402,7 +405,7 @@ event_definitions:
|
|
|
402
405
|
expect(second.replicationStreamId).toBe(first.replicationStreamId);
|
|
403
406
|
|
|
404
407
|
const replicatingStreams = await factory.getReplicatingReplicationStreams();
|
|
405
|
-
const secondStorage = factory
|
|
408
|
+
const secondStorage = (await getTestStorage(factory, replicatingStreams[0])) as MongoSyncBucketStorageV3;
|
|
406
409
|
await using secondWriter = await secondStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
407
410
|
await secondWriter.markAllSnapshotDone('2/1');
|
|
408
411
|
await secondWriter.commit('2/1');
|
|
@@ -466,7 +469,7 @@ event_definitions:
|
|
|
466
469
|
{ storageVersion: 3 }
|
|
467
470
|
)
|
|
468
471
|
);
|
|
469
|
-
const firstStorage = factory
|
|
472
|
+
const firstStorage = (await getTestStorage(factory, first)) as MongoSyncBucketStorageV3;
|
|
470
473
|
const db = firstStorage.db as VersionedPowerSyncMongoV3;
|
|
471
474
|
await using firstWriter = await firstStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
472
475
|
|
|
@@ -538,7 +541,7 @@ streams:
|
|
|
538
541
|
expect(second.replicationStreamId).toBe(first.replicationStreamId);
|
|
539
542
|
|
|
540
543
|
const replicatingStreams = await factory.getReplicatingReplicationStreams();
|
|
541
|
-
const secondStorage = factory
|
|
544
|
+
const secondStorage = (await getTestStorage(factory, replicatingStreams[0])) as MongoSyncBucketStorageV3;
|
|
542
545
|
await using secondWriter = await secondStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
543
546
|
await secondWriter.markAllSnapshotDone('2/1');
|
|
544
547
|
await secondWriter.commit('2/1');
|
|
@@ -599,7 +602,7 @@ streams:
|
|
|
599
602
|
{ storageVersion: 3 }
|
|
600
603
|
)
|
|
601
604
|
);
|
|
602
|
-
const firstStorage = factory
|
|
605
|
+
const firstStorage = (await getTestStorage(factory, first)) as MongoSyncBucketStorageV3;
|
|
603
606
|
const db = firstStorage.db as VersionedPowerSyncMongoV3;
|
|
604
607
|
await using firstWriter = await firstStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
605
608
|
const resolved = await firstWriter.resolveTables({
|
|
@@ -652,7 +655,7 @@ streams:
|
|
|
652
655
|
expect(secondIndexId).toBe(roleIndexId);
|
|
653
656
|
|
|
654
657
|
const replicatingStreams = await factory.getReplicatingReplicationStreams();
|
|
655
|
-
const secondStorage = factory
|
|
658
|
+
const secondStorage = (await getTestStorage(factory, replicatingStreams[0])) as MongoSyncBucketStorageV3;
|
|
656
659
|
await using secondWriter = await secondStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
657
660
|
await secondWriter.markAllSnapshotDone('2/1');
|
|
658
661
|
await secondWriter.commit('2/1');
|
|
@@ -664,7 +667,10 @@ streams:
|
|
|
664
667
|
expect(await collectionExists(db, orgParameterIndexCollection)).toBe(false);
|
|
665
668
|
expect(await collectionExists(db, sourceRecordsCollection)).toBe(true);
|
|
666
669
|
|
|
667
|
-
const activeStorage = (await
|
|
670
|
+
const activeStorage = (await getTestStorage(
|
|
671
|
+
factory,
|
|
672
|
+
(await factory.getActiveSyncConfig())!.replicationStream
|
|
673
|
+
)) as MongoSyncBucketStorageV3;
|
|
668
674
|
await using activeWriter = await activeStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
669
675
|
const activeTable = (
|
|
670
676
|
await activeWriter.resolveTables({
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
applyStatsReplacement,
|
|
4
4
|
bucketStats,
|
|
5
5
|
chooseCompactionKind,
|
|
6
|
+
chooseRequestedCompactionKind,
|
|
6
7
|
combineAdjacentStats,
|
|
7
8
|
combineChunkStats,
|
|
8
9
|
CompactIntervalConfig,
|
|
9
10
|
CompactionKind,
|
|
10
11
|
emptyBucketStats,
|
|
11
|
-
forcedCompactionKind,
|
|
12
12
|
fullCompactionCheckAt,
|
|
13
13
|
statsForDocument,
|
|
14
14
|
statsForDocuments
|
|
@@ -130,44 +130,69 @@ describe('V3 compact utilities', () => {
|
|
|
130
130
|
test.each([
|
|
131
131
|
{
|
|
132
132
|
name: 'does not force an unspecified kind',
|
|
133
|
-
|
|
133
|
+
requestedKind: undefined,
|
|
134
134
|
compactedOpId: undefined,
|
|
135
135
|
maxOpIdCap: undefined,
|
|
136
136
|
expected: null
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
name: 'forces work without previous compacted state',
|
|
140
|
-
|
|
140
|
+
requestedKind: CompactionKind.Chunks,
|
|
141
141
|
compactedOpId: undefined,
|
|
142
142
|
maxOpIdCap: undefined,
|
|
143
143
|
expected: CompactionKind.Chunks
|
|
144
144
|
},
|
|
145
145
|
{
|
|
146
146
|
name: 'skips work already compacted through the cap',
|
|
147
|
-
|
|
147
|
+
requestedKind: CompactionKind.Chunks,
|
|
148
148
|
compactedOpId: 5n,
|
|
149
149
|
maxOpIdCap: 5n,
|
|
150
150
|
expected: null
|
|
151
151
|
},
|
|
152
152
|
{
|
|
153
153
|
name: 'skips work already compacted through the bucket head',
|
|
154
|
-
|
|
154
|
+
requestedKind: CompactionKind.Chunks,
|
|
155
155
|
compactedOpId: 10n,
|
|
156
156
|
maxOpIdCap: undefined,
|
|
157
157
|
expected: null
|
|
158
158
|
},
|
|
159
159
|
{
|
|
160
160
|
name: 'forces work beyond the compacted state',
|
|
161
|
-
|
|
161
|
+
requestedKind: CompactionKind.Chunks,
|
|
162
162
|
compactedOpId: 5n,
|
|
163
163
|
maxOpIdCap: 6n,
|
|
164
164
|
expected: CompactionKind.Chunks
|
|
165
165
|
}
|
|
166
|
-
])('$name', ({
|
|
166
|
+
])('$name', ({ requestedKind, compactedOpId, maxOpIdCap, expected }) => {
|
|
167
167
|
const state = bucketState({
|
|
168
|
+
bucket_stats: { count: 10, bytes: 100n, chunks: 9 },
|
|
168
169
|
compacted_state: compactedOpId == null ? undefined : compactedState({ op_id: compactedOpId })
|
|
169
170
|
});
|
|
170
|
-
expect(
|
|
171
|
+
expect(chooseRequestedCompactionKind(state, requestedKind, { maxOpIdCap })).toBe(expected);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test.each([undefined, compactedState({ at: new Date() })])(
|
|
175
|
+
'initial chunk compaction requires eight new chunks, regardless of the interval: %o',
|
|
176
|
+
(compacted) => {
|
|
177
|
+
for (const newChunks of [1, 7, 8]) {
|
|
178
|
+
const state = bucketState({
|
|
179
|
+
bucket_stats: { count: 10, bytes: 100n, chunks: (compacted?.chunks ?? 0) + newChunks },
|
|
180
|
+
compacted_state: compacted
|
|
181
|
+
});
|
|
182
|
+
expect(chooseRequestedCompactionKind(state, CompactionKind.Chunks, { maxOpIdCap: undefined })).toBe(
|
|
183
|
+
newChunks < 8 ? null : CompactionKind.Chunks
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
test('the testing override bypasses the chunk threshold but preserves the compaction watermark', () => {
|
|
190
|
+
const state = bucketState();
|
|
191
|
+
const config = { maxOpIdCap: undefined, forceChunkCompaction: true };
|
|
192
|
+
expect(chooseRequestedCompactionKind(state, CompactionKind.Chunks, config)).toBe(CompactionKind.Chunks);
|
|
193
|
+
expect(chooseRequestedCompactionKind(state, undefined, config)).toBeNull();
|
|
194
|
+
state.compacted_state = compactedState({ op_id: state.last_op });
|
|
195
|
+
expect(chooseRequestedCompactionKind(state, CompactionKind.Chunks, config)).toBeNull();
|
|
171
196
|
});
|
|
172
197
|
|
|
173
198
|
test('derives and combines bucket statistics', () => {
|