@powersync/service-core-tests 0.15.0 → 0.15.2
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 +27 -0
- package/dist/test-utils/general-utils.d.ts +13 -1
- package/dist/test-utils/general-utils.js +30 -1
- package/dist/test-utils/general-utils.js.map +1 -1
- package/dist/test-utils/stream_utils.js +2 -2
- package/dist/test-utils/stream_utils.js.map +1 -1
- package/dist/tests/register-compacting-tests.js +266 -257
- package/dist/tests/register-compacting-tests.js.map +1 -1
- package/dist/tests/register-data-storage-checkpoint-tests.js +36 -57
- package/dist/tests/register-data-storage-checkpoint-tests.js.map +1 -1
- package/dist/tests/register-data-storage-data-tests.js +839 -863
- package/dist/tests/register-data-storage-data-tests.js.map +1 -1
- package/dist/tests/register-data-storage-parameter-tests.js +228 -236
- package/dist/tests/register-data-storage-parameter-tests.js.map +1 -1
- package/dist/tests/register-parameter-compacting-tests.js +81 -89
- package/dist/tests/register-parameter-compacting-tests.js.map +1 -1
- package/dist/tests/register-sync-tests.js +468 -462
- package/dist/tests/register-sync-tests.js.map +1 -1
- package/package.json +3 -3
- package/src/test-utils/general-utils.ts +41 -2
- package/src/test-utils/stream_utils.ts +2 -2
- package/src/tests/register-compacting-tests.ts +279 -270
- package/src/tests/register-data-storage-checkpoint-tests.ts +36 -57
- package/src/tests/register-data-storage-data-tests.ts +673 -770
- package/src/tests/register-data-storage-parameter-tests.ts +245 -257
- package/src/tests/register-parameter-compacting-tests.ts +84 -92
- package/src/tests/register-sync-tests.ts +375 -391
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -53,7 +53,6 @@ export function registerSyncTests(
|
|
|
53
53
|
maxDataFetchConcurrency: 2
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
const TEST_TABLE = test_utils.makeTestTable('test', ['id'], config);
|
|
57
56
|
const updateSyncRules = (bucketStorageFactory: storage.BucketStorageFactory, updateOptions: { content: string }) => {
|
|
58
57
|
return bucketStorageFactory.updateSyncRules(
|
|
59
58
|
updateSyncRulesFromYaml(updateOptions.content, {
|
|
@@ -71,33 +70,33 @@ export function registerSyncTests(
|
|
|
71
70
|
});
|
|
72
71
|
|
|
73
72
|
const bucketStorage = f.getInstance(syncRules);
|
|
73
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
74
|
+
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
74
75
|
|
|
75
|
-
await
|
|
76
|
-
await batch.markAllSnapshotDone('0/1');
|
|
76
|
+
await writer.markAllSnapshotDone('0/1');
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
await batch.save({
|
|
89
|
-
sourceTable: TEST_TABLE,
|
|
90
|
-
tag: storage.SaveOperationTag.INSERT,
|
|
91
|
-
after: {
|
|
92
|
-
id: 't2',
|
|
93
|
-
description: 'Test 2'
|
|
94
|
-
},
|
|
95
|
-
afterReplicaId: 't2'
|
|
96
|
-
});
|
|
78
|
+
await writer.save({
|
|
79
|
+
sourceTable,
|
|
80
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
81
|
+
after: {
|
|
82
|
+
id: 't1',
|
|
83
|
+
description: 'Test 1'
|
|
84
|
+
},
|
|
85
|
+
afterReplicaId: 't1'
|
|
86
|
+
});
|
|
97
87
|
|
|
98
|
-
|
|
88
|
+
await writer.save({
|
|
89
|
+
sourceTable,
|
|
90
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
91
|
+
after: {
|
|
92
|
+
id: 't2',
|
|
93
|
+
description: 'Test 2'
|
|
94
|
+
},
|
|
95
|
+
afterReplicaId: 't2'
|
|
99
96
|
});
|
|
100
97
|
|
|
98
|
+
await writer.commit('0/1');
|
|
99
|
+
|
|
101
100
|
const stream = sync.streamResponse({
|
|
102
101
|
syncContext,
|
|
103
102
|
bucketStorage: bucketStorage,
|
|
@@ -134,32 +133,32 @@ bucket_definitions:
|
|
|
134
133
|
});
|
|
135
134
|
|
|
136
135
|
const bucketStorage = f.getInstance(syncRules);
|
|
136
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
137
|
+
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
138
|
+
|
|
139
|
+
await writer.markAllSnapshotDone('0/1');
|
|
140
|
+
await writer.save({
|
|
141
|
+
sourceTable: testTable,
|
|
142
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
143
|
+
after: {
|
|
144
|
+
id: 't1',
|
|
145
|
+
description: 'Test 1'
|
|
146
|
+
},
|
|
147
|
+
afterReplicaId: 't1'
|
|
148
|
+
});
|
|
137
149
|
|
|
138
|
-
await
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
},
|
|
147
|
-
afterReplicaId: 't1'
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
await batch.save({
|
|
151
|
-
sourceTable: TEST_TABLE,
|
|
152
|
-
tag: storage.SaveOperationTag.INSERT,
|
|
153
|
-
after: {
|
|
154
|
-
id: 'earlier',
|
|
155
|
-
description: 'Test 2'
|
|
156
|
-
},
|
|
157
|
-
afterReplicaId: 'earlier'
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
await batch.commit('0/1');
|
|
150
|
+
await writer.save({
|
|
151
|
+
sourceTable: testTable,
|
|
152
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
153
|
+
after: {
|
|
154
|
+
id: 'earlier',
|
|
155
|
+
description: 'Test 2'
|
|
156
|
+
},
|
|
157
|
+
afterReplicaId: 'earlier'
|
|
161
158
|
});
|
|
162
159
|
|
|
160
|
+
await writer.commit('0/1');
|
|
161
|
+
|
|
163
162
|
const stream = sync.streamResponse({
|
|
164
163
|
syncContext,
|
|
165
164
|
bucketStorage,
|
|
@@ -196,33 +195,33 @@ bucket_definitions:
|
|
|
196
195
|
});
|
|
197
196
|
|
|
198
197
|
const bucketStorage = f.getInstance(syncRules);
|
|
199
|
-
|
|
200
|
-
await
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
198
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
199
|
+
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
200
|
+
|
|
201
|
+
await writer.markAllSnapshotDone('0/1');
|
|
202
|
+
// Initial data: Add one priority row and 10k low-priority rows.
|
|
203
|
+
await writer.save({
|
|
204
|
+
sourceTable: testTable,
|
|
205
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
206
|
+
after: {
|
|
207
|
+
id: 'highprio',
|
|
208
|
+
description: 'High priority row'
|
|
209
|
+
},
|
|
210
|
+
afterReplicaId: 'highprio'
|
|
211
|
+
});
|
|
212
|
+
for (let i = 0; i < 10_000; i++) {
|
|
213
|
+
await writer.save({
|
|
214
|
+
sourceTable: testTable,
|
|
205
215
|
tag: storage.SaveOperationTag.INSERT,
|
|
206
216
|
after: {
|
|
207
|
-
id:
|
|
208
|
-
description: '
|
|
217
|
+
id: `${i}`,
|
|
218
|
+
description: 'low prio'
|
|
209
219
|
},
|
|
210
|
-
afterReplicaId:
|
|
220
|
+
afterReplicaId: `${i}`
|
|
211
221
|
});
|
|
212
|
-
|
|
213
|
-
await batch.save({
|
|
214
|
-
sourceTable: TEST_TABLE,
|
|
215
|
-
tag: storage.SaveOperationTag.INSERT,
|
|
216
|
-
after: {
|
|
217
|
-
id: `${i}`,
|
|
218
|
-
description: 'low prio'
|
|
219
|
-
},
|
|
220
|
-
afterReplicaId: `${i}`
|
|
221
|
-
});
|
|
222
|
-
}
|
|
222
|
+
}
|
|
223
223
|
|
|
224
|
-
|
|
225
|
-
});
|
|
224
|
+
await writer.commit('0/1');
|
|
226
225
|
|
|
227
226
|
const stream = sync.streamResponse({
|
|
228
227
|
syncContext,
|
|
@@ -250,20 +249,18 @@ bucket_definitions:
|
|
|
250
249
|
if (sentCheckpoints == 1) {
|
|
251
250
|
// Save new data to interrupt the low-priority sync.
|
|
252
251
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
afterReplicaId: 'highprio2'
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
await batch.commit('0/2');
|
|
252
|
+
// Add another high-priority row. This should interrupt the long-running low-priority sync.
|
|
253
|
+
await writer.save({
|
|
254
|
+
sourceTable: testTable,
|
|
255
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
256
|
+
after: {
|
|
257
|
+
id: 'highprio2',
|
|
258
|
+
description: 'Another high-priority row'
|
|
259
|
+
},
|
|
260
|
+
afterReplicaId: 'highprio2'
|
|
266
261
|
});
|
|
262
|
+
|
|
263
|
+
await writer.commit('0/2');
|
|
267
264
|
} else {
|
|
268
265
|
// Low-priority sync from the first checkpoint was interrupted. This should not happen before
|
|
269
266
|
// 1000 low-priority items were synchronized.
|
|
@@ -307,33 +304,33 @@ bucket_definitions:
|
|
|
307
304
|
});
|
|
308
305
|
|
|
309
306
|
const bucketStorage = f.getInstance(syncRules);
|
|
310
|
-
|
|
311
|
-
await
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
307
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
308
|
+
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
309
|
+
|
|
310
|
+
await writer.markAllSnapshotDone('0/1');
|
|
311
|
+
// Initial data: Add one priority row and 10k low-priority rows.
|
|
312
|
+
await writer.save({
|
|
313
|
+
sourceTable: testTable,
|
|
314
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
315
|
+
after: {
|
|
316
|
+
id: 'highprio',
|
|
317
|
+
description: 'user_one'
|
|
318
|
+
},
|
|
319
|
+
afterReplicaId: 'highprio'
|
|
320
|
+
});
|
|
321
|
+
for (let i = 0; i < 10_000; i++) {
|
|
322
|
+
await writer.save({
|
|
323
|
+
sourceTable: testTable,
|
|
316
324
|
tag: storage.SaveOperationTag.INSERT,
|
|
317
325
|
after: {
|
|
318
|
-
id:
|
|
319
|
-
description: '
|
|
326
|
+
id: `${i}`,
|
|
327
|
+
description: 'low prio'
|
|
320
328
|
},
|
|
321
|
-
afterReplicaId:
|
|
329
|
+
afterReplicaId: `${i}`
|
|
322
330
|
});
|
|
323
|
-
|
|
324
|
-
await batch.save({
|
|
325
|
-
sourceTable: TEST_TABLE,
|
|
326
|
-
tag: storage.SaveOperationTag.INSERT,
|
|
327
|
-
after: {
|
|
328
|
-
id: `${i}`,
|
|
329
|
-
description: 'low prio'
|
|
330
|
-
},
|
|
331
|
-
afterReplicaId: `${i}`
|
|
332
|
-
});
|
|
333
|
-
}
|
|
331
|
+
}
|
|
334
332
|
|
|
335
|
-
|
|
336
|
-
});
|
|
333
|
+
await writer.commit('0/1');
|
|
337
334
|
|
|
338
335
|
const stream = sync.streamResponse({
|
|
339
336
|
syncContext,
|
|
@@ -366,20 +363,18 @@ bucket_definitions:
|
|
|
366
363
|
if (typeof next === 'object' && next !== null) {
|
|
367
364
|
if ('partial_checkpoint_complete' in next) {
|
|
368
365
|
if (sentCheckpoints == 1) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
afterReplicaId: 'highprio2'
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
await batch.commit('0/2');
|
|
366
|
+
// Add a high-priority row that doesn't affect this sync stream.
|
|
367
|
+
await writer.save({
|
|
368
|
+
sourceTable: testTable,
|
|
369
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
370
|
+
after: {
|
|
371
|
+
id: 'highprio2',
|
|
372
|
+
description: 'user_two'
|
|
373
|
+
},
|
|
374
|
+
afterReplicaId: 'highprio2'
|
|
382
375
|
});
|
|
376
|
+
|
|
377
|
+
await writer.commit('0/2');
|
|
383
378
|
} else {
|
|
384
379
|
expect(sentCheckpoints).toBe(2);
|
|
385
380
|
expect(sentRows).toBe(10002);
|
|
@@ -400,20 +395,18 @@ bucket_definitions:
|
|
|
400
395
|
if (completedCheckpoints == 1) {
|
|
401
396
|
expect(sentRows).toBe(10001);
|
|
402
397
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
afterReplicaId: 'highprio3'
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
await batch.commit('0/3');
|
|
398
|
+
// Add a high-priority row that affects this sync stream.
|
|
399
|
+
await writer.save({
|
|
400
|
+
sourceTable: testTable,
|
|
401
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
402
|
+
after: {
|
|
403
|
+
id: 'highprio3',
|
|
404
|
+
description: 'user_one'
|
|
405
|
+
},
|
|
406
|
+
afterReplicaId: 'highprio3'
|
|
416
407
|
});
|
|
408
|
+
|
|
409
|
+
await writer.commit('0/3');
|
|
417
410
|
}
|
|
418
411
|
}
|
|
419
412
|
}
|
|
@@ -449,33 +442,33 @@ bucket_definitions:
|
|
|
449
442
|
});
|
|
450
443
|
|
|
451
444
|
const bucketStorage = f.getInstance(syncRules);
|
|
452
|
-
|
|
453
|
-
await
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
445
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
446
|
+
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
447
|
+
|
|
448
|
+
await writer.markAllSnapshotDone('0/1');
|
|
449
|
+
// Initial data: Add one priority row and 10k low-priority rows.
|
|
450
|
+
await writer.save({
|
|
451
|
+
sourceTable: testTable,
|
|
452
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
453
|
+
after: {
|
|
454
|
+
id: 'highprio',
|
|
455
|
+
description: 'High priority row'
|
|
456
|
+
},
|
|
457
|
+
afterReplicaId: 'highprio'
|
|
458
|
+
});
|
|
459
|
+
for (let i = 0; i < 2_000; i++) {
|
|
460
|
+
await writer.save({
|
|
461
|
+
sourceTable: testTable,
|
|
458
462
|
tag: storage.SaveOperationTag.INSERT,
|
|
459
463
|
after: {
|
|
460
|
-
id:
|
|
461
|
-
description: '
|
|
464
|
+
id: `${i}`,
|
|
465
|
+
description: 'low prio'
|
|
462
466
|
},
|
|
463
|
-
afterReplicaId:
|
|
467
|
+
afterReplicaId: `${i}`
|
|
464
468
|
});
|
|
465
|
-
|
|
466
|
-
await batch.save({
|
|
467
|
-
sourceTable: TEST_TABLE,
|
|
468
|
-
tag: storage.SaveOperationTag.INSERT,
|
|
469
|
-
after: {
|
|
470
|
-
id: `${i}`,
|
|
471
|
-
description: 'low prio'
|
|
472
|
-
},
|
|
473
|
-
afterReplicaId: `${i}`
|
|
474
|
-
});
|
|
475
|
-
}
|
|
469
|
+
}
|
|
476
470
|
|
|
477
|
-
|
|
478
|
-
});
|
|
471
|
+
await writer.commit('0/1');
|
|
479
472
|
|
|
480
473
|
const stream = sync.streamResponse({
|
|
481
474
|
syncContext,
|
|
@@ -512,31 +505,29 @@ bucket_definitions:
|
|
|
512
505
|
|
|
513
506
|
if (sentRows == 1001) {
|
|
514
507
|
// Save new data to interrupt the low-priority sync.
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
afterReplicaId: '2001'
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
await batch.commit('0/2');
|
|
508
|
+
// Add another high-priority row. This should interrupt the long-running low-priority sync.
|
|
509
|
+
await writer.save({
|
|
510
|
+
sourceTable: testTable,
|
|
511
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
512
|
+
after: {
|
|
513
|
+
id: 'highprio2',
|
|
514
|
+
description: 'Another high-priority row'
|
|
515
|
+
},
|
|
516
|
+
afterReplicaId: 'highprio2'
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
// Also add a low-priority row
|
|
520
|
+
await writer.save({
|
|
521
|
+
sourceTable: testTable,
|
|
522
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
523
|
+
after: {
|
|
524
|
+
id: '2001',
|
|
525
|
+
description: 'Another low-priority row'
|
|
526
|
+
},
|
|
527
|
+
afterReplicaId: '2001'
|
|
539
528
|
});
|
|
529
|
+
|
|
530
|
+
await writer.commit('0/2');
|
|
540
531
|
}
|
|
541
532
|
|
|
542
533
|
if (sentRows >= 1000 && sentRows <= 2001) {
|
|
@@ -579,20 +570,20 @@ bucket_definitions:
|
|
|
579
570
|
content: BASIC_SYNC_RULES
|
|
580
571
|
});
|
|
581
572
|
const bucketStorage = f.getInstance(syncRules);
|
|
582
|
-
|
|
583
|
-
await
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
await batch.commit('0/1');
|
|
573
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
574
|
+
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
575
|
+
|
|
576
|
+
await writer.markAllSnapshotDone('0/1');
|
|
577
|
+
await writer.save({
|
|
578
|
+
sourceTable: testTable,
|
|
579
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
580
|
+
after: {
|
|
581
|
+
id: 't1',
|
|
582
|
+
description: 'sync'
|
|
583
|
+
},
|
|
584
|
+
afterReplicaId: 't1'
|
|
595
585
|
});
|
|
586
|
+
await writer.commit('0/1');
|
|
596
587
|
|
|
597
588
|
const stream = sync.streamResponse({
|
|
598
589
|
syncContext,
|
|
@@ -623,9 +614,7 @@ bucket_definitions:
|
|
|
623
614
|
if (receivedCompletions == 1) {
|
|
624
615
|
// Trigger an empty bucket update.
|
|
625
616
|
await bucketStorage.createManagedWriteCheckpoint({ user_id: '', heads: { '1': '1/0' } });
|
|
626
|
-
await
|
|
627
|
-
await batch.commit('1/0');
|
|
628
|
-
});
|
|
617
|
+
await writer.commit('1/0');
|
|
629
618
|
} else {
|
|
630
619
|
break;
|
|
631
620
|
}
|
|
@@ -637,30 +626,30 @@ bucket_definitions:
|
|
|
637
626
|
});
|
|
638
627
|
|
|
639
628
|
test('sync legacy non-raw data', async () => {
|
|
640
|
-
|
|
629
|
+
await using f = await factory();
|
|
641
630
|
|
|
642
631
|
const syncRules = await updateSyncRules(f, {
|
|
643
632
|
content: BASIC_SYNC_RULES
|
|
644
633
|
});
|
|
645
634
|
|
|
646
635
|
const bucketStorage = await f.getInstance(syncRules);
|
|
647
|
-
|
|
648
|
-
const
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
await batch.commit('0/1');
|
|
636
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
637
|
+
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
638
|
+
|
|
639
|
+
await writer.markAllSnapshotDone('0/1');
|
|
640
|
+
await writer.save({
|
|
641
|
+
sourceTable: testTable,
|
|
642
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
643
|
+
after: {
|
|
644
|
+
id: 't1',
|
|
645
|
+
description: 'Test\n"string"',
|
|
646
|
+
large_num: 12345678901234567890n
|
|
647
|
+
},
|
|
648
|
+
afterReplicaId: 't1'
|
|
662
649
|
});
|
|
663
650
|
|
|
651
|
+
await writer.commit('0/1');
|
|
652
|
+
|
|
664
653
|
const stream = sync.streamResponse({
|
|
665
654
|
syncContext,
|
|
666
655
|
bucketStorage,
|
|
@@ -716,11 +705,11 @@ bucket_definitions:
|
|
|
716
705
|
});
|
|
717
706
|
|
|
718
707
|
const bucketStorage = await f.getInstance(syncRules);
|
|
708
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
709
|
+
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
719
710
|
// Activate
|
|
720
|
-
await
|
|
721
|
-
|
|
722
|
-
await batch.keepalive('0/0');
|
|
723
|
-
});
|
|
711
|
+
await writer.markAllSnapshotDone('0/0');
|
|
712
|
+
await writer.keepalive('0/0');
|
|
724
713
|
|
|
725
714
|
const stream = sync.streamResponse({
|
|
726
715
|
syncContext,
|
|
@@ -742,36 +731,32 @@ bucket_definitions:
|
|
|
742
731
|
|
|
743
732
|
expect(await getCheckpointLines(iter)).toMatchSnapshot();
|
|
744
733
|
|
|
745
|
-
await
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
afterReplicaId: 't1'
|
|
754
|
-
});
|
|
755
|
-
|
|
756
|
-
await batch.commit('0/1');
|
|
734
|
+
await writer.save({
|
|
735
|
+
sourceTable: testTable,
|
|
736
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
737
|
+
after: {
|
|
738
|
+
id: 't1',
|
|
739
|
+
description: 'Test 1'
|
|
740
|
+
},
|
|
741
|
+
afterReplicaId: 't1'
|
|
757
742
|
});
|
|
758
743
|
|
|
759
|
-
|
|
744
|
+
await writer.commit('0/1');
|
|
760
745
|
|
|
761
|
-
await
|
|
762
|
-
await batch.save({
|
|
763
|
-
sourceTable: TEST_TABLE,
|
|
764
|
-
tag: storage.SaveOperationTag.INSERT,
|
|
765
|
-
after: {
|
|
766
|
-
id: 't2',
|
|
767
|
-
description: 'Test 2'
|
|
768
|
-
},
|
|
769
|
-
afterReplicaId: 't2'
|
|
770
|
-
});
|
|
746
|
+
expect(await getCheckpointLines(iter)).toMatchSnapshot();
|
|
771
747
|
|
|
772
|
-
|
|
748
|
+
await writer.save({
|
|
749
|
+
sourceTable: testTable,
|
|
750
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
751
|
+
after: {
|
|
752
|
+
id: 't2',
|
|
753
|
+
description: 'Test 2'
|
|
754
|
+
},
|
|
755
|
+
afterReplicaId: 't2'
|
|
773
756
|
});
|
|
774
757
|
|
|
758
|
+
await writer.commit('0/2');
|
|
759
|
+
|
|
775
760
|
expect(await getCheckpointLines(iter)).toMatchSnapshot();
|
|
776
761
|
});
|
|
777
762
|
|
|
@@ -787,15 +772,13 @@ bucket_definitions:
|
|
|
787
772
|
`
|
|
788
773
|
});
|
|
789
774
|
|
|
790
|
-
const usersTable = test_utils.makeTestTable('users', ['id'], config);
|
|
791
|
-
const listsTable = test_utils.makeTestTable('lists', ['id'], config);
|
|
792
|
-
|
|
793
775
|
const bucketStorage = await f.getInstance(syncRules);
|
|
776
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
777
|
+
const usersTable = await test_utils.resolveTestTable(writer, 'users', ['id'], config, 1);
|
|
778
|
+
|
|
794
779
|
// Activate
|
|
795
|
-
await
|
|
796
|
-
|
|
797
|
-
await batch.keepalive('0/0');
|
|
798
|
-
});
|
|
780
|
+
await writer.markAllSnapshotDone('0/0');
|
|
781
|
+
await writer.keepalive('0/0');
|
|
799
782
|
|
|
800
783
|
const stream = sync.streamResponse({
|
|
801
784
|
syncContext,
|
|
@@ -821,22 +804,21 @@ bucket_definitions:
|
|
|
821
804
|
expect(checkpoint1).toMatchSnapshot();
|
|
822
805
|
|
|
823
806
|
// Add user
|
|
824
|
-
await
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
afterReplicaId: 'user1'
|
|
833
|
-
});
|
|
834
|
-
|
|
835
|
-
await batch.commit('0/1');
|
|
807
|
+
await writer.save({
|
|
808
|
+
sourceTable: usersTable,
|
|
809
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
810
|
+
after: {
|
|
811
|
+
id: 'user1',
|
|
812
|
+
name: 'User 1'
|
|
813
|
+
},
|
|
814
|
+
afterReplicaId: 'user1'
|
|
836
815
|
});
|
|
837
816
|
|
|
838
|
-
|
|
817
|
+
await writer.commit('0/1');
|
|
818
|
+
|
|
839
819
|
const checkpoint2 = await getCheckpointLines(iter);
|
|
820
|
+
|
|
821
|
+
const { bucket } = test_utils.bucketRequest(syncRules, 'by_user["user1"]');
|
|
840
822
|
expect(
|
|
841
823
|
(checkpoint2[0] as StreamingSyncCheckpointDiff).checkpoint_diff?.updated_buckets?.map((b) => b.bucket)
|
|
842
824
|
).toEqual([bucket]);
|
|
@@ -855,26 +837,24 @@ bucket_definitions:
|
|
|
855
837
|
`
|
|
856
838
|
});
|
|
857
839
|
|
|
858
|
-
const usersTable = test_utils.makeTestTable('users', ['id'], config);
|
|
859
|
-
const listsTable = test_utils.makeTestTable('lists', ['id'], config);
|
|
860
|
-
|
|
861
840
|
const bucketStorage = await f.getInstance(syncRules);
|
|
862
|
-
|
|
863
|
-
await
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
await batch.commit('0/1');
|
|
841
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
842
|
+
const usersTable = await test_utils.resolveTestTable(writer, 'users', ['id'], config, 1);
|
|
843
|
+
const listsTable = await test_utils.resolveTestTable(writer, 'lists', ['id'], config, 2);
|
|
844
|
+
|
|
845
|
+
await writer.markAllSnapshotDone('0/1');
|
|
846
|
+
await writer.save({
|
|
847
|
+
sourceTable: usersTable,
|
|
848
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
849
|
+
after: {
|
|
850
|
+
id: 'user1',
|
|
851
|
+
name: 'User 1'
|
|
852
|
+
},
|
|
853
|
+
afterReplicaId: 'user1'
|
|
876
854
|
});
|
|
877
855
|
|
|
856
|
+
await writer.commit('0/1');
|
|
857
|
+
|
|
878
858
|
const stream = sync.streamResponse({
|
|
879
859
|
syncContext,
|
|
880
860
|
bucketStorage,
|
|
@@ -895,24 +875,23 @@ bucket_definitions:
|
|
|
895
875
|
|
|
896
876
|
const { bucket } = bucketRequest(syncRules, 'by_user["user1"]');
|
|
897
877
|
const checkpoint1 = await getCheckpointLines(iter);
|
|
878
|
+
|
|
898
879
|
expect((checkpoint1[0] as StreamingSyncCheckpoint).checkpoint?.buckets?.map((b) => b.bucket)).toEqual([bucket]);
|
|
899
880
|
expect(checkpoint1).toMatchSnapshot();
|
|
900
881
|
|
|
901
|
-
await
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
afterReplicaId: 'list1'
|
|
911
|
-
});
|
|
912
|
-
|
|
913
|
-
await batch.commit('0/1');
|
|
882
|
+
await writer.save({
|
|
883
|
+
sourceTable: listsTable,
|
|
884
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
885
|
+
after: {
|
|
886
|
+
id: 'list1',
|
|
887
|
+
user_id: 'user1',
|
|
888
|
+
name: 'User 1'
|
|
889
|
+
},
|
|
890
|
+
afterReplicaId: 'list1'
|
|
914
891
|
});
|
|
915
892
|
|
|
893
|
+
await writer.commit('0/1');
|
|
894
|
+
|
|
916
895
|
const checkpoint2 = await getCheckpointLines(iter);
|
|
917
896
|
expect(
|
|
918
897
|
(checkpoint2[0] as StreamingSyncCheckpointDiff).checkpoint_diff?.updated_buckets?.map((b) => b.bucket)
|
|
@@ -932,15 +911,13 @@ bucket_definitions:
|
|
|
932
911
|
`
|
|
933
912
|
});
|
|
934
913
|
|
|
935
|
-
const usersTable = test_utils.makeTestTable('users', ['id'], config);
|
|
936
|
-
const listsTable = test_utils.makeTestTable('lists', ['id'], config);
|
|
937
|
-
|
|
938
914
|
const bucketStorage = await f.getInstance(syncRules);
|
|
915
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
916
|
+
const usersTable = await test_utils.resolveTestTable(writer, 'users', ['id'], config, 1);
|
|
917
|
+
const listsTable = await test_utils.resolveTestTable(writer, 'lists', ['id'], config, 2);
|
|
939
918
|
// Activate
|
|
940
|
-
await
|
|
941
|
-
|
|
942
|
-
await batch.keepalive('0/0');
|
|
943
|
-
});
|
|
919
|
+
await writer.markAllSnapshotDone('0/0');
|
|
920
|
+
await writer.keepalive('0/0');
|
|
944
921
|
|
|
945
922
|
const stream = sync.streamResponse({
|
|
946
923
|
syncContext,
|
|
@@ -963,33 +940,32 @@ bucket_definitions:
|
|
|
963
940
|
// Initial empty checkpoint
|
|
964
941
|
expect(await getCheckpointLines(iter)).toMatchSnapshot();
|
|
965
942
|
|
|
966
|
-
await
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
});
|
|
978
|
-
|
|
979
|
-
await batch.save({
|
|
980
|
-
sourceTable: usersTable,
|
|
981
|
-
tag: storage.SaveOperationTag.INSERT,
|
|
982
|
-
after: {
|
|
983
|
-
id: 'user1',
|
|
984
|
-
name: 'User 1'
|
|
985
|
-
},
|
|
986
|
-
afterReplicaId: 'user1'
|
|
987
|
-
});
|
|
943
|
+
await writer.markAllSnapshotDone('0/1');
|
|
944
|
+
await writer.save({
|
|
945
|
+
sourceTable: listsTable,
|
|
946
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
947
|
+
after: {
|
|
948
|
+
id: 'list1',
|
|
949
|
+
user_id: 'user1',
|
|
950
|
+
name: 'User 1'
|
|
951
|
+
},
|
|
952
|
+
afterReplicaId: 'list1'
|
|
953
|
+
});
|
|
988
954
|
|
|
989
|
-
|
|
955
|
+
await writer.save({
|
|
956
|
+
sourceTable: usersTable,
|
|
957
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
958
|
+
after: {
|
|
959
|
+
id: 'user1',
|
|
960
|
+
name: 'User 1'
|
|
961
|
+
},
|
|
962
|
+
afterReplicaId: 'user1'
|
|
990
963
|
});
|
|
991
964
|
|
|
992
|
-
|
|
965
|
+
await writer.commit('0/1');
|
|
966
|
+
|
|
967
|
+
const { bucket } = test_utils.bucketRequest(syncRules, 'by_user["user1"]');
|
|
968
|
+
|
|
993
969
|
const checkpoint2 = await getCheckpointLines(iter);
|
|
994
970
|
expect(
|
|
995
971
|
(checkpoint2[0] as StreamingSyncCheckpointDiff).checkpoint_diff?.updated_buckets?.map((b) => b.bucket)
|
|
@@ -1005,11 +981,10 @@ bucket_definitions:
|
|
|
1005
981
|
});
|
|
1006
982
|
|
|
1007
983
|
const bucketStorage = await f.getInstance(syncRules);
|
|
984
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1008
985
|
// Activate
|
|
1009
|
-
await
|
|
1010
|
-
|
|
1011
|
-
await batch.keepalive('0/0');
|
|
1012
|
-
});
|
|
986
|
+
await writer.markAllSnapshotDone('0/0');
|
|
987
|
+
await writer.keepalive('0/0');
|
|
1013
988
|
|
|
1014
989
|
const exp = Date.now() / 1000 + 0.1;
|
|
1015
990
|
|
|
@@ -1051,32 +1026,32 @@ bucket_definitions:
|
|
|
1051
1026
|
});
|
|
1052
1027
|
|
|
1053
1028
|
const bucketStorage = await f.getInstance(syncRules);
|
|
1029
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1030
|
+
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
1031
|
+
|
|
1032
|
+
await writer.markAllSnapshotDone('0/1');
|
|
1033
|
+
await writer.save({
|
|
1034
|
+
sourceTable: testTable,
|
|
1035
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
1036
|
+
after: {
|
|
1037
|
+
id: 't1',
|
|
1038
|
+
description: 'Test 1'
|
|
1039
|
+
},
|
|
1040
|
+
afterReplicaId: 't1'
|
|
1041
|
+
});
|
|
1054
1042
|
|
|
1055
|
-
await
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
},
|
|
1064
|
-
afterReplicaId: 't1'
|
|
1065
|
-
});
|
|
1066
|
-
|
|
1067
|
-
await batch.save({
|
|
1068
|
-
sourceTable: TEST_TABLE,
|
|
1069
|
-
tag: storage.SaveOperationTag.INSERT,
|
|
1070
|
-
after: {
|
|
1071
|
-
id: 't2',
|
|
1072
|
-
description: 'Test 2'
|
|
1073
|
-
},
|
|
1074
|
-
afterReplicaId: 't2'
|
|
1075
|
-
});
|
|
1076
|
-
|
|
1077
|
-
await batch.commit('0/1');
|
|
1043
|
+
await writer.save({
|
|
1044
|
+
sourceTable: testTable,
|
|
1045
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
1046
|
+
after: {
|
|
1047
|
+
id: 't2',
|
|
1048
|
+
description: 'Test 2'
|
|
1049
|
+
},
|
|
1050
|
+
afterReplicaId: 't2'
|
|
1078
1051
|
});
|
|
1079
1052
|
|
|
1053
|
+
await writer.commit('0/1');
|
|
1054
|
+
|
|
1080
1055
|
const stream = sync.streamResponse({
|
|
1081
1056
|
syncContext,
|
|
1082
1057
|
bucketStorage,
|
|
@@ -1108,31 +1083,29 @@ bucket_definitions:
|
|
|
1108
1083
|
// Now we save additional data AND compact before continuing.
|
|
1109
1084
|
// This invalidates the checkpoint we've received above.
|
|
1110
1085
|
|
|
1111
|
-
await
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
});
|
|
1122
|
-
|
|
1123
|
-
await batch.save({
|
|
1124
|
-
sourceTable: TEST_TABLE,
|
|
1125
|
-
tag: storage.SaveOperationTag.UPDATE,
|
|
1126
|
-
after: {
|
|
1127
|
-
id: 't2',
|
|
1128
|
-
description: 'Test 2b'
|
|
1129
|
-
},
|
|
1130
|
-
afterReplicaId: 't2'
|
|
1131
|
-
});
|
|
1086
|
+
await writer.markAllSnapshotDone('0/1');
|
|
1087
|
+
await writer.save({
|
|
1088
|
+
sourceTable: testTable,
|
|
1089
|
+
tag: storage.SaveOperationTag.UPDATE,
|
|
1090
|
+
after: {
|
|
1091
|
+
id: 't1',
|
|
1092
|
+
description: 'Test 1b'
|
|
1093
|
+
},
|
|
1094
|
+
afterReplicaId: 't1'
|
|
1095
|
+
});
|
|
1132
1096
|
|
|
1133
|
-
|
|
1097
|
+
await writer.save({
|
|
1098
|
+
sourceTable: testTable,
|
|
1099
|
+
tag: storage.SaveOperationTag.UPDATE,
|
|
1100
|
+
after: {
|
|
1101
|
+
id: 't2',
|
|
1102
|
+
description: 'Test 2b'
|
|
1103
|
+
},
|
|
1104
|
+
afterReplicaId: 't2'
|
|
1134
1105
|
});
|
|
1135
1106
|
|
|
1107
|
+
await writer.commit('0/2');
|
|
1108
|
+
|
|
1136
1109
|
await bucketStorage.compact({
|
|
1137
1110
|
minBucketChanges: 1,
|
|
1138
1111
|
minChangeRatio: 0
|
|
@@ -1196,12 +1169,11 @@ bucket_definitions:
|
|
|
1196
1169
|
});
|
|
1197
1170
|
|
|
1198
1171
|
const bucketStorage = f.getInstance(syncRules);
|
|
1172
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1199
1173
|
|
|
1200
|
-
await
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
await batch.commit('0/1');
|
|
1204
|
-
});
|
|
1174
|
+
await writer.markAllSnapshotDone('0/1');
|
|
1175
|
+
// <= the managed write checkpoint LSN below
|
|
1176
|
+
await writer.commit('0/1');
|
|
1205
1177
|
|
|
1206
1178
|
const checkpoint = await bucketStorage.createManagedWriteCheckpoint({
|
|
1207
1179
|
user_id: 'test',
|
|
@@ -1233,11 +1205,9 @@ bucket_definitions:
|
|
|
1233
1205
|
})
|
|
1234
1206
|
});
|
|
1235
1207
|
|
|
1236
|
-
await
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
await batch.commit('1/0');
|
|
1240
|
-
});
|
|
1208
|
+
await writer.markAllSnapshotDone('0/1');
|
|
1209
|
+
// must be >= the managed write checkpoint LSN
|
|
1210
|
+
await writer.commit('1/0');
|
|
1241
1211
|
|
|
1242
1212
|
// At this point the LSN has advanced, so the write checkpoint should be
|
|
1243
1213
|
// included in the next checkpoint message.
|
|
@@ -1251,9 +1221,12 @@ bucket_definitions:
|
|
|
1251
1221
|
});
|
|
1252
1222
|
});
|
|
1253
1223
|
|
|
1254
|
-
test('encodes sync rules id in
|
|
1224
|
+
test('encodes sync rules id in buckets for streams', async () => {
|
|
1255
1225
|
await using f = await factory();
|
|
1256
|
-
|
|
1226
|
+
// This test relies making an actual update to sync rules to test the different bucket names.
|
|
1227
|
+
// The actual naming scheme may change, as long as the two buckets have different names.
|
|
1228
|
+
const rules = [
|
|
1229
|
+
`
|
|
1257
1230
|
streams:
|
|
1258
1231
|
test:
|
|
1259
1232
|
auto_subscribe: true
|
|
@@ -1261,27 +1234,38 @@ streams:
|
|
|
1261
1234
|
|
|
1262
1235
|
config:
|
|
1263
1236
|
edition: 2
|
|
1264
|
-
|
|
1237
|
+
`,
|
|
1238
|
+
`
|
|
1239
|
+
streams:
|
|
1240
|
+
test2:
|
|
1241
|
+
auto_subscribe: true
|
|
1242
|
+
query: SELECT * FROM test WHERE 1;
|
|
1243
|
+
|
|
1244
|
+
config:
|
|
1245
|
+
edition: 2
|
|
1246
|
+
`
|
|
1247
|
+
];
|
|
1265
1248
|
|
|
1266
1249
|
for (let i = 0; i < 2; i++) {
|
|
1267
1250
|
const syncRules = await updateSyncRules(f, {
|
|
1268
|
-
content: rules
|
|
1251
|
+
content: rules[i]
|
|
1269
1252
|
});
|
|
1270
1253
|
const bucketStorage = f.getInstance(syncRules);
|
|
1254
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1255
|
+
|
|
1256
|
+
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config, i + 1);
|
|
1271
1257
|
|
|
1272
|
-
await
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
afterReplicaId: 't1'
|
|
1282
|
-
});
|
|
1283
|
-
await batch.commit('0/1');
|
|
1258
|
+
await writer.markAllSnapshotDone('0/1');
|
|
1259
|
+
await writer.save({
|
|
1260
|
+
sourceTable: testTable,
|
|
1261
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
1262
|
+
after: {
|
|
1263
|
+
id: 't1',
|
|
1264
|
+
description: 'Test 1'
|
|
1265
|
+
},
|
|
1266
|
+
afterReplicaId: 't1'
|
|
1284
1267
|
});
|
|
1268
|
+
await writer.commit('0/1');
|
|
1285
1269
|
|
|
1286
1270
|
const stream = sync.streamResponse({
|
|
1287
1271
|
syncContext,
|