@powersync/service-core-tests 0.0.0-dev-20260602073133 → 0.0.0-dev-20260803144812
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 +75 -4
- package/dist/test-utils/AbstractStreamTestContext.d.ts +7 -6
- package/dist/test-utils/AbstractStreamTestContext.js +28 -25
- package/dist/test-utils/AbstractStreamTestContext.js.map +1 -1
- package/dist/test-utils/StorageDataHelpers.d.ts +6 -5
- package/dist/test-utils/StorageDataHelpers.js +40 -2
- package/dist/test-utils/StorageDataHelpers.js.map +1 -1
- package/dist/test-utils/bucket-validation.d.ts +3 -3
- package/dist/test-utils/bucket-validation.js +3 -3
- package/dist/test-utils/general-utils.d.ts +16 -3
- package/dist/test-utils/general-utils.js +37 -4
- package/dist/test-utils/general-utils.js.map +1 -1
- package/dist/test-utils/stream_utils.d.ts +0 -1
- package/dist/test-utils/stream_utils.js +0 -10
- package/dist/test-utils/stream_utils.js.map +1 -1
- package/dist/tests/register-compacting-tests.js +28 -21
- package/dist/tests/register-compacting-tests.js.map +1 -1
- package/dist/tests/register-data-storage-checkpoint-tests.js +102 -3
- package/dist/tests/register-data-storage-checkpoint-tests.js.map +1 -1
- package/dist/tests/register-data-storage-data-tests.js +202 -136
- package/dist/tests/register-data-storage-data-tests.js.map +1 -1
- package/dist/tests/register-data-storage-parameter-tests.js +44 -42
- package/dist/tests/register-data-storage-parameter-tests.js.map +1 -1
- package/dist/tests/register-sync-tests.js +399 -82
- package/dist/tests/register-sync-tests.js.map +1 -1
- package/dist/tests/util.d.ts +2 -2
- package/dist/tests/util.js.map +1 -1
- package/package.json +5 -6
- package/src/test-utils/AbstractStreamTestContext.ts +31 -27
- package/src/test-utils/StorageDataHelpers.ts +52 -8
- package/src/test-utils/bucket-validation.ts +3 -3
- package/src/test-utils/general-utils.ts +62 -10
- package/src/test-utils/stream_utils.ts +0 -11
- package/src/tests/register-compacting-tests.ts +47 -24
- package/src/tests/register-data-storage-checkpoint-tests.ts +132 -3
- package/src/tests/register-data-storage-data-tests.ts +248 -148
- package/src/tests/register-data-storage-parameter-tests.ts +58 -42
- package/src/tests/register-sync-tests.ts +438 -84
- package/src/tests/util.ts +2 -2
- package/tsconfig.json +1 -4
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -27,13 +27,13 @@ export function registerDataStorageDataTests(config) {
|
|
|
27
27
|
const storageVersion = config.storageVersion ?? storage.CURRENT_STORAGE_VERSION;
|
|
28
28
|
test('removing row', async () => {
|
|
29
29
|
await using factory = await generateStorageFactory();
|
|
30
|
-
const syncRules = await
|
|
30
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
31
31
|
bucket_definitions:
|
|
32
32
|
global:
|
|
33
33
|
data:
|
|
34
34
|
- SELECT id, description FROM "%"
|
|
35
35
|
`, { storageVersion }));
|
|
36
|
-
const bucketStorage = factory.getInstance(
|
|
36
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
37
37
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
38
38
|
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
39
39
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -52,9 +52,9 @@ bucket_definitions:
|
|
|
52
52
|
beforeReplicaId: test_utils.rid('test1')
|
|
53
53
|
});
|
|
54
54
|
await writer.commit('1/1');
|
|
55
|
-
const
|
|
55
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
56
56
|
const request = bucketRequest(syncRules, 'global[]');
|
|
57
|
-
const batch = await test_utils.
|
|
57
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [request]));
|
|
58
58
|
const data = batch[0].chunkData.data.map((d) => {
|
|
59
59
|
return {
|
|
60
60
|
op: d.op,
|
|
@@ -79,13 +79,13 @@ bucket_definitions:
|
|
|
79
79
|
});
|
|
80
80
|
test('insert after delete in new batch', async () => {
|
|
81
81
|
await using factory = await generateStorageFactory();
|
|
82
|
-
const syncRules = await
|
|
82
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
83
83
|
bucket_definitions:
|
|
84
84
|
global:
|
|
85
85
|
data:
|
|
86
86
|
- SELECT id, description FROM "%"
|
|
87
87
|
`, { storageVersion }));
|
|
88
|
-
const bucketStorage = factory.getInstance(
|
|
88
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
89
89
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
90
90
|
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
91
91
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -105,9 +105,9 @@ bucket_definitions:
|
|
|
105
105
|
afterReplicaId: test_utils.rid('test1')
|
|
106
106
|
});
|
|
107
107
|
await writer.commit('2/1');
|
|
108
|
-
const
|
|
108
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
109
109
|
const request = bucketRequest(syncRules, 'global[]');
|
|
110
|
-
const batch = await test_utils.
|
|
110
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [request]));
|
|
111
111
|
const data = batch[0].chunkData.data.map((d) => {
|
|
112
112
|
return {
|
|
113
113
|
op: d.op,
|
|
@@ -129,13 +129,13 @@ bucket_definitions:
|
|
|
129
129
|
test('update after delete in new batch', async () => {
|
|
130
130
|
// Update after delete may not be common, but the storage layer should handle it in an eventually-consistent way.
|
|
131
131
|
await using factory = await generateStorageFactory();
|
|
132
|
-
const syncRules = await
|
|
132
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
133
133
|
bucket_definitions:
|
|
134
134
|
global:
|
|
135
135
|
data:
|
|
136
136
|
- SELECT id, description FROM "%"
|
|
137
137
|
`, { storageVersion }));
|
|
138
|
-
const bucketStorage = factory.getInstance(
|
|
138
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
139
139
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
140
140
|
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
141
141
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -159,9 +159,9 @@ bucket_definitions:
|
|
|
159
159
|
afterReplicaId: test_utils.rid('test1')
|
|
160
160
|
});
|
|
161
161
|
await writer.commit('2/1');
|
|
162
|
-
const
|
|
162
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
163
163
|
const request = bucketRequest(syncRules, 'global[]');
|
|
164
|
-
const batch = await test_utils.
|
|
164
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [request]));
|
|
165
165
|
const data = batch[0].chunkData.data.map((d) => {
|
|
166
166
|
return {
|
|
167
167
|
op: d.op,
|
|
@@ -182,7 +182,7 @@ bucket_definitions:
|
|
|
182
182
|
});
|
|
183
183
|
test('insert after delete in same batch', async () => {
|
|
184
184
|
await using factory = await generateStorageFactory();
|
|
185
|
-
const syncRules = await
|
|
185
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
186
186
|
bucket_definitions:
|
|
187
187
|
global:
|
|
188
188
|
data:
|
|
@@ -190,7 +190,7 @@ bucket_definitions:
|
|
|
190
190
|
`, {
|
|
191
191
|
storageVersion
|
|
192
192
|
}));
|
|
193
|
-
const bucketStorage = factory.getInstance(
|
|
193
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
194
194
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
195
195
|
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
196
196
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -209,9 +209,9 @@ bucket_definitions:
|
|
|
209
209
|
afterReplicaId: test_utils.rid('test1')
|
|
210
210
|
});
|
|
211
211
|
await writer.commit('1/1');
|
|
212
|
-
const
|
|
212
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
213
213
|
const request = bucketRequest(syncRules, 'global[]');
|
|
214
|
-
const batch = await test_utils.
|
|
214
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [request]));
|
|
215
215
|
const data = batch[0].chunkData.data.map((d) => {
|
|
216
216
|
return {
|
|
217
217
|
op: d.op,
|
|
@@ -232,7 +232,7 @@ bucket_definitions:
|
|
|
232
232
|
});
|
|
233
233
|
test('(insert, delete, insert), (delete)', async () => {
|
|
234
234
|
await using factory = await generateStorageFactory();
|
|
235
|
-
const syncRules = await
|
|
235
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
236
236
|
bucket_definitions:
|
|
237
237
|
global:
|
|
238
238
|
data:
|
|
@@ -240,7 +240,7 @@ bucket_definitions:
|
|
|
240
240
|
`, {
|
|
241
241
|
storageVersion
|
|
242
242
|
}));
|
|
243
|
-
const bucketStorage = factory.getInstance(
|
|
243
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
244
244
|
{
|
|
245
245
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
246
246
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
@@ -281,9 +281,9 @@ bucket_definitions:
|
|
|
281
281
|
});
|
|
282
282
|
await writer.commit('2/1');
|
|
283
283
|
}
|
|
284
|
-
const
|
|
284
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
285
285
|
const request = bucketRequest(syncRules, 'global[]');
|
|
286
|
-
const batch = await test_utils.
|
|
286
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [request]));
|
|
287
287
|
expect(reduceBucket(batch[0].chunkData.data).slice(1)).toEqual([]);
|
|
288
288
|
const data = batch[0].chunkData.data.map((d) => {
|
|
289
289
|
return {
|
|
@@ -296,7 +296,7 @@ bucket_definitions:
|
|
|
296
296
|
});
|
|
297
297
|
test('changing client ids', async () => {
|
|
298
298
|
await using factory = await generateStorageFactory();
|
|
299
|
-
const syncRules = await
|
|
299
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
300
300
|
bucket_definitions:
|
|
301
301
|
global:
|
|
302
302
|
data:
|
|
@@ -304,7 +304,7 @@ bucket_definitions:
|
|
|
304
304
|
`, {
|
|
305
305
|
storageVersion
|
|
306
306
|
}));
|
|
307
|
-
const bucketStorage = factory.getInstance(
|
|
307
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
308
308
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
309
309
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
310
310
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -339,8 +339,8 @@ bucket_definitions:
|
|
|
339
339
|
afterReplicaId: test_utils.rid('test2')
|
|
340
340
|
});
|
|
341
341
|
await writer.commit('1/1');
|
|
342
|
-
const
|
|
343
|
-
const batch = await test_utils.
|
|
342
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
343
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [bucketRequest(syncRules, 'global[]')]));
|
|
344
344
|
const data = batch[0].chunkData.data.map((d) => {
|
|
345
345
|
return {
|
|
346
346
|
op: d.op,
|
|
@@ -356,7 +356,7 @@ bucket_definitions:
|
|
|
356
356
|
});
|
|
357
357
|
test('re-apply delete', async () => {
|
|
358
358
|
await using factory = await generateStorageFactory();
|
|
359
|
-
const syncRules = await
|
|
359
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
360
360
|
bucket_definitions:
|
|
361
361
|
global:
|
|
362
362
|
data:
|
|
@@ -364,7 +364,7 @@ bucket_definitions:
|
|
|
364
364
|
`, {
|
|
365
365
|
storageVersion
|
|
366
366
|
}));
|
|
367
|
-
const bucketStorage = factory.getInstance(
|
|
367
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
368
368
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
369
369
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
370
370
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -390,9 +390,9 @@ bucket_definitions:
|
|
|
390
390
|
beforeReplicaId: test_utils.rid('test1')
|
|
391
391
|
});
|
|
392
392
|
await writer.flush();
|
|
393
|
-
const
|
|
393
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
394
394
|
const request = bucketRequest(syncRules, 'global[]');
|
|
395
|
-
const batch = await test_utils.
|
|
395
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [request]));
|
|
396
396
|
const data = batch[0].chunkData.data.map((d) => {
|
|
397
397
|
return {
|
|
398
398
|
op: d.op,
|
|
@@ -417,13 +417,13 @@ bucket_definitions:
|
|
|
417
417
|
});
|
|
418
418
|
test('re-apply update + delete', async () => {
|
|
419
419
|
await using factory = await generateStorageFactory();
|
|
420
|
-
const syncRules = await
|
|
420
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
421
421
|
bucket_definitions:
|
|
422
422
|
global:
|
|
423
423
|
data:
|
|
424
424
|
- SELECT id, description FROM "%"
|
|
425
425
|
`, { storageVersion }));
|
|
426
|
-
const bucketStorage = factory.getInstance(
|
|
426
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
427
427
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
428
428
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
429
429
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -487,9 +487,9 @@ bucket_definitions:
|
|
|
487
487
|
beforeReplicaId: test_utils.rid('test1')
|
|
488
488
|
});
|
|
489
489
|
await writer.commit('2/1');
|
|
490
|
-
const
|
|
490
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
491
491
|
const request = bucketRequest(syncRules, 'global[]');
|
|
492
|
-
const batch = await test_utils.
|
|
492
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [request]));
|
|
493
493
|
const data = batch[0].chunkData.data.map((d) => {
|
|
494
494
|
return {
|
|
495
495
|
op: d.op,
|
|
@@ -523,13 +523,13 @@ bucket_definitions:
|
|
|
523
523
|
// 1. Not getting the correct "current_data" state for each operation.
|
|
524
524
|
// 2. Output order not being correct.
|
|
525
525
|
await using factory = await generateStorageFactory();
|
|
526
|
-
const syncRules = await
|
|
526
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
527
527
|
bucket_definitions:
|
|
528
528
|
global:
|
|
529
529
|
data:
|
|
530
530
|
- SELECT id, description FROM "test"
|
|
531
531
|
`, { storageVersion }));
|
|
532
|
-
const bucketStorage = factory.getInstance(
|
|
532
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
533
533
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
534
534
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
535
535
|
// Pre-setup
|
|
@@ -627,7 +627,7 @@ bucket_definitions:
|
|
|
627
627
|
const result2 = await writer.flush();
|
|
628
628
|
const checkpoint2 = result2.flushed_op;
|
|
629
629
|
const request = bucketRequest(syncRules, 'global[]', checkpoint1);
|
|
630
|
-
const batch = await test_utils.
|
|
630
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(test_utils.testCheckpoint(checkpoint2), [request]));
|
|
631
631
|
const data = batch[0].chunkData.data.map((d) => {
|
|
632
632
|
return {
|
|
633
633
|
op: d.op,
|
|
@@ -659,7 +659,7 @@ bucket_definitions:
|
|
|
659
659
|
]);
|
|
660
660
|
}
|
|
661
661
|
await using factory = await generateStorageFactory();
|
|
662
|
-
const syncRules = await
|
|
662
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
663
663
|
bucket_definitions:
|
|
664
664
|
global:
|
|
665
665
|
data:
|
|
@@ -667,7 +667,7 @@ bucket_definitions:
|
|
|
667
667
|
`, {
|
|
668
668
|
storageVersion
|
|
669
669
|
}));
|
|
670
|
-
const bucketStorage = factory.getInstance(
|
|
670
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
671
671
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
672
672
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id', 'description'], config);
|
|
673
673
|
// Pre-setup
|
|
@@ -713,7 +713,7 @@ bucket_definitions:
|
|
|
713
713
|
const result3 = await writer.flush();
|
|
714
714
|
const checkpoint3 = result3.flushed_op;
|
|
715
715
|
const request = bucketRequest(syncRules, 'global[]');
|
|
716
|
-
const batch = await test_utils.
|
|
716
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(test_utils.testCheckpoint(checkpoint3), [{ ...request, start: checkpoint1 }]));
|
|
717
717
|
const data = batch[0].chunkData.data.map((d) => {
|
|
718
718
|
return {
|
|
719
719
|
op: d.op,
|
|
@@ -755,7 +755,7 @@ bucket_definitions:
|
|
|
755
755
|
]);
|
|
756
756
|
}
|
|
757
757
|
await using factory = await generateStorageFactory();
|
|
758
|
-
const syncRules = await
|
|
758
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
759
759
|
bucket_definitions:
|
|
760
760
|
global:
|
|
761
761
|
data:
|
|
@@ -763,7 +763,7 @@ bucket_definitions:
|
|
|
763
763
|
`, {
|
|
764
764
|
storageVersion
|
|
765
765
|
}));
|
|
766
|
-
const bucketStorage = factory.getInstance(
|
|
766
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
767
767
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
768
768
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id', 'description'], config);
|
|
769
769
|
// Pre-setup
|
|
@@ -809,7 +809,7 @@ bucket_definitions:
|
|
|
809
809
|
const result3 = await writer.flush();
|
|
810
810
|
const checkpoint3 = result3.flushed_op;
|
|
811
811
|
const request = bucketRequest(syncRules, 'global[]');
|
|
812
|
-
const batch = await test_utils.
|
|
812
|
+
const batch = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(test_utils.testCheckpoint(checkpoint3), [{ ...request, start: checkpoint1 }]));
|
|
813
813
|
const data = batch[0].chunkData.data.map((d) => {
|
|
814
814
|
return {
|
|
815
815
|
op: d.op,
|
|
@@ -842,7 +842,7 @@ bucket_definitions:
|
|
|
842
842
|
// The specific batch splits is an implementation detail of the storage driver,
|
|
843
843
|
// and the test will have to updated when other implementations are added.
|
|
844
844
|
await using factory = await generateStorageFactory();
|
|
845
|
-
const syncRules = await
|
|
845
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
846
846
|
bucket_definitions:
|
|
847
847
|
global:
|
|
848
848
|
data:
|
|
@@ -850,7 +850,7 @@ bucket_definitions:
|
|
|
850
850
|
`, {
|
|
851
851
|
storageVersion
|
|
852
852
|
}));
|
|
853
|
-
const bucketStorage = factory.getInstance(
|
|
853
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
854
854
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
855
855
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
856
856
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -893,12 +893,12 @@ bucket_definitions:
|
|
|
893
893
|
afterReplicaId: test_utils.rid('test3')
|
|
894
894
|
});
|
|
895
895
|
await writer.commit('1/1');
|
|
896
|
-
const
|
|
896
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
897
897
|
const options = {
|
|
898
898
|
chunkLimitBytes: 16 * 1024 * 1024
|
|
899
899
|
};
|
|
900
900
|
const request = bucketRequest(syncRules, 'global[]');
|
|
901
|
-
const batch1 = await test_utils.
|
|
901
|
+
const batch1 = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [request], options));
|
|
902
902
|
expect(test_utils.getBatchData(batch1)).toEqual([
|
|
903
903
|
{ op_id: '1', op: 'PUT', object_id: 'test1', checksum: 2871785649 },
|
|
904
904
|
{ op_id: '2', op: 'PUT', object_id: 'large1', checksum: 454746904 }
|
|
@@ -908,7 +908,7 @@ bucket_definitions:
|
|
|
908
908
|
has_more: true,
|
|
909
909
|
next_after: '2'
|
|
910
910
|
});
|
|
911
|
-
const batch2 = await test_utils.
|
|
911
|
+
const batch2 = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [{ ...request, start: BigInt(batch1[0].chunkData.next_after) }], options));
|
|
912
912
|
expect(test_utils.getBatchData(batch2)).toEqual([
|
|
913
913
|
{ op_id: '3', op: 'PUT', object_id: 'large2', checksum: 1795508474 },
|
|
914
914
|
{ op_id: '4', op: 'PUT', object_id: 'test3', checksum: 1359888332 }
|
|
@@ -918,14 +918,15 @@ bucket_definitions:
|
|
|
918
918
|
has_more: false,
|
|
919
919
|
next_after: '4'
|
|
920
920
|
});
|
|
921
|
-
const batch3 = await test_utils.
|
|
921
|
+
const batch3 = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [{ ...request, start: BigInt(batch2[0].chunkData.next_after) }], options));
|
|
922
922
|
expect(test_utils.getBatchData(batch3)).toEqual([]);
|
|
923
923
|
expect(test_utils.getBatchMeta(batch3)).toEqual(null);
|
|
924
924
|
});
|
|
925
925
|
test('long batch', async () => {
|
|
926
|
-
// Test syncing a batch of data that is limited by count.
|
|
926
|
+
// Test syncing a batch of data that is limited by count. Compressed storage limits persisted
|
|
927
|
+
// documents and finishes yielding all operations from a document once it has been hydrated.
|
|
927
928
|
await using factory = await generateStorageFactory();
|
|
928
|
-
const syncRules = await
|
|
929
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
929
930
|
bucket_definitions:
|
|
930
931
|
global:
|
|
931
932
|
data:
|
|
@@ -933,7 +934,7 @@ bucket_definitions:
|
|
|
933
934
|
`, {
|
|
934
935
|
storageVersion
|
|
935
936
|
}));
|
|
936
|
-
const bucketStorage = factory.getInstance(
|
|
937
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
937
938
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
938
939
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
939
940
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -949,42 +950,57 @@ bucket_definitions:
|
|
|
949
950
|
});
|
|
950
951
|
}
|
|
951
952
|
await writer.commit('1/1');
|
|
952
|
-
const
|
|
953
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
953
954
|
const request = bucketRequest(syncRules, 'global[]');
|
|
954
|
-
const batch1 = await test_utils.
|
|
955
|
-
|
|
955
|
+
const batch1 = await test_utils.getSingleBatchItem(bucketStorage.getBucketDataBatch(checkpoint, [request], { limit: 4 }));
|
|
956
|
+
const allOperations = [
|
|
956
957
|
{ op_id: '1', op: 'PUT', object_id: 'test1', checksum: 2871785649 },
|
|
957
958
|
{ op_id: '2', op: 'PUT', object_id: 'test2', checksum: 730027011 },
|
|
958
959
|
{ op_id: '3', op: 'PUT', object_id: 'test3', checksum: 1359888332 },
|
|
959
|
-
{ op_id: '4', op: 'PUT', object_id: 'test4', checksum: 2049153252 }
|
|
960
|
-
]);
|
|
961
|
-
expect(test_utils.getBatchMeta(batch1)).toEqual({
|
|
962
|
-
after: '0',
|
|
963
|
-
has_more: true,
|
|
964
|
-
next_after: '4'
|
|
965
|
-
});
|
|
966
|
-
const batch2 = await test_utils.oneFromAsync(bucketStorage.getBucketDataBatch(checkpoint, [{ ...request, start: BigInt(batch1.chunkData.next_after) }], {
|
|
967
|
-
limit: 4
|
|
968
|
-
}));
|
|
969
|
-
expect(test_utils.getBatchData(batch2)).toEqual([
|
|
960
|
+
{ op_id: '4', op: 'PUT', object_id: 'test4', checksum: 2049153252 },
|
|
970
961
|
{ op_id: '5', op: 'PUT', object_id: 'test5', checksum: 3686902721 },
|
|
971
962
|
{ op_id: '6', op: 'PUT', object_id: 'test6', checksum: 1974820016 }
|
|
972
|
-
]
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
963
|
+
];
|
|
964
|
+
if (config.compressedBucketStorage) {
|
|
965
|
+
expect(test_utils.getBatchData(batch1)).toEqual(allOperations);
|
|
966
|
+
expect(test_utils.getBatchMeta(batch1)).toEqual({
|
|
967
|
+
after: '0',
|
|
968
|
+
has_more: false,
|
|
969
|
+
next_after: '6'
|
|
970
|
+
});
|
|
971
|
+
const batch2 = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [{ ...request, start: BigInt(batch1.chunkData.next_after) }], {
|
|
972
|
+
limit: 4
|
|
973
|
+
}));
|
|
974
|
+
expect(test_utils.getBatchData(batch2)).toEqual([]);
|
|
975
|
+
expect(test_utils.getBatchMeta(batch2)).toEqual(null);
|
|
976
|
+
}
|
|
977
|
+
else {
|
|
978
|
+
expect(test_utils.getBatchData(batch1)).toEqual(allOperations.slice(0, 4));
|
|
979
|
+
expect(test_utils.getBatchMeta(batch1)).toEqual({
|
|
980
|
+
after: '0',
|
|
981
|
+
has_more: true,
|
|
982
|
+
next_after: '4'
|
|
983
|
+
});
|
|
984
|
+
const batch2 = await test_utils.getSingleBatchItem(bucketStorage.getBucketDataBatch(checkpoint, [{ ...request, start: BigInt(batch1.chunkData.next_after) }], {
|
|
985
|
+
limit: 4
|
|
986
|
+
}));
|
|
987
|
+
expect(test_utils.getBatchData(batch2)).toEqual(allOperations.slice(4));
|
|
988
|
+
expect(test_utils.getBatchMeta(batch2)).toEqual({
|
|
989
|
+
after: '4',
|
|
990
|
+
has_more: false,
|
|
991
|
+
next_after: '6'
|
|
992
|
+
});
|
|
993
|
+
const batch3 = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(checkpoint, [{ ...request, start: BigInt(batch2.chunkData.next_after) }], {
|
|
994
|
+
limit: 4
|
|
995
|
+
}));
|
|
996
|
+
expect(test_utils.getBatchData(batch3)).toEqual([]);
|
|
997
|
+
expect(test_utils.getBatchMeta(batch3)).toEqual(null);
|
|
998
|
+
}
|
|
983
999
|
});
|
|
984
1000
|
describe('batch has_more', () => {
|
|
985
|
-
const setup = async (options) => {
|
|
1001
|
+
const setup = async (options, commitAfter) => {
|
|
986
1002
|
await using factory = await generateStorageFactory();
|
|
987
|
-
const syncRules = await
|
|
1003
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
988
1004
|
bucket_definitions:
|
|
989
1005
|
global1:
|
|
990
1006
|
data:
|
|
@@ -993,7 +1009,7 @@ bucket_definitions:
|
|
|
993
1009
|
data:
|
|
994
1010
|
- SELECT id, description FROM test WHERE bucket = 'global2'
|
|
995
1011
|
`, { storageVersion }));
|
|
996
|
-
const bucketStorage = factory.getInstance(
|
|
1012
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
997
1013
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
998
1014
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
999
1015
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -1008,28 +1024,39 @@ bucket_definitions:
|
|
|
1008
1024
|
},
|
|
1009
1025
|
afterReplicaId: `test${i}`
|
|
1010
1026
|
});
|
|
1027
|
+
if (i == commitAfter) {
|
|
1028
|
+
await writer.commit('1/1');
|
|
1029
|
+
}
|
|
1011
1030
|
}
|
|
1012
|
-
await writer.commit('1/1');
|
|
1013
|
-
const
|
|
1031
|
+
await writer.commit(commitAfter == null ? '1/1' : '1/2');
|
|
1032
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
1014
1033
|
const global1Request = bucketRequest(syncRules, 'global1[]', 0n);
|
|
1015
1034
|
const global2Request = bucketRequest(syncRules, 'global2[]', 0n);
|
|
1016
|
-
const batch = await test_utils.
|
|
1035
|
+
const batch = await new test_utils.StorageDataHelpers(bucketStorage, syncRules).getAllBucketData([global1Request, global2Request], checkpoint, options);
|
|
1017
1036
|
return { batch, global1Request, global2Request };
|
|
1018
1037
|
};
|
|
1019
1038
|
test('batch has_more (1)', async () => {
|
|
1020
|
-
|
|
1021
|
-
|
|
1039
|
+
// The commit boundary creates two compressed documents for global2. The limit selects the global1
|
|
1040
|
+
// document and the first global2 document, leaving the second global2 document for the next batch.
|
|
1041
|
+
const { batch, global1Request, global2Request } = await setup({ limit: 2 }, 5);
|
|
1042
|
+
expect(batch.length).toBeGreaterThanOrEqual(2);
|
|
1022
1043
|
expect(batch[0].chunkData.bucket).toEqual(global1Request.bucket);
|
|
1023
1044
|
expect(batch[1].chunkData.bucket).toEqual(global2Request.bucket);
|
|
1024
1045
|
expect(test_utils.getBatchData(batch[0])).toEqual([
|
|
1025
1046
|
{ op_id: '1', op: 'PUT', object_id: 'test1', checksum: 2871785649 }
|
|
1026
1047
|
]);
|
|
1027
|
-
|
|
1048
|
+
const global2Operations = [
|
|
1028
1049
|
{ op_id: '2', op: 'PUT', object_id: 'test2', checksum: 730027011 },
|
|
1029
1050
|
{ op_id: '3', op: 'PUT', object_id: 'test3', checksum: 1359888332 },
|
|
1030
1051
|
{ op_id: '4', op: 'PUT', object_id: 'test4', checksum: 2049153252 },
|
|
1031
|
-
{ op_id: '5', op: 'PUT', object_id: 'test5', checksum: 3686902721 }
|
|
1032
|
-
|
|
1052
|
+
{ op_id: '5', op: 'PUT', object_id: 'test5', checksum: 3686902721 },
|
|
1053
|
+
{ op_id: '6', op: 'PUT', object_id: 'test6', checksum: 1974820016 },
|
|
1054
|
+
{ op_id: '7', op: 'PUT', object_id: 'test7', checksum: 2477637855 },
|
|
1055
|
+
{ op_id: '8', op: 'PUT', object_id: 'test8', checksum: 3644033632 },
|
|
1056
|
+
{ op_id: '9', op: 'PUT', object_id: 'test9', checksum: 1011055869 },
|
|
1057
|
+
{ op_id: '10', op: 'PUT', object_id: 'test10', checksum: 1331456365 }
|
|
1058
|
+
];
|
|
1059
|
+
expect(test_utils.getBatchData(batch[1])).toEqual(config.compressedBucketStorage ? global2Operations.slice(0, 4) : global2Operations.slice(0, 1));
|
|
1033
1060
|
expect(test_utils.getBatchMeta(batch[0])).toEqual({
|
|
1034
1061
|
after: '0',
|
|
1035
1062
|
has_more: false,
|
|
@@ -1038,7 +1065,7 @@ bucket_definitions:
|
|
|
1038
1065
|
expect(test_utils.getBatchMeta(batch[1])).toEqual({
|
|
1039
1066
|
after: '0',
|
|
1040
1067
|
has_more: true,
|
|
1041
|
-
next_after: '5'
|
|
1068
|
+
next_after: config.compressedBucketStorage ? '5' : '2'
|
|
1042
1069
|
});
|
|
1043
1070
|
});
|
|
1044
1071
|
test('batch has_more (2)', async () => {
|
|
@@ -1074,34 +1101,67 @@ bucket_definitions:
|
|
|
1074
1101
|
test('batch has_more (3)', async () => {
|
|
1075
1102
|
// 50 bytes is more than 1 row, less than 2 rows
|
|
1076
1103
|
const { batch, global1Request, global2Request } = await setup({ limit: 3, chunkLimitBytes: 50 });
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1104
|
+
if (config.compressedBucketStorage) {
|
|
1105
|
+
// In v3+, ops in the same bucket share a document. Once hydrated, the entire document is yielded even
|
|
1106
|
+
// when it exceeds the byte limit; the byte limit controls whether another document is fetched.
|
|
1107
|
+
expect(batch.length).toEqual(2);
|
|
1108
|
+
expect(batch[0].chunkData.bucket).toEqual(global1Request.bucket);
|
|
1109
|
+
expect(batch[1].chunkData.bucket).toEqual(global2Request.bucket);
|
|
1110
|
+
expect(test_utils.getBatchData(batch[0])).toEqual([
|
|
1111
|
+
{ op_id: '1', op: 'PUT', object_id: 'test1', checksum: 2871785649 }
|
|
1112
|
+
]);
|
|
1113
|
+
expect(test_utils.getBatchData(batch[1])).toEqual([
|
|
1114
|
+
{ op_id: '2', op: 'PUT', object_id: 'test2', checksum: 730027011 },
|
|
1115
|
+
{ op_id: '3', op: 'PUT', object_id: 'test3', checksum: 1359888332 },
|
|
1116
|
+
{ op_id: '4', op: 'PUT', object_id: 'test4', checksum: 2049153252 },
|
|
1117
|
+
{ op_id: '5', op: 'PUT', object_id: 'test5', checksum: 3686902721 },
|
|
1118
|
+
{ op_id: '6', op: 'PUT', object_id: 'test6', checksum: 1974820016 },
|
|
1119
|
+
{ op_id: '7', op: 'PUT', object_id: 'test7', checksum: 2477637855 },
|
|
1120
|
+
{ op_id: '8', op: 'PUT', object_id: 'test8', checksum: 3644033632 },
|
|
1121
|
+
{ op_id: '9', op: 'PUT', object_id: 'test9', checksum: 1011055869 },
|
|
1122
|
+
{ op_id: '10', op: 'PUT', object_id: 'test10', checksum: 1331456365 }
|
|
1123
|
+
]);
|
|
1124
|
+
expect(test_utils.getBatchMeta(batch[0])).toEqual({
|
|
1125
|
+
after: '0',
|
|
1126
|
+
has_more: false,
|
|
1127
|
+
next_after: '1'
|
|
1128
|
+
});
|
|
1129
|
+
expect(test_utils.getBatchMeta(batch[1])).toEqual({
|
|
1130
|
+
after: '0',
|
|
1131
|
+
has_more: false,
|
|
1132
|
+
next_after: '10'
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
else {
|
|
1136
|
+
expect(batch.length).toBeGreaterThanOrEqual(3);
|
|
1137
|
+
expect(batch[0].chunkData.bucket).toEqual(global1Request.bucket);
|
|
1138
|
+
expect(batch[1].chunkData.bucket).toEqual(global2Request.bucket);
|
|
1139
|
+
expect(batch[2].chunkData.bucket).toEqual(global2Request.bucket);
|
|
1140
|
+
expect(test_utils.getBatchData(batch[0])).toEqual([
|
|
1141
|
+
{ op_id: '1', op: 'PUT', object_id: 'test1', checksum: 2871785649 }
|
|
1142
|
+
]);
|
|
1143
|
+
expect(test_utils.getBatchData(batch[1])).toEqual([
|
|
1144
|
+
{ op_id: '2', op: 'PUT', object_id: 'test2', checksum: 730027011 }
|
|
1145
|
+
]);
|
|
1146
|
+
expect(test_utils.getBatchData(batch[2])).toEqual([
|
|
1147
|
+
{ op_id: '3', op: 'PUT', object_id: 'test3', checksum: 1359888332 }
|
|
1148
|
+
]);
|
|
1149
|
+
expect(test_utils.getBatchMeta(batch[0])).toEqual({
|
|
1150
|
+
after: '0',
|
|
1151
|
+
has_more: false,
|
|
1152
|
+
next_after: '1'
|
|
1153
|
+
});
|
|
1154
|
+
expect(test_utils.getBatchMeta(batch[1])).toEqual({
|
|
1155
|
+
after: '0',
|
|
1156
|
+
has_more: true,
|
|
1157
|
+
next_after: '2'
|
|
1158
|
+
});
|
|
1159
|
+
expect(test_utils.getBatchMeta(batch[2])).toEqual({
|
|
1160
|
+
after: '2',
|
|
1161
|
+
has_more: true,
|
|
1162
|
+
next_after: '3'
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1105
1165
|
});
|
|
1106
1166
|
});
|
|
1107
1167
|
test('empty storage metrics', async () => {
|
|
@@ -1125,7 +1185,7 @@ bucket_definitions:
|
|
|
1125
1185
|
// but large enough in size to be split over multiple returned chunks.
|
|
1126
1186
|
// Similar to the above test, but splits over 1MB chunks.
|
|
1127
1187
|
await using factory = await generateStorageFactory();
|
|
1128
|
-
const syncRules = await
|
|
1188
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
1129
1189
|
bucket_definitions:
|
|
1130
1190
|
global:
|
|
1131
1191
|
data:
|
|
@@ -1134,7 +1194,7 @@ bucket_definitions:
|
|
|
1134
1194
|
`, {
|
|
1135
1195
|
storageVersion
|
|
1136
1196
|
}));
|
|
1137
|
-
const bucketStorage = factory.getInstance(
|
|
1197
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
1138
1198
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1139
1199
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config, 1);
|
|
1140
1200
|
const sourceTableIgnore = await test_utils.resolveTestTable(writer, 'test_ignore', ['id'], config, 2);
|
|
@@ -1166,7 +1226,7 @@ bucket_definitions:
|
|
|
1166
1226
|
});
|
|
1167
1227
|
test('unchanged checksums', async () => {
|
|
1168
1228
|
await using factory = await generateStorageFactory();
|
|
1169
|
-
const syncRules = await
|
|
1229
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
1170
1230
|
bucket_definitions:
|
|
1171
1231
|
global:
|
|
1172
1232
|
data:
|
|
@@ -1174,7 +1234,7 @@ bucket_definitions:
|
|
|
1174
1234
|
`, {
|
|
1175
1235
|
storageVersion
|
|
1176
1236
|
}));
|
|
1177
|
-
const bucketStorage = factory.getInstance(
|
|
1237
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
1178
1238
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1179
1239
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
1180
1240
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -1188,23 +1248,25 @@ bucket_definitions:
|
|
|
1188
1248
|
afterReplicaId: test_utils.rid('test1')
|
|
1189
1249
|
});
|
|
1190
1250
|
await writer.commit('1/1');
|
|
1191
|
-
const
|
|
1251
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
1192
1252
|
const request = bucketRequest(syncRules, 'global[]');
|
|
1193
1253
|
const checksums = [...(await bucketStorage.getChecksums(checkpoint, [request])).values()];
|
|
1194
1254
|
expect(checksums).toEqual([{ bucket: request.bucket, checksum: 1917136889, count: 1 }]);
|
|
1195
|
-
const checksums2 = [
|
|
1255
|
+
const checksums2 = [
|
|
1256
|
+
...(await bucketStorage.getChecksums(test_utils.testCheckpoint(checkpoint.checkpoint + 1n), [request])).values()
|
|
1257
|
+
];
|
|
1196
1258
|
expect(checksums2).toEqual([{ bucket: request.bucket, checksum: 1917136889, count: 1 }]);
|
|
1197
1259
|
});
|
|
1198
1260
|
testChecksumBatching(config);
|
|
1199
1261
|
test('empty checkpoints (1)', async () => {
|
|
1200
1262
|
await using factory = await generateStorageFactory();
|
|
1201
|
-
const
|
|
1263
|
+
const { stream: replicationStream } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
1202
1264
|
bucket_definitions:
|
|
1203
1265
|
global:
|
|
1204
1266
|
data:
|
|
1205
1267
|
- SELECT id, description FROM "%"
|
|
1206
1268
|
`, { storageVersion }));
|
|
1207
|
-
const bucketStorage = factory.getInstance(
|
|
1269
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
1208
1270
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1209
1271
|
await writer.markAllSnapshotDone('1/1');
|
|
1210
1272
|
await writer.commit('1/1');
|
|
@@ -1224,7 +1286,7 @@ bucket_definitions:
|
|
|
1224
1286
|
});
|
|
1225
1287
|
test('empty checkpoints (2)', async () => {
|
|
1226
1288
|
await using factory = await generateStorageFactory();
|
|
1227
|
-
const
|
|
1289
|
+
const { stream: replicationStream } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
1228
1290
|
bucket_definitions:
|
|
1229
1291
|
global:
|
|
1230
1292
|
data:
|
|
@@ -1232,7 +1294,7 @@ bucket_definitions:
|
|
|
1232
1294
|
`, {
|
|
1233
1295
|
storageVersion
|
|
1234
1296
|
}));
|
|
1235
|
-
const bucketStorage = factory.getInstance(
|
|
1297
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
1236
1298
|
await using writer1 = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1237
1299
|
await using writer2 = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1238
1300
|
const sourceTable = await test_utils.resolveTestTable(writer2, 'test', ['id'], config);
|
|
@@ -1263,7 +1325,7 @@ bucket_definitions:
|
|
|
1263
1325
|
});
|
|
1264
1326
|
test('empty checkpoints (sync rule activation)', async () => {
|
|
1265
1327
|
await using factory = await generateStorageFactory();
|
|
1266
|
-
const syncRules = await
|
|
1328
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
1267
1329
|
bucket_definitions:
|
|
1268
1330
|
global:
|
|
1269
1331
|
data:
|
|
@@ -1271,7 +1333,7 @@ bucket_definitions:
|
|
|
1271
1333
|
`, {
|
|
1272
1334
|
storageVersion
|
|
1273
1335
|
}));
|
|
1274
|
-
const bucketStorage = factory.getInstance(
|
|
1336
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
1275
1337
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1276
1338
|
const result1 = await writer.commit('1/1', { createEmptyCheckpoints: false });
|
|
1277
1339
|
expect(result1).toEqual({ checkpointBlocked: true, checkpointCreated: false });
|
|
@@ -1290,8 +1352,8 @@ bucket_definitions:
|
|
|
1290
1352
|
// Now, the checkpoint should advance the sync rules active.
|
|
1291
1353
|
const cp2 = await bucketStorage.getCheckpoint();
|
|
1292
1354
|
expect(cp2.lsn).toEqual('3/1');
|
|
1293
|
-
const activeSyncRules = await factory.
|
|
1294
|
-
expect(activeSyncRules?.
|
|
1355
|
+
const activeSyncRules = await factory.getActiveSyncConfig();
|
|
1356
|
+
expect(activeSyncRules?.content.replicationStreamId).toEqual(syncRules.replicationStreamId);
|
|
1295
1357
|
// At this point, it should be a truely empty checkpoint
|
|
1296
1358
|
const result4 = await writer.commit('4/1', { createEmptyCheckpoints: false });
|
|
1297
1359
|
expect(result4).toEqual({ checkpointBlocked: false, checkpointCreated: false });
|
|
@@ -1301,7 +1363,7 @@ bucket_definitions:
|
|
|
1301
1363
|
});
|
|
1302
1364
|
test.runIf(storageVersion >= 3)('deleting while streaming', async () => {
|
|
1303
1365
|
await using factory = await generateStorageFactory();
|
|
1304
|
-
const syncRules = await
|
|
1366
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
1305
1367
|
bucket_definitions:
|
|
1306
1368
|
global:
|
|
1307
1369
|
data:
|
|
@@ -1309,7 +1371,7 @@ bucket_definitions:
|
|
|
1309
1371
|
`, {
|
|
1310
1372
|
storageVersion
|
|
1311
1373
|
}));
|
|
1312
|
-
const bucketStorage = factory.getInstance(
|
|
1374
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
1313
1375
|
await using snapshotWriter = await bucketStorage.createWriter({
|
|
1314
1376
|
...test_utils.BATCH_OPTIONS,
|
|
1315
1377
|
skipExistingRows: true
|
|
@@ -1344,7 +1406,7 @@ bucket_definitions:
|
|
|
1344
1406
|
await streamingWriter.keepalive('3/1');
|
|
1345
1407
|
const cp = await bucketStorage.getCheckpoint();
|
|
1346
1408
|
expect(cp.lsn).toEqual('3/1');
|
|
1347
|
-
const data = await test_utils.
|
|
1409
|
+
const data = await test_utils.getBatchArray(bucketStorage.getBucketDataBatch(cp, [bucketRequest(syncRules, 'global[]')]));
|
|
1348
1410
|
expect(data).toEqual([]);
|
|
1349
1411
|
});
|
|
1350
1412
|
}
|
|
@@ -1357,7 +1419,7 @@ export function testChecksumBatching(config) {
|
|
|
1357
1419
|
const storageVersion = config.storageVersion ?? CURRENT_STORAGE_VERSION;
|
|
1358
1420
|
test('checksums for multiple buckets', async () => {
|
|
1359
1421
|
await using factory = await config.factory();
|
|
1360
|
-
const syncRules = await
|
|
1422
|
+
const { stream: replicationStream, content: syncRules } = await test_utils.deploySyncRules(factory, updateSyncRulesFromYaml(`
|
|
1361
1423
|
bucket_definitions:
|
|
1362
1424
|
user:
|
|
1363
1425
|
parameters: select request.user_id() as user_id
|
|
@@ -1366,7 +1428,7 @@ bucket_definitions:
|
|
|
1366
1428
|
`, {
|
|
1367
1429
|
storageVersion
|
|
1368
1430
|
}));
|
|
1369
|
-
const bucketStorage = factory.getInstance(
|
|
1431
|
+
const bucketStorage = factory.getInstance(replicationStream);
|
|
1370
1432
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1371
1433
|
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
1372
1434
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -1386,7 +1448,7 @@ bucket_definitions:
|
|
|
1386
1448
|
}
|
|
1387
1449
|
}
|
|
1388
1450
|
await writer.commit('1/1');
|
|
1389
|
-
const
|
|
1451
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
1390
1452
|
bucketStorage.clearChecksumCache();
|
|
1391
1453
|
const users = ['u1', 'u2', 'u3', 'u4'];
|
|
1392
1454
|
const expectedChecksums = [346204588, 5261081, 134760718, -302639724];
|
|
@@ -1411,7 +1473,11 @@ streams:
|
|
|
1411
1473
|
invalid:
|
|
1412
1474
|
query: UPDATE test SET foo = 'bar' RETURNING *
|
|
1413
1475
|
`));
|
|
1414
|
-
const
|
|
1476
|
+
const [deployedContent] = deployed.syncConfigContent;
|
|
1477
|
+
expect(deployedContent).toBeDefined();
|
|
1478
|
+
const [deployedConfig] = deployedContent.parsed({ defaultSchema: 'ignored' }).syncConfigs;
|
|
1479
|
+
expect(deployedConfig).toBeDefined();
|
|
1480
|
+
const { errors } = deployedConfig;
|
|
1415
1481
|
expect(errors).toHaveLength(1);
|
|
1416
1482
|
expect(errors[0].message).toStrictEqual('Expected a SELECT statement');
|
|
1417
1483
|
expect(errors[0].location).toStrictEqual({
|