@powersync/service-module-mongodb-storage 0.22.0 → 0.23.1
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 +69 -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/MongoParsedSyncConfigSet.js +8 -2
- package/dist/storage/implementation/MongoParsedSyncConfigSet.js.map +1 -1
- 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 +19 -10
- package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -1
- package/dist/storage/implementation/v3/compact-utils.d.ts +6 -3
- 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/MongoParsedSyncConfigSet.ts +19 -1
- 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 +25 -22
- package/src/storage/implementation/v3/compact-utils.ts +19 -8
- 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/source_table_config.test.ts +97 -0
- package/test/src/storage.test.ts +32 -33
- package/test/src/storage_compacting.test.ts +184 -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 +54 -47
- package/test/src/storeCurrentData.test.ts +5 -5
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
SyncRulesBucketStorage,
|
|
18
18
|
updateSyncRulesFromYaml
|
|
19
19
|
} from '@powersync/service-core';
|
|
20
|
-
import { bucketRequest, compactActive, register, test_utils } from '@powersync/service-core-tests';
|
|
20
|
+
import { bucketRequest, compactActive, getTestStorage, register, test_utils } from '@powersync/service-core-tests';
|
|
21
21
|
import * as bson from 'bson';
|
|
22
22
|
import { describe, expect, test, vi } from 'vitest';
|
|
23
23
|
import { env } from './env.js';
|
|
@@ -106,7 +106,7 @@ bucket_definitions:
|
|
|
106
106
|
{ storageVersion }
|
|
107
107
|
)
|
|
108
108
|
);
|
|
109
|
-
const bucketStorage = factory
|
|
109
|
+
const bucketStorage = await getTestStorage(factory, syncRules);
|
|
110
110
|
const syncRulesContent = syncRules.syncConfigContent[0];
|
|
111
111
|
const { checkpoint } = await populate(bucketStorage, 1);
|
|
112
112
|
|
|
@@ -164,15 +164,16 @@ bucket_definitions:
|
|
|
164
164
|
{ storageVersion }
|
|
165
165
|
)
|
|
166
166
|
);
|
|
167
|
-
const bucketStorage = factory
|
|
167
|
+
const bucketStorage = await getTestStorage(factory, syncRules);
|
|
168
168
|
const syncRulesContent = syncRules.syncConfigContent[0];
|
|
169
169
|
|
|
170
170
|
await populate(bucketStorage, 2);
|
|
171
171
|
const { checkpoint } = await bucketStorage.getCheckpoint();
|
|
172
172
|
|
|
173
|
-
// V3's initial lite pass
|
|
173
|
+
// Force V3's initial lite pass to process these small buckets for cache verification.
|
|
174
174
|
// Earlier storage versions use the default minimum-change threshold.
|
|
175
175
|
const result0 = await bucketStorage.compactInitialReplication({
|
|
176
|
+
forceChunkCompaction: true,
|
|
176
177
|
maxOpId: checkpoint
|
|
177
178
|
});
|
|
178
179
|
expect(result0.buckets).toEqual(storageVersion >= storage.STORAGE_VERSION_3 ? 2 : 0);
|
|
@@ -180,6 +181,7 @@ bucket_definitions:
|
|
|
180
181
|
// For V1/V2, lower the threshold to populate the checksum cache. V3 has
|
|
181
182
|
// already updated its compacted state, so another initial pass is a no-op.
|
|
182
183
|
const result1 = await bucketStorage.compactInitialReplication({
|
|
184
|
+
forceChunkCompaction: true,
|
|
183
185
|
maxOpId: checkpoint,
|
|
184
186
|
minBucketChanges: 1
|
|
185
187
|
});
|
|
@@ -187,6 +189,7 @@ bucket_definitions:
|
|
|
187
189
|
|
|
188
190
|
// Repeating it stays a no-op.
|
|
189
191
|
const result2 = await bucketStorage.compactInitialReplication({
|
|
192
|
+
forceChunkCompaction: true,
|
|
190
193
|
maxOpId: checkpoint,
|
|
191
194
|
minBucketChanges: 1
|
|
192
195
|
});
|
|
@@ -214,6 +217,7 @@ bucket_definitions:
|
|
|
214
217
|
.createMongoCompactor({
|
|
215
218
|
maxOpId: checkpoint,
|
|
216
219
|
compactChunksOnly: true,
|
|
220
|
+
forceChunkCompaction: true,
|
|
217
221
|
minCompactChunkIntervalMs: 1
|
|
218
222
|
})
|
|
219
223
|
.compact();
|
|
@@ -223,7 +227,10 @@ bucket_definitions:
|
|
|
223
227
|
|
|
224
228
|
test('v3 repeated initial chunk compaction reschedules overdue full work beyond the current run', async () => {
|
|
225
229
|
const { bucketStorage, checkpoint } = await setup(storage.STORAGE_VERSION_3);
|
|
226
|
-
const firstResult = await bucketStorage.compactInitialReplication({
|
|
230
|
+
const firstResult = await bucketStorage.compactInitialReplication({
|
|
231
|
+
forceChunkCompaction: true,
|
|
232
|
+
maxOpId: checkpoint
|
|
233
|
+
});
|
|
227
234
|
expect(firstResult.buckets).toBe(2);
|
|
228
235
|
|
|
229
236
|
const bucketStateCollection = (bucketStorage.db as VersionedPowerSyncMongoV3).bucketState(
|
|
@@ -243,6 +250,7 @@ bucket_definitions:
|
|
|
243
250
|
.aggregate<{ now: Date }>([{ $documents: [{}] }, { $project: { _id: 0, now: '$$NOW' } }])
|
|
244
251
|
.toArray();
|
|
245
252
|
const result = await bucketStorage.compactInitialReplication({
|
|
253
|
+
forceChunkCompaction: true,
|
|
246
254
|
maxOpId: checkpoint,
|
|
247
255
|
signal: AbortSignal.timeout(2_000)
|
|
248
256
|
});
|
|
@@ -289,7 +297,11 @@ bucket_definitions:
|
|
|
289
297
|
});
|
|
290
298
|
|
|
291
299
|
describe('Mongo Sync Parameter Storage Compact', () => {
|
|
292
|
-
|
|
300
|
+
for (const storageVersion of TEST_STORAGE_VERSIONS) {
|
|
301
|
+
describe(`storage v${storageVersion}`, () => {
|
|
302
|
+
register.registerParameterCompactTests({ ...INITIALIZED_MONGO_STORAGE_FACTORY, storageVersion });
|
|
303
|
+
});
|
|
304
|
+
}
|
|
293
305
|
});
|
|
294
306
|
|
|
295
307
|
/**
|
|
@@ -348,7 +360,7 @@ bucket_definitions:
|
|
|
348
360
|
{ storageVersion: 3 }
|
|
349
361
|
)
|
|
350
362
|
);
|
|
351
|
-
const bucketStorage = factory
|
|
363
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
352
364
|
const db = bucketStorage.db as VersionedPowerSyncMongoV3;
|
|
353
365
|
const mapping = syncRules.syncConfigContent[0].mapping;
|
|
354
366
|
const definitionId = mapping.allBucketDefinitionIds()[0];
|
|
@@ -388,6 +400,91 @@ bucket_definitions:
|
|
|
388
400
|
});
|
|
389
401
|
}
|
|
390
402
|
|
|
403
|
+
test.each([1, 7])(
|
|
404
|
+
'initial compaction bulk-reschedules buckets with %s chunks without reading data',
|
|
405
|
+
async (chunks) => {
|
|
406
|
+
const { bucketStorage, collection, bucketStateCollection, ctx, sourceTableId, db } = await setupV3Storage();
|
|
407
|
+
const documents = Array.from({ length: chunks }, (_, index) =>
|
|
408
|
+
serializeBucketData(BUCKET, [makeOp(index + 1, String(index), 'data', ctx, sourceTableId)])
|
|
409
|
+
);
|
|
410
|
+
await insertDocs(collection, documents);
|
|
411
|
+
await bucketStateCollection.insertOne({
|
|
412
|
+
_id: { d: ctx.definitionId, b: BUCKET },
|
|
413
|
+
last_op: BigInt(chunks),
|
|
414
|
+
next_compact_check: new Date(0),
|
|
415
|
+
// Even overdue full compaction must not force a small initial chunk merge.
|
|
416
|
+
first_uncompacted_write: new Date(0),
|
|
417
|
+
bucket_stats: { count: chunks, bytes: BigInt(documents.reduce((sum, doc) => sum + doc.size, 0)), chunks }
|
|
418
|
+
});
|
|
419
|
+
const claim = vi.spyOn(CompactionLease, 'claim');
|
|
420
|
+
const data = vi.spyOn(db, 'bucketData');
|
|
421
|
+
try {
|
|
422
|
+
expect(await bucketStorage.compactInitialReplication({ maxOpId: BigInt(chunks) })).toEqual({ buckets: 0 });
|
|
423
|
+
expect(claim).not.toHaveBeenCalled();
|
|
424
|
+
expect(data).not.toHaveBeenCalled();
|
|
425
|
+
const state = await bucketStateCollection.findOne({ _id: { d: ctx.definitionId, b: BUCKET } });
|
|
426
|
+
expect(state?.compacted_state).toBeUndefined();
|
|
427
|
+
expect(state?.compact_lease).toBeUndefined();
|
|
428
|
+
expect(state?.last_full_compact).toBeUndefined();
|
|
429
|
+
expect(state!.next_compact_check!.getTime()).toBeGreaterThan(Date.now());
|
|
430
|
+
expect(await collection.find().toArray()).toEqual(documents);
|
|
431
|
+
} finally {
|
|
432
|
+
claim.mockRestore();
|
|
433
|
+
data.mockRestore();
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
test('initial compaction rechecks the chunk threshold after claiming', async () => {
|
|
439
|
+
const { bucketStorage, collection, bucketStateCollection, ctx, sourceTableId, db } = await setupV3Storage();
|
|
440
|
+
const documents = Array.from({ length: 8 }, (_, index) =>
|
|
441
|
+
serializeBucketData(BUCKET, [makeOp(index + 1, String(index), 'data', ctx, sourceTableId)])
|
|
442
|
+
);
|
|
443
|
+
await insertDocs(collection, documents);
|
|
444
|
+
const bytes = BigInt(documents.reduce((sum, doc) => sum + doc.size, 0));
|
|
445
|
+
await bucketStateCollection.insertOne({
|
|
446
|
+
_id: { d: ctx.definitionId, b: BUCKET },
|
|
447
|
+
last_op: 8n,
|
|
448
|
+
next_compact_check: new Date(0),
|
|
449
|
+
first_uncompacted_write: new Date(),
|
|
450
|
+
bucket_stats: { count: 8, bytes, chunks: 8 }
|
|
451
|
+
});
|
|
452
|
+
const originalClaim = CompactionLease.claim.bind(CompactionLease);
|
|
453
|
+
const claim = vi.spyOn(CompactionLease, 'claim').mockImplementationOnce(async (...args) => {
|
|
454
|
+
// Another compactor finishes before we acquire the lease, leaving one
|
|
455
|
+
// new chunk beyond its cached prefix instead of the eight we selected.
|
|
456
|
+
await bucketStateCollection.updateOne(
|
|
457
|
+
{ _id: { d: ctx.definitionId, b: BUCKET } },
|
|
458
|
+
{
|
|
459
|
+
$set: {
|
|
460
|
+
compacted_state: {
|
|
461
|
+
op_id: 7n,
|
|
462
|
+
checksum: 196n,
|
|
463
|
+
count: 7,
|
|
464
|
+
bytes: bytes - BigInt(documents[7].size),
|
|
465
|
+
chunks: 7,
|
|
466
|
+
at: new Date()
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
);
|
|
471
|
+
return originalClaim(...args);
|
|
472
|
+
});
|
|
473
|
+
const data = vi.spyOn(db, 'bucketData');
|
|
474
|
+
try {
|
|
475
|
+
expect(await bucketStorage.compactInitialReplication({ maxOpId: 8n })).toEqual({ buckets: 0 });
|
|
476
|
+
expect(claim).toHaveBeenCalledTimes(1);
|
|
477
|
+
expect(data).not.toHaveBeenCalled();
|
|
478
|
+
const state = await bucketStateCollection.findOne({ _id: { d: ctx.definitionId, b: BUCKET } });
|
|
479
|
+
expect(state?.compacted_state?.op_id).toBe(7n);
|
|
480
|
+
expect(state?.compact_lease).toBeUndefined();
|
|
481
|
+
expect(state!.next_compact_check!.getTime()).toBeGreaterThan(Date.now());
|
|
482
|
+
} finally {
|
|
483
|
+
claim.mockRestore();
|
|
484
|
+
data.mockRestore();
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
|
|
391
488
|
test('a successful lease renewal clears a transient renewal error', async () => {
|
|
392
489
|
const { bucketStateCollection, ctx } = await setupV3Storage();
|
|
393
490
|
await insertBucketState(bucketStateCollection, ctx.definitionId, 1n);
|
|
@@ -449,7 +546,7 @@ bucket_definitions:
|
|
|
449
546
|
);
|
|
450
547
|
|
|
451
548
|
await (bucketStorage as MongoSyncBucketStorage)
|
|
452
|
-
.createMongoCompactor({ maxOpId: 2n, compactChunksOnly: true })
|
|
549
|
+
.createMongoCompactor({ maxOpId: 2n, compactChunksOnly: true, forceChunkCompaction: true })
|
|
453
550
|
.compact();
|
|
454
551
|
|
|
455
552
|
const [badState, goodState] = await Promise.all([
|
|
@@ -493,6 +590,7 @@ bucket_definitions:
|
|
|
493
590
|
.createMongoCompactor({
|
|
494
591
|
maxOpId: 2n,
|
|
495
592
|
compactChunksOnly: true,
|
|
593
|
+
forceChunkCompaction: true,
|
|
496
594
|
signal: abortController.signal,
|
|
497
595
|
logger: testLogger
|
|
498
596
|
})
|
|
@@ -896,7 +994,7 @@ bucket_definitions:
|
|
|
896
994
|
{ storageVersion: 3 }
|
|
897
995
|
)
|
|
898
996
|
);
|
|
899
|
-
const bucketStorage = factory
|
|
997
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
900
998
|
const db = bucketStorage.db as VersionedPowerSyncMongoV3;
|
|
901
999
|
const mapping = syncRules.syncConfigContent[0].mapping;
|
|
902
1000
|
const definitionId = mapping.allBucketDefinitionIds()[0];
|
|
@@ -1073,7 +1171,7 @@ bucket_definitions:
|
|
|
1073
1171
|
{ storageVersion: 3 }
|
|
1074
1172
|
)
|
|
1075
1173
|
);
|
|
1076
|
-
const bucketStorage = factory
|
|
1174
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
1077
1175
|
const db = bucketStorage.db as VersionedPowerSyncMongoV3;
|
|
1078
1176
|
const mapping = syncRules.syncConfigContent[0].mapping;
|
|
1079
1177
|
const definitionId = mapping.allBucketDefinitionIds()[0];
|
|
@@ -1466,7 +1564,7 @@ bucket_definitions:
|
|
|
1466
1564
|
{ storageVersion: 3 }
|
|
1467
1565
|
)
|
|
1468
1566
|
);
|
|
1469
|
-
const bucketStorage = factory
|
|
1567
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
1470
1568
|
const db = bucketStorage.db as VersionedPowerSyncMongoV3;
|
|
1471
1569
|
const mapping = syncRules.syncConfigContent[0].mapping;
|
|
1472
1570
|
const definitionId = mapping.allBucketDefinitionIds()[0];
|
|
@@ -1655,7 +1753,7 @@ bucket_definitions:
|
|
|
1655
1753
|
{ storageVersion: 3 }
|
|
1656
1754
|
)
|
|
1657
1755
|
);
|
|
1658
|
-
const bucketStorage = factory
|
|
1756
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
1659
1757
|
const db = bucketStorage.db as VersionedPowerSyncMongoV3;
|
|
1660
1758
|
const definitionId = bucketStorage.storageIds.bucketDefinitionIds[0];
|
|
1661
1759
|
const collection = db.bucketData(bucketStorage.replicationStreamId, definitionId);
|
|
@@ -1752,6 +1850,29 @@ bucket_definitions:
|
|
|
1752
1850
|
expect(state?.bucket_stats).toEqual({ count: 4, bytes, chunks: documents.length });
|
|
1753
1851
|
}
|
|
1754
1852
|
|
|
1853
|
+
test('initial compaction merges eight chunks immediately without full compaction', async () => {
|
|
1854
|
+
const { bucketStorage, collection, bucketStateCollection, ctx, sourceTableId } = await setupV3();
|
|
1855
|
+
const inputs = Array.from({ length: 8 }, (_, index) =>
|
|
1856
|
+
serializeBucketData(BUCKET, [makeOp(index + 1, 'A', 'data', ctx, sourceTableId)])
|
|
1857
|
+
);
|
|
1858
|
+
await insertDocs(collection, inputs);
|
|
1859
|
+
await bucketStateCollection.insertOne({
|
|
1860
|
+
_id: { d: ctx.definitionId, b: BUCKET },
|
|
1861
|
+
last_op: 8n,
|
|
1862
|
+
next_compact_check: new Date(),
|
|
1863
|
+
first_uncompacted_write: new Date(0),
|
|
1864
|
+
bucket_stats: { count: 8, bytes: BigInt(inputs.reduce((sum, doc) => sum + doc.size, 0)), chunks: 8 }
|
|
1865
|
+
});
|
|
1866
|
+
|
|
1867
|
+
expect(await bucketStorage.compactInitialReplication({ maxOpId: 8n })).toEqual({ buckets: 1 });
|
|
1868
|
+
const documents = await collection.find({ '_id.b': BUCKET }).toArray();
|
|
1869
|
+
expect(documents).toHaveLength(1);
|
|
1870
|
+
expect(documents[0].ops!.map((op) => op.o)).toEqual([1n, 2n, 3n, 4n, 5n, 6n, 7n, 8n]);
|
|
1871
|
+
const state = await bucketStateCollection.findOne({ _id: { d: ctx.definitionId, b: BUCKET } });
|
|
1872
|
+
expect(state?.compacted_state).toMatchObject({ op_id: 8n, count: 8, checksum: 252n });
|
|
1873
|
+
expect(state?.last_full_compact).toBeUndefined();
|
|
1874
|
+
});
|
|
1875
|
+
|
|
1755
1876
|
test('initial compaction merges small chunks and refreshes bucket metadata', async () => {
|
|
1756
1877
|
const { bucketStorage, collection, bucketStateCollection, ctx, sourceTableId } = await setupV3();
|
|
1757
1878
|
await insertDocs(collection, [
|
|
@@ -1760,7 +1881,7 @@ bucket_definitions:
|
|
|
1760
1881
|
]);
|
|
1761
1882
|
await insertBucketState(bucketStateCollection, ctx.definitionId, 4n);
|
|
1762
1883
|
|
|
1763
|
-
const result = await bucketStorage.compactInitialReplication({ maxOpId: 4n });
|
|
1884
|
+
const result = await bucketStorage.compactInitialReplication({ forceChunkCompaction: true, maxOpId: 4n });
|
|
1764
1885
|
|
|
1765
1886
|
expect(result).toEqual({ buckets: 1 });
|
|
1766
1887
|
const documents = await collection.find({ '_id.b': BUCKET }).sort({ '_id.o': 1 }).toArray();
|
|
@@ -1827,7 +1948,7 @@ bucket_definitions:
|
|
|
1827
1948
|
Array.from({ length: 2 }, () =>
|
|
1828
1949
|
bucketStorage.factory
|
|
1829
1950
|
.getInstance(syncRules)
|
|
1830
|
-
.compactInitialReplication({ maxOpId: 2n, signal: controller.signal })
|
|
1951
|
+
.compactInitialReplication({ forceChunkCompaction: true, maxOpId: 2n, signal: controller.signal })
|
|
1831
1952
|
)
|
|
1832
1953
|
).finally(() => {
|
|
1833
1954
|
settled = true;
|
|
@@ -1858,7 +1979,9 @@ bucket_definitions:
|
|
|
1858
1979
|
expect(results.every((result) => result.status === 'rejected')).toBe(true);
|
|
1859
1980
|
expect(await bucketStateCollection.countDocuments({ compact_lease: { $exists: true } })).toBe(0);
|
|
1860
1981
|
// Cancellation must return all worker slots.
|
|
1861
|
-
expect(await bucketStorage.compactInitialReplication({ maxOpId: 2n })).toEqual({
|
|
1982
|
+
expect(await bucketStorage.compactInitialReplication({ forceChunkCompaction: true, maxOpId: 2n })).toEqual({
|
|
1983
|
+
buckets: bucketCount
|
|
1984
|
+
});
|
|
1862
1985
|
} else {
|
|
1863
1986
|
expect(results.every((result) => result.status === 'fulfilled')).toBe(true);
|
|
1864
1987
|
expect(results.reduce((sum, result) => sum + (result.status === 'fulfilled' ? result.value.buckets : 0), 0)).toBe(
|
|
@@ -2048,7 +2171,7 @@ bucket_definitions:
|
|
|
2048
2171
|
}
|
|
2049
2172
|
});
|
|
2050
2173
|
|
|
2051
|
-
const result = await bucketStorage.compactInitialReplication({ maxOpId: 4n });
|
|
2174
|
+
const result = await bucketStorage.compactInitialReplication({ forceChunkCompaction: true, maxOpId: 4n });
|
|
2052
2175
|
|
|
2053
2176
|
expect(result).toEqual({ buckets: 1 });
|
|
2054
2177
|
const expectedStats = {
|
|
@@ -2167,9 +2290,9 @@ bucket_definitions:
|
|
|
2167
2290
|
bucket_stats: { count: 4, bytes: 200n, chunks: 4 }
|
|
2168
2291
|
});
|
|
2169
2292
|
|
|
2170
|
-
await expect(
|
|
2171
|
-
|
|
2172
|
-
);
|
|
2293
|
+
await expect(
|
|
2294
|
+
bucketStorage.createMongoCompactor({ maxOpId: 4n, compactChunksOnly: true, forceChunkCompaction: true }).compact()
|
|
2295
|
+
).resolves.toBe(1);
|
|
2173
2296
|
|
|
2174
2297
|
const currentDocuments = await collection.find({ '_id.b': BUCKET }).sort({ '_id.o': 1 }).toArray();
|
|
2175
2298
|
expect(currentDocuments.flatMap((document) => document.ops!.map((op) => op.o))).toEqual([1n, 3n, 4n]);
|
|
@@ -2189,7 +2312,8 @@ bucket_definitions:
|
|
|
2189
2312
|
const { bucketStorage, collection, bucketStateCollection, ctx } = await setupCompactedTail();
|
|
2190
2313
|
const failedCompactor = bucketStorage.createMongoCompactor({
|
|
2191
2314
|
maxOpId: 4n,
|
|
2192
|
-
compactChunksOnly: true
|
|
2315
|
+
compactChunksOnly: true,
|
|
2316
|
+
forceChunkCompaction: true
|
|
2193
2317
|
});
|
|
2194
2318
|
const originalFlush = (failedCompactor as any).flushCompactionGroup.bind(failedCompactor);
|
|
2195
2319
|
const flushSpy = vi
|
|
@@ -2210,7 +2334,9 @@ bucket_definitions:
|
|
|
2210
2334
|
{ $set: { next_compact_check: new Date(0) } }
|
|
2211
2335
|
);
|
|
2212
2336
|
|
|
2213
|
-
const result = await bucketStorage
|
|
2337
|
+
const result = await bucketStorage
|
|
2338
|
+
.createMongoCompactor({ maxOpId: 4n, compactChunksOnly: true, forceChunkCompaction: true })
|
|
2339
|
+
.compact();
|
|
2214
2340
|
|
|
2215
2341
|
expect(result).toBe(1);
|
|
2216
2342
|
await expectRecoveredCompactedTail(collection, bucketStateCollection, ctx.definitionId);
|
|
@@ -2489,6 +2615,43 @@ bucket_definitions:
|
|
|
2489
2615
|
});
|
|
2490
2616
|
});
|
|
2491
2617
|
|
|
2618
|
+
test('full compaction releases superseded input payloads across read batches', async () => {
|
|
2619
|
+
const { bucketStorage, collection, bucketStateCollection, ctx, sourceTableId } = await setupV3();
|
|
2620
|
+
const documents = Array.from({ length: 6 }, (_, index) =>
|
|
2621
|
+
serializeBucketData(BUCKET, [makeOp(index + 1, 'A', 'x'.repeat(256 * 1024), ctx, sourceTableId)])
|
|
2622
|
+
);
|
|
2623
|
+
const latest = makeOp(7, 'A', 'latest', ctx, sourceTableId);
|
|
2624
|
+
documents.push(serializeBucketData(BUCKET, [latest]));
|
|
2625
|
+
await insertDocs(collection, documents);
|
|
2626
|
+
await insertBucketState(bucketStateCollection, ctx.definitionId, 7n);
|
|
2627
|
+
|
|
2628
|
+
const compactor = bucketStorage.createMongoCompactor({
|
|
2629
|
+
compactBuckets: [BUCKET],
|
|
2630
|
+
maxOpId: 7n,
|
|
2631
|
+
moveBatchQueryLimit: 2
|
|
2632
|
+
});
|
|
2633
|
+
const originalFlush = (compactor as any).flushCompactionGroup.bind(compactor);
|
|
2634
|
+
const flushSpy = vi.spyOn(compactor as any, 'flushCompactionGroup').mockImplementation(async (...args: any[]) => {
|
|
2635
|
+
const group = args[1];
|
|
2636
|
+
// All seven inputs merge into one small output across four read batches.
|
|
2637
|
+
// Keeping their original ops here would retain every superseded payload.
|
|
2638
|
+
expect(group.inputs).toHaveLength(7);
|
|
2639
|
+
expect(group.inputs.every((input: BucketDataDocumentV3) => input.ops == null)).toBe(true);
|
|
2640
|
+
expect(group.ops.filter((op: BucketDataDoc) => op.op === 'MOVE')).toHaveLength(6);
|
|
2641
|
+
return originalFlush(...args);
|
|
2642
|
+
});
|
|
2643
|
+
|
|
2644
|
+
await expect(compactor.compact()).resolves.toBe(1);
|
|
2645
|
+
expect(flushSpy).toHaveBeenCalledOnce();
|
|
2646
|
+
const compacted = await collection.find({ '_id.b': BUCKET }).toArray();
|
|
2647
|
+
const ops = compacted.flatMap((document) => document.ops!);
|
|
2648
|
+
expect(ops.map((op) => op.op)).toEqual(['CLEAR', 'PUT']);
|
|
2649
|
+
expect(ops[1]).toMatchObject({ o: latest.o, data: latest.data });
|
|
2650
|
+
expect(compacted.reduce((sum, document) => sum + document.checksum, 0n)).toBe(
|
|
2651
|
+
documents.reduce((sum, document) => sum + document.checksum, 0n)
|
|
2652
|
+
);
|
|
2653
|
+
});
|
|
2654
|
+
|
|
2492
2655
|
test('7. cross-batch seen map overflow - dedup continues across batches', async () => {
|
|
2493
2656
|
const { bucketStorage, collection, bucketStateCollection, ctx, sourceTableId } = await setupV3();
|
|
2494
2657
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mongoTestStorageFactoryGenerator } from '@module/utils/test-utils.js';
|
|
2
2
|
import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
3
|
-
import { bucketRequest, test_utils } from '@powersync/service-core-tests';
|
|
3
|
+
import { bucketRequest, getTestStorage, test_utils } from '@powersync/service-core-tests';
|
|
4
4
|
import { describe, expect, test } from 'vitest';
|
|
5
5
|
import { DEFAULT_INLINE_THRESHOLD_BYTES } from '../../src/storage/implementation/common/PersistedBatch.js';
|
|
6
6
|
import { MongoSyncBucketStorage } from '../../src/storage/implementation/createMongoSyncBucketStorage.js';
|
|
@@ -31,7 +31,7 @@ describe('Object storage inline threshold', () => {
|
|
|
31
31
|
const { memoryStorage, factoryGen } = s3Factory();
|
|
32
32
|
await using factory = await factoryGen.factory();
|
|
33
33
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
34
|
-
const bucketStorage = factory
|
|
34
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
35
35
|
expect(bucketStorage.inlineThresholdBytes).toBe(DEFAULT_INLINE_THRESHOLD_BYTES);
|
|
36
36
|
|
|
37
37
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -77,7 +77,7 @@ describe('Object storage inline threshold', () => {
|
|
|
77
77
|
const { memoryStorage, factoryGen } = s3Factory(256);
|
|
78
78
|
await using factory = await factoryGen.factory();
|
|
79
79
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
80
|
-
const bucketStorage = factory
|
|
80
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
81
81
|
expect(bucketStorage.inlineThresholdBytes).toBe(256);
|
|
82
82
|
|
|
83
83
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
storage,
|
|
5
5
|
updateSyncRulesFromYaml
|
|
6
6
|
} from '@powersync/service-core';
|
|
7
|
-
import { bucketRequest, compactActive, test_utils } from '@powersync/service-core-tests';
|
|
7
|
+
import { bucketRequest, compactActive, getTestStorage, test_utils } from '@powersync/service-core-tests';
|
|
8
8
|
import { describe, expect, test } from 'vitest';
|
|
9
9
|
import { MongoSyncBucketStorage } from '../../src/storage/implementation/createMongoSyncBucketStorage.js';
|
|
10
10
|
import { VersionedPowerSyncMongoV3 } from '../../src/storage/implementation/v3/VersionedPowerSyncMongoV3.js';
|
|
@@ -28,7 +28,7 @@ describe('V3 checksums with S3 object storage', () => {
|
|
|
28
28
|
const { factoryGen } = s3Factory();
|
|
29
29
|
await using factory = await factoryGen.factory();
|
|
30
30
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
31
|
-
const bucketStorage = factory
|
|
31
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
32
32
|
const db = bucketStorage.db as VersionedPowerSyncMongoV3;
|
|
33
33
|
|
|
34
34
|
const request = bucketRequest(syncRules.syncConfigContent[0], 'global[]', 0n);
|
|
@@ -75,7 +75,7 @@ describe('V3 checksums with S3 object storage', () => {
|
|
|
75
75
|
const { factoryGen } = s3Factory();
|
|
76
76
|
await using factory = await factoryGen.factory();
|
|
77
77
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
78
|
-
const bucketStorage = factory
|
|
78
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
79
79
|
const db = bucketStorage.db as VersionedPowerSyncMongoV3;
|
|
80
80
|
|
|
81
81
|
const request = bucketRequest(syncRules.syncConfigContent[0], 'global[]', 0n);
|
|
@@ -114,7 +114,7 @@ describe('V3 checksums with S3 object storage', () => {
|
|
|
114
114
|
const { factoryGen } = s3Factory();
|
|
115
115
|
await using factory = await factoryGen.factory();
|
|
116
116
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
117
|
-
const bucketStorage = factory
|
|
117
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
118
118
|
const db = bucketStorage.db as VersionedPowerSyncMongoV3;
|
|
119
119
|
|
|
120
120
|
const request = bucketRequest(syncRules.syncConfigContent[0], 'global[]', 0n);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as lib_mongo from '@powersync/lib-service-mongodb';
|
|
2
2
|
import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
3
|
-
import { bucketRequest, compactActive, test_utils } from '@powersync/service-core-tests';
|
|
3
|
+
import { bucketRequest, compactActive, getTestStorage, test_utils } from '@powersync/service-core-tests';
|
|
4
4
|
import { describe, expect, test } from 'vitest';
|
|
5
5
|
import { MongoSyncBucketStorage } from '../../src/storage/implementation/createMongoSyncBucketStorage.js';
|
|
6
6
|
import { MongoSyncBucketStorageV3 } from '../../src/storage/implementation/v3/MongoSyncBucketStorageV3.js';
|
|
@@ -57,7 +57,7 @@ describe('S3 compaction storage lifecycle', () => {
|
|
|
57
57
|
const { memoryStorage, factory: factoryGen } = memoryS3Factory();
|
|
58
58
|
await using factory = await factoryGen.factory();
|
|
59
59
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
60
|
-
const bucketStorage = factory
|
|
60
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
61
61
|
|
|
62
62
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
63
63
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 1);
|
|
@@ -106,7 +106,7 @@ describe('S3 compaction storage lifecycle', () => {
|
|
|
106
106
|
const { memoryStorage, factory: factoryGen } = memoryS3Factory({ inlineThresholdBytes: 10_000 });
|
|
107
107
|
await using factory = await factoryGen.factory();
|
|
108
108
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
109
|
-
const bucketStorage = factory
|
|
109
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
110
110
|
|
|
111
111
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
112
112
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 10);
|
|
@@ -152,7 +152,7 @@ describe('S3 compaction storage lifecycle', () => {
|
|
|
152
152
|
const { factory: factoryGen } = memoryS3Factory();
|
|
153
153
|
await using factory = await factoryGen.factory();
|
|
154
154
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
155
|
-
const bucketStorage = factory
|
|
155
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
156
156
|
|
|
157
157
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
158
158
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 11);
|
|
@@ -187,7 +187,7 @@ describe('S3 compaction storage lifecycle', () => {
|
|
|
187
187
|
const { factory: factoryGen } = memoryS3Factory();
|
|
188
188
|
await using factory = await factoryGen.factory();
|
|
189
189
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
190
|
-
const bucketStorage = factory
|
|
190
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
191
191
|
|
|
192
192
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
193
193
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 12);
|
|
@@ -248,7 +248,7 @@ describe('S3 compaction storage lifecycle', () => {
|
|
|
248
248
|
const { memoryStorage, factory: factoryGen } = memoryS3Factory();
|
|
249
249
|
await using factory = await factoryGen.factory();
|
|
250
250
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
251
|
-
const bucketStorage = factory
|
|
251
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
252
252
|
|
|
253
253
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
254
254
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 1);
|
|
@@ -323,7 +323,7 @@ describe('S3 compaction storage lifecycle', () => {
|
|
|
323
323
|
const { memoryStorage, factory: factoryGen } = memoryS3Factory();
|
|
324
324
|
await using factory = await factoryGen.factory();
|
|
325
325
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
326
|
-
const bucketStorage = factory
|
|
326
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
327
327
|
|
|
328
328
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
329
329
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 1);
|
|
@@ -396,7 +396,7 @@ describe('S3 compaction storage lifecycle', () => {
|
|
|
396
396
|
const { memoryStorage, factory: factoryGen } = memoryS3Factory();
|
|
397
397
|
await using factory = await factoryGen.factory();
|
|
398
398
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
399
|
-
const bucketStorage = factory
|
|
399
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
400
400
|
|
|
401
401
|
// Write several operations, including a repeated object id, to exercise
|
|
402
402
|
// the compaction round-trip.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DeleteObjectsCommand, ListObjectsV2Command } from '@aws-sdk/client-s3';
|
|
2
2
|
import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
3
|
-
import { bucketRequest, test_utils } from '@powersync/service-core-tests';
|
|
3
|
+
import { bucketRequest, getTestStorage, test_utils } from '@powersync/service-core-tests';
|
|
4
4
|
import * as bson from 'bson';
|
|
5
5
|
import { describe, expect, test, vi } from 'vitest';
|
|
6
6
|
import { MongoSyncBucketStorage } from '../../src/storage/implementation/createMongoSyncBucketStorage.js';
|
|
@@ -662,7 +662,7 @@ describe('S3 object storage reads', () => {
|
|
|
662
662
|
const { memoryStorage, factory: factoryGen } = memoryS3Factory();
|
|
663
663
|
await using factory = await factoryGen.factory();
|
|
664
664
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
665
|
-
const bucketStorage = factory
|
|
665
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
666
666
|
|
|
667
667
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
668
668
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 1);
|
|
@@ -710,7 +710,7 @@ describe('S3 object storage reads', () => {
|
|
|
710
710
|
const { factory: factoryGen } = s3Factory();
|
|
711
711
|
await using factory = await factoryGen.factory();
|
|
712
712
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
713
|
-
const bucketStorage = factory
|
|
713
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
714
714
|
|
|
715
715
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
716
716
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 1);
|
|
@@ -763,7 +763,7 @@ describe('S3 object storage reads', () => {
|
|
|
763
763
|
const { memoryStorage, factory: factoryGen } = memoryS3Factory({ inlineThresholdBytes: 1_000 });
|
|
764
764
|
await using factory = await factoryGen.factory();
|
|
765
765
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
766
|
-
const bucketStorage = factory
|
|
766
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
767
767
|
|
|
768
768
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
769
769
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 1);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
2
|
-
import { test_utils } from '@powersync/service-core-tests';
|
|
2
|
+
import { getTestStorage, test_utils } from '@powersync/service-core-tests';
|
|
3
3
|
import * as bson from 'bson';
|
|
4
4
|
import { describe, expect, test } from 'vitest';
|
|
5
5
|
import { MongoSyncBucketStorage } from '../../src/storage/implementation/createMongoSyncBucketStorage.js';
|
|
@@ -28,7 +28,7 @@ describe('S3 object storage writes', () => {
|
|
|
28
28
|
const { memoryStorage, factory: factoryGen } = memoryS3Factory();
|
|
29
29
|
await using factory = await factoryGen.factory();
|
|
30
30
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
31
|
-
const bucketStorage = factory
|
|
31
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
32
32
|
|
|
33
33
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
34
34
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 1);
|
|
@@ -95,7 +95,7 @@ describe('S3 object storage writes', () => {
|
|
|
95
95
|
const { memoryStorage, factory: factoryGen } = memoryS3Factory();
|
|
96
96
|
await using factory = await factoryGen.factory();
|
|
97
97
|
const syncRules = await factory.updateSyncRules(updateSyncRulesFromYaml(SYNC_RULES_YAML, { storageVersion: 3 }));
|
|
98
|
-
const bucketStorage = factory
|
|
98
|
+
const bucketStorage = (await getTestStorage(factory, syncRules)) as MongoSyncBucketStorage;
|
|
99
99
|
|
|
100
100
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
101
101
|
const sourceTable = await test_utils.resolveTestTable(writer, 'items', ['id'], factoryGen, 4);
|