@powersync/service-core 1.14.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/LICENSE +3 -3
- package/dist/api/api-metrics.js +5 -0
- package/dist/api/api-metrics.js.map +1 -1
- package/dist/api/diagnostics.js +1 -1
- package/dist/api/diagnostics.js.map +1 -1
- package/dist/metrics/open-telemetry/util.d.ts +0 -3
- package/dist/metrics/open-telemetry/util.js +18 -13
- package/dist/metrics/open-telemetry/util.js.map +1 -1
- package/dist/routes/compression.d.ts +19 -0
- package/dist/routes/compression.js +70 -0
- package/dist/routes/compression.js.map +1 -0
- package/dist/routes/configure-fastify.d.ts +40 -5
- package/dist/routes/endpoints/socket-route.js +24 -9
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/endpoints/sync-rules.js +1 -27
- package/dist/routes/endpoints/sync-rules.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.d.ts +80 -10
- package/dist/routes/endpoints/sync-stream.js +17 -12
- package/dist/routes/endpoints/sync-stream.js.map +1 -1
- package/dist/storage/BucketStorage.d.ts +1 -1
- package/dist/storage/BucketStorage.js.map +1 -1
- package/dist/storage/BucketStorageBatch.d.ts +4 -4
- package/dist/storage/BucketStorageBatch.js.map +1 -1
- package/dist/storage/ChecksumCache.d.ts +4 -19
- package/dist/storage/ChecksumCache.js +4 -0
- package/dist/storage/ChecksumCache.js.map +1 -1
- package/dist/storage/ReplicationEventPayload.d.ts +2 -2
- package/dist/storage/SyncRulesBucketStorage.d.ts +9 -0
- package/dist/storage/SyncRulesBucketStorage.js.map +1 -1
- package/dist/sync/BucketChecksumState.d.ts +40 -10
- package/dist/sync/BucketChecksumState.js +154 -18
- package/dist/sync/BucketChecksumState.js.map +1 -1
- package/dist/sync/RequestTracker.d.ts +7 -1
- package/dist/sync/RequestTracker.js +22 -2
- package/dist/sync/RequestTracker.js.map +1 -1
- package/dist/sync/sync.d.ts +3 -3
- package/dist/sync/sync.js +23 -42
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/util.js +1 -1
- package/dist/sync/util.js.map +1 -1
- package/dist/util/protocol-types.d.ts +153 -9
- package/dist/util/protocol-types.js +41 -6
- package/dist/util/protocol-types.js.map +1 -1
- package/dist/util/utils.d.ts +18 -3
- package/dist/util/utils.js +33 -9
- package/dist/util/utils.js.map +1 -1
- package/package.json +14 -14
- package/src/api/api-metrics.ts +6 -0
- package/src/api/diagnostics.ts +1 -1
- package/src/metrics/open-telemetry/util.ts +22 -21
- package/src/routes/compression.ts +75 -0
- package/src/routes/endpoints/socket-route.ts +24 -9
- package/src/routes/endpoints/sync-rules.ts +1 -28
- package/src/routes/endpoints/sync-stream.ts +18 -15
- package/src/storage/BucketStorage.ts +2 -2
- package/src/storage/BucketStorageBatch.ts +10 -4
- package/src/storage/ChecksumCache.ts +8 -22
- package/src/storage/ReplicationEventPayload.ts +2 -2
- package/src/storage/SyncRulesBucketStorage.ts +12 -0
- package/src/sync/BucketChecksumState.ts +192 -29
- package/src/sync/RequestTracker.ts +27 -2
- package/src/sync/sync.ts +53 -51
- package/src/sync/util.ts +1 -1
- package/src/util/protocol-types.ts +138 -10
- package/src/util/utils.ts +59 -12
- package/test/src/checksum_cache.test.ts +6 -8
- package/test/src/routes/mocks.ts +59 -0
- package/test/src/routes/stream.test.ts +84 -0
- package/test/src/sync/BucketChecksumState.test.ts +340 -42
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BucketChecksum,
|
|
3
3
|
BucketChecksumState,
|
|
4
|
+
BucketChecksumStateOptions,
|
|
4
5
|
BucketChecksumStateStorage,
|
|
5
6
|
CHECKPOINT_INVALIDATE_ALL,
|
|
6
7
|
ChecksumMap,
|
|
7
8
|
InternalOpId,
|
|
8
9
|
ReplicationCheckpoint,
|
|
10
|
+
StreamingSyncRequest,
|
|
9
11
|
SyncContext,
|
|
10
12
|
WatchFilterEvent
|
|
11
13
|
} from '@/index.js';
|
|
12
14
|
import { JSONBig } from '@powersync/service-jsonbig';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
+
import {
|
|
16
|
+
SqliteJsonRow,
|
|
17
|
+
ParameterLookup,
|
|
18
|
+
SqlSyncRules,
|
|
19
|
+
RequestJwtPayload,
|
|
20
|
+
BucketSource
|
|
21
|
+
} from '@powersync/service-sync-rules';
|
|
22
|
+
import { describe, expect, test, beforeEach } from 'vitest';
|
|
15
23
|
|
|
16
24
|
describe('BucketChecksumState', () => {
|
|
17
25
|
// Single global[] bucket.
|
|
@@ -55,6 +63,9 @@ bucket_definitions:
|
|
|
55
63
|
maxDataFetchConcurrency: 10
|
|
56
64
|
});
|
|
57
65
|
|
|
66
|
+
const syncRequest: StreamingSyncRequest = {};
|
|
67
|
+
const tokenPayload: RequestJwtPayload = { sub: '' };
|
|
68
|
+
|
|
58
69
|
test('global bucket with update', async () => {
|
|
59
70
|
const storage = new MockBucketChecksumStateStorage();
|
|
60
71
|
// Set intial state
|
|
@@ -62,8 +73,12 @@ bucket_definitions:
|
|
|
62
73
|
|
|
63
74
|
const state = new BucketChecksumState({
|
|
64
75
|
syncContext,
|
|
65
|
-
|
|
66
|
-
|
|
76
|
+
syncRequest,
|
|
77
|
+
tokenPayload,
|
|
78
|
+
syncRules: {
|
|
79
|
+
syncRules: SYNC_RULES_GLOBAL,
|
|
80
|
+
version: 1
|
|
81
|
+
},
|
|
67
82
|
bucketStorage: storage
|
|
68
83
|
});
|
|
69
84
|
|
|
@@ -75,9 +90,10 @@ bucket_definitions:
|
|
|
75
90
|
line.advance();
|
|
76
91
|
expect(line.checkpointLine).toEqual({
|
|
77
92
|
checkpoint: {
|
|
78
|
-
buckets: [{ bucket: 'global[]', checksum: 1, count: 1, priority: 3 }],
|
|
93
|
+
buckets: [{ bucket: 'global[]', checksum: 1, count: 1, priority: 3, subscriptions: [{ default: 0 }] }],
|
|
79
94
|
last_op_id: '1',
|
|
80
|
-
write_checkpoint: undefined
|
|
95
|
+
write_checkpoint: undefined,
|
|
96
|
+
streams: [{ name: 'global', is_default: true, errors: [] }]
|
|
81
97
|
}
|
|
82
98
|
});
|
|
83
99
|
expect(line.bucketsToFetch).toEqual([
|
|
@@ -111,7 +127,7 @@ bucket_definitions:
|
|
|
111
127
|
expect(line2.checkpointLine).toEqual({
|
|
112
128
|
checkpoint_diff: {
|
|
113
129
|
removed_buckets: [],
|
|
114
|
-
updated_buckets: [{ bucket: 'global[]', checksum: 2, count: 2, priority: 3 }],
|
|
130
|
+
updated_buckets: [{ bucket: 'global[]', checksum: 2, count: 2, priority: 3, subscriptions: [{ default: 0 }] }],
|
|
115
131
|
last_op_id: '2',
|
|
116
132
|
write_checkpoint: undefined
|
|
117
133
|
}
|
|
@@ -129,10 +145,13 @@ bucket_definitions:
|
|
|
129
145
|
|
|
130
146
|
const state = new BucketChecksumState({
|
|
131
147
|
syncContext,
|
|
148
|
+
tokenPayload,
|
|
132
149
|
// Client sets the initial state here
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
150
|
+
syncRequest: { buckets: [{ name: 'global[]', after: '1' }] },
|
|
151
|
+
syncRules: {
|
|
152
|
+
syncRules: SYNC_RULES_GLOBAL,
|
|
153
|
+
version: 1
|
|
154
|
+
},
|
|
136
155
|
bucketStorage: storage
|
|
137
156
|
});
|
|
138
157
|
|
|
@@ -144,9 +163,10 @@ bucket_definitions:
|
|
|
144
163
|
line.advance();
|
|
145
164
|
expect(line.checkpointLine).toEqual({
|
|
146
165
|
checkpoint: {
|
|
147
|
-
buckets: [{ bucket: 'global[]', checksum: 1, count: 1, priority: 3 }],
|
|
166
|
+
buckets: [{ bucket: 'global[]', checksum: 1, count: 1, priority: 3, subscriptions: [{ default: 0 }] }],
|
|
148
167
|
last_op_id: '1',
|
|
149
|
-
write_checkpoint: undefined
|
|
168
|
+
write_checkpoint: undefined,
|
|
169
|
+
streams: [{ name: 'global', is_default: true, errors: [] }]
|
|
150
170
|
}
|
|
151
171
|
});
|
|
152
172
|
expect(line.bucketsToFetch).toEqual([
|
|
@@ -167,8 +187,12 @@ bucket_definitions:
|
|
|
167
187
|
|
|
168
188
|
const state = new BucketChecksumState({
|
|
169
189
|
syncContext,
|
|
170
|
-
|
|
171
|
-
|
|
190
|
+
tokenPayload,
|
|
191
|
+
syncRequest,
|
|
192
|
+
syncRules: {
|
|
193
|
+
syncRules: SYNC_RULES_GLOBAL_TWO,
|
|
194
|
+
version: 2
|
|
195
|
+
},
|
|
172
196
|
bucketStorage: storage
|
|
173
197
|
});
|
|
174
198
|
|
|
@@ -180,11 +204,12 @@ bucket_definitions:
|
|
|
180
204
|
expect(line.checkpointLine).toEqual({
|
|
181
205
|
checkpoint: {
|
|
182
206
|
buckets: [
|
|
183
|
-
{ bucket: 'global[1]', checksum: 1, count: 1, priority: 3 },
|
|
184
|
-
{ bucket: 'global[2]', checksum: 1, count: 1, priority: 3 }
|
|
207
|
+
{ bucket: 'global[1]', checksum: 1, count: 1, priority: 3, subscriptions: [{ default: 0 }] },
|
|
208
|
+
{ bucket: 'global[2]', checksum: 1, count: 1, priority: 3, subscriptions: [{ default: 0 }] }
|
|
185
209
|
],
|
|
186
210
|
last_op_id: '1',
|
|
187
|
-
write_checkpoint: undefined
|
|
211
|
+
write_checkpoint: undefined,
|
|
212
|
+
streams: [{ name: 'global', is_default: true, errors: [] }]
|
|
188
213
|
}
|
|
189
214
|
});
|
|
190
215
|
expect(line.bucketsToFetch).toEqual([
|
|
@@ -215,8 +240,8 @@ bucket_definitions:
|
|
|
215
240
|
checkpoint_diff: {
|
|
216
241
|
removed_buckets: [],
|
|
217
242
|
updated_buckets: [
|
|
218
|
-
{ bucket: 'global[1]', checksum: 2, count: 2, priority: 3 },
|
|
219
|
-
{ bucket: 'global[2]', checksum: 2, count: 2, priority: 3 }
|
|
243
|
+
{ bucket: 'global[1]', checksum: 2, count: 2, priority: 3, subscriptions: [{ default: 0 }] },
|
|
244
|
+
{ bucket: 'global[2]', checksum: 2, count: 2, priority: 3, subscriptions: [{ default: 0 }] }
|
|
220
245
|
],
|
|
221
246
|
last_op_id: '2',
|
|
222
247
|
write_checkpoint: undefined
|
|
@@ -232,10 +257,13 @@ bucket_definitions:
|
|
|
232
257
|
|
|
233
258
|
const state = new BucketChecksumState({
|
|
234
259
|
syncContext,
|
|
260
|
+
tokenPayload,
|
|
235
261
|
// Client sets the initial state here
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
262
|
+
syncRequest: { buckets: [{ name: 'something_here[]', after: '1' }] },
|
|
263
|
+
syncRules: {
|
|
264
|
+
syncRules: SYNC_RULES_GLOBAL,
|
|
265
|
+
version: 1
|
|
266
|
+
},
|
|
239
267
|
bucketStorage: storage
|
|
240
268
|
});
|
|
241
269
|
|
|
@@ -249,9 +277,10 @@ bucket_definitions:
|
|
|
249
277
|
line.advance();
|
|
250
278
|
expect(line.checkpointLine).toEqual({
|
|
251
279
|
checkpoint: {
|
|
252
|
-
buckets: [{ bucket: 'global[]', checksum: 1, count: 1, priority: 3 }],
|
|
280
|
+
buckets: [{ bucket: 'global[]', checksum: 1, count: 1, priority: 3, subscriptions: [{ default: 0 }] }],
|
|
253
281
|
last_op_id: '1',
|
|
254
|
-
write_checkpoint: undefined
|
|
282
|
+
write_checkpoint: undefined,
|
|
283
|
+
streams: [{ name: 'global', is_default: true, errors: [] }]
|
|
255
284
|
}
|
|
256
285
|
});
|
|
257
286
|
expect(line.bucketsToFetch).toEqual([
|
|
@@ -273,8 +302,12 @@ bucket_definitions:
|
|
|
273
302
|
|
|
274
303
|
const state = new BucketChecksumState({
|
|
275
304
|
syncContext,
|
|
276
|
-
|
|
277
|
-
|
|
305
|
+
tokenPayload,
|
|
306
|
+
syncRequest,
|
|
307
|
+
syncRules: {
|
|
308
|
+
syncRules: SYNC_RULES_GLOBAL_TWO,
|
|
309
|
+
version: 1
|
|
310
|
+
},
|
|
278
311
|
bucketStorage: storage
|
|
279
312
|
});
|
|
280
313
|
|
|
@@ -310,7 +343,7 @@ bucket_definitions:
|
|
|
310
343
|
removed_buckets: [],
|
|
311
344
|
updated_buckets: [
|
|
312
345
|
// This does not include global[2], since it was not invalidated.
|
|
313
|
-
{ bucket: 'global[1]', checksum: 2, count: 2, priority: 3 }
|
|
346
|
+
{ bucket: 'global[1]', checksum: 2, count: 2, priority: 3, subscriptions: [{ default: 0 }] }
|
|
314
347
|
],
|
|
315
348
|
last_op_id: '2',
|
|
316
349
|
write_checkpoint: undefined
|
|
@@ -325,8 +358,12 @@ bucket_definitions:
|
|
|
325
358
|
|
|
326
359
|
const state = new BucketChecksumState({
|
|
327
360
|
syncContext,
|
|
328
|
-
|
|
329
|
-
|
|
361
|
+
tokenPayload,
|
|
362
|
+
syncRequest,
|
|
363
|
+
syncRules: {
|
|
364
|
+
syncRules: SYNC_RULES_GLOBAL_TWO,
|
|
365
|
+
version: 2
|
|
366
|
+
},
|
|
330
367
|
bucketStorage: storage
|
|
331
368
|
});
|
|
332
369
|
|
|
@@ -358,8 +395,8 @@ bucket_definitions:
|
|
|
358
395
|
checkpoint_diff: {
|
|
359
396
|
removed_buckets: [],
|
|
360
397
|
updated_buckets: [
|
|
361
|
-
{ bucket: 'global[1]', checksum: 2, count: 2, priority: 3 },
|
|
362
|
-
{ bucket: 'global[2]', checksum: 2, count: 2, priority: 3 }
|
|
398
|
+
{ bucket: 'global[1]', checksum: 2, count: 2, priority: 3, subscriptions: [{ default: 0 }] },
|
|
399
|
+
{ bucket: 'global[2]', checksum: 2, count: 2, priority: 3, subscriptions: [{ default: 0 }] }
|
|
363
400
|
],
|
|
364
401
|
last_op_id: '2',
|
|
365
402
|
write_checkpoint: undefined
|
|
@@ -379,8 +416,12 @@ bucket_definitions:
|
|
|
379
416
|
|
|
380
417
|
const state = new BucketChecksumState({
|
|
381
418
|
syncContext,
|
|
382
|
-
|
|
383
|
-
|
|
419
|
+
tokenPayload,
|
|
420
|
+
syncRequest,
|
|
421
|
+
syncRules: {
|
|
422
|
+
syncRules: SYNC_RULES_GLOBAL_TWO,
|
|
423
|
+
version: 2
|
|
424
|
+
},
|
|
384
425
|
bucketStorage: storage
|
|
385
426
|
});
|
|
386
427
|
|
|
@@ -393,11 +434,12 @@ bucket_definitions:
|
|
|
393
434
|
expect(line.checkpointLine).toEqual({
|
|
394
435
|
checkpoint: {
|
|
395
436
|
buckets: [
|
|
396
|
-
{ bucket: 'global[1]', checksum: 3, count: 3, priority: 3 },
|
|
397
|
-
{ bucket: 'global[2]', checksum: 3, count: 3, priority: 3 }
|
|
437
|
+
{ bucket: 'global[1]', checksum: 3, count: 3, priority: 3, subscriptions: [{ default: 0 }] },
|
|
438
|
+
{ bucket: 'global[2]', checksum: 3, count: 3, priority: 3, subscriptions: [{ default: 0 }] }
|
|
398
439
|
],
|
|
399
440
|
last_op_id: '3',
|
|
400
|
-
write_checkpoint: undefined
|
|
441
|
+
write_checkpoint: undefined,
|
|
442
|
+
streams: [{ name: 'global', is_default: true, errors: [] }]
|
|
401
443
|
}
|
|
402
444
|
});
|
|
403
445
|
expect(line.bucketsToFetch).toEqual([
|
|
@@ -444,7 +486,8 @@ bucket_definitions:
|
|
|
444
486
|
bucket: 'global[1]',
|
|
445
487
|
checksum: 4,
|
|
446
488
|
count: 4,
|
|
447
|
-
priority: 3
|
|
489
|
+
priority: 3,
|
|
490
|
+
subscriptions: [{ default: 0 }]
|
|
448
491
|
}
|
|
449
492
|
],
|
|
450
493
|
last_op_id: '4',
|
|
@@ -480,8 +523,12 @@ bucket_definitions:
|
|
|
480
523
|
|
|
481
524
|
const state = new BucketChecksumState({
|
|
482
525
|
syncContext,
|
|
483
|
-
|
|
484
|
-
|
|
526
|
+
tokenPayload: { sub: 'u1' },
|
|
527
|
+
syncRequest,
|
|
528
|
+
syncRules: {
|
|
529
|
+
syncRules: SYNC_RULES_DYNAMIC,
|
|
530
|
+
version: 1
|
|
531
|
+
},
|
|
485
532
|
bucketStorage: storage
|
|
486
533
|
});
|
|
487
534
|
|
|
@@ -496,10 +543,29 @@ bucket_definitions:
|
|
|
496
543
|
expect(line.checkpointLine).toEqual({
|
|
497
544
|
checkpoint: {
|
|
498
545
|
buckets: [
|
|
499
|
-
{
|
|
500
|
-
|
|
546
|
+
{
|
|
547
|
+
bucket: 'by_project[1]',
|
|
548
|
+
checksum: 1,
|
|
549
|
+
count: 1,
|
|
550
|
+
priority: 3,
|
|
551
|
+
subscriptions: [{ default: 0 }]
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
bucket: 'by_project[2]',
|
|
555
|
+
checksum: 1,
|
|
556
|
+
count: 1,
|
|
557
|
+
priority: 3,
|
|
558
|
+
subscriptions: [{ default: 0 }]
|
|
559
|
+
}
|
|
501
560
|
],
|
|
502
561
|
last_op_id: '1',
|
|
562
|
+
streams: [
|
|
563
|
+
{
|
|
564
|
+
is_default: true,
|
|
565
|
+
name: 'by_project',
|
|
566
|
+
errors: []
|
|
567
|
+
}
|
|
568
|
+
],
|
|
503
569
|
write_checkpoint: undefined
|
|
504
570
|
}
|
|
505
571
|
});
|
|
@@ -544,13 +610,245 @@ bucket_definitions:
|
|
|
544
610
|
expect(line2.checkpointLine).toEqual({
|
|
545
611
|
checkpoint_diff: {
|
|
546
612
|
removed_buckets: [],
|
|
547
|
-
updated_buckets: [
|
|
613
|
+
updated_buckets: [
|
|
614
|
+
{
|
|
615
|
+
bucket: 'by_project[3]',
|
|
616
|
+
checksum: 1,
|
|
617
|
+
count: 1,
|
|
618
|
+
priority: 3,
|
|
619
|
+
subscriptions: [{ default: 0 }]
|
|
620
|
+
}
|
|
621
|
+
],
|
|
548
622
|
last_op_id: '2',
|
|
549
623
|
write_checkpoint: undefined
|
|
550
624
|
}
|
|
551
625
|
});
|
|
552
626
|
expect(line2.getFilteredBucketPositions()).toEqual(new Map([['by_project[3]', 0n]]));
|
|
553
627
|
});
|
|
628
|
+
|
|
629
|
+
describe('streams', () => {
|
|
630
|
+
let source: { -readonly [P in keyof BucketSource]: BucketSource[P] };
|
|
631
|
+
let storage: MockBucketChecksumStateStorage;
|
|
632
|
+
|
|
633
|
+
function checksumState(source: string | boolean, options?: Partial<BucketChecksumStateOptions>) {
|
|
634
|
+
if (typeof source == 'boolean') {
|
|
635
|
+
source = `
|
|
636
|
+
streams:
|
|
637
|
+
stream:
|
|
638
|
+
auto_subscribe: ${source}
|
|
639
|
+
query: SELECT * FROM assets WHERE id IN ifnull(subscription.parameter('ids'), '["default"]');
|
|
640
|
+
|
|
641
|
+
config:
|
|
642
|
+
edition: 2
|
|
643
|
+
`;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const rules = SqlSyncRules.fromYaml(source, {
|
|
647
|
+
defaultSchema: 'public'
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
return new BucketChecksumState({
|
|
651
|
+
syncContext,
|
|
652
|
+
syncRequest,
|
|
653
|
+
tokenPayload,
|
|
654
|
+
syncRules: { syncRules: rules, version: 1 },
|
|
655
|
+
bucketStorage: storage,
|
|
656
|
+
...options
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
beforeEach(() => {
|
|
661
|
+
storage = new MockBucketChecksumStateStorage();
|
|
662
|
+
storage.updateTestChecksum({ bucket: '1#stream|0["default"]', checksum: 1, count: 1 });
|
|
663
|
+
storage.updateTestChecksum({ bucket: '1#stream|0["a"]', checksum: 1, count: 1 });
|
|
664
|
+
storage.updateTestChecksum({ bucket: '1#stream|0["b"]', checksum: 1, count: 1 });
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
test('includes defaults', async () => {
|
|
668
|
+
const state = checksumState(true);
|
|
669
|
+
const line = await state.buildNextCheckpointLine({
|
|
670
|
+
base: storage.makeCheckpoint(1n),
|
|
671
|
+
writeCheckpoint: null,
|
|
672
|
+
update: CHECKPOINT_INVALIDATE_ALL
|
|
673
|
+
})!;
|
|
674
|
+
line?.advance();
|
|
675
|
+
expect(line?.checkpointLine).toEqual({
|
|
676
|
+
checkpoint: {
|
|
677
|
+
buckets: [
|
|
678
|
+
{ bucket: '1#stream|0["default"]', checksum: 1, count: 1, priority: 3, subscriptions: [{ default: 0 }] }
|
|
679
|
+
],
|
|
680
|
+
last_op_id: '1',
|
|
681
|
+
write_checkpoint: undefined,
|
|
682
|
+
streams: [{ name: 'stream', is_default: true, errors: [] }]
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
test('can exclude defaults', async () => {
|
|
688
|
+
const state = checksumState(true, { syncRequest: { streams: { include_defaults: false, subscriptions: [] } } });
|
|
689
|
+
|
|
690
|
+
const line = await state.buildNextCheckpointLine({
|
|
691
|
+
base: storage.makeCheckpoint(1n),
|
|
692
|
+
writeCheckpoint: null,
|
|
693
|
+
update: CHECKPOINT_INVALIDATE_ALL
|
|
694
|
+
})!;
|
|
695
|
+
line?.advance();
|
|
696
|
+
expect(line?.checkpointLine).toEqual({
|
|
697
|
+
checkpoint: {
|
|
698
|
+
buckets: [],
|
|
699
|
+
last_op_id: '1',
|
|
700
|
+
write_checkpoint: undefined,
|
|
701
|
+
streams: []
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
test('custom subscriptions', async () => {
|
|
707
|
+
const state = checksumState(true, {
|
|
708
|
+
syncRequest: {
|
|
709
|
+
streams: {
|
|
710
|
+
subscriptions: [
|
|
711
|
+
{ stream: 'stream', parameters: { ids: '["a"]' }, override_priority: null },
|
|
712
|
+
{ stream: 'stream', parameters: { ids: '["b"]' }, override_priority: 1 }
|
|
713
|
+
]
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
const line = await state.buildNextCheckpointLine({
|
|
719
|
+
base: storage.makeCheckpoint(1n),
|
|
720
|
+
writeCheckpoint: null,
|
|
721
|
+
update: CHECKPOINT_INVALIDATE_ALL
|
|
722
|
+
})!;
|
|
723
|
+
line?.advance();
|
|
724
|
+
expect(line?.checkpointLine).toEqual({
|
|
725
|
+
checkpoint: {
|
|
726
|
+
buckets: [
|
|
727
|
+
{ bucket: '1#stream|0["a"]', checksum: 1, count: 1, priority: 3, subscriptions: [{ sub: 0 }] },
|
|
728
|
+
{ bucket: '1#stream|0["b"]', checksum: 1, count: 1, priority: 1, subscriptions: [{ sub: 1 }] },
|
|
729
|
+
{ bucket: '1#stream|0["default"]', checksum: 1, count: 1, priority: 3, subscriptions: [{ default: 0 }] }
|
|
730
|
+
],
|
|
731
|
+
last_op_id: '1',
|
|
732
|
+
write_checkpoint: undefined,
|
|
733
|
+
streams: [{ name: 'stream', is_default: true, errors: [] }]
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
test('overlap between custom subscriptions', async () => {
|
|
739
|
+
const state = checksumState(false, {
|
|
740
|
+
syncRequest: {
|
|
741
|
+
streams: {
|
|
742
|
+
subscriptions: [
|
|
743
|
+
{ stream: 'stream', parameters: { ids: '["a", "b"]' }, override_priority: null },
|
|
744
|
+
{ stream: 'stream', parameters: { ids: '["b"]' }, override_priority: 1 }
|
|
745
|
+
]
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
const line = await state.buildNextCheckpointLine({
|
|
751
|
+
base: storage.makeCheckpoint(1n),
|
|
752
|
+
writeCheckpoint: null,
|
|
753
|
+
update: CHECKPOINT_INVALIDATE_ALL
|
|
754
|
+
})!;
|
|
755
|
+
line?.advance();
|
|
756
|
+
expect(line?.checkpointLine).toEqual({
|
|
757
|
+
checkpoint: {
|
|
758
|
+
buckets: [
|
|
759
|
+
{ bucket: '1#stream|0["a"]', checksum: 1, count: 1, priority: 3, subscriptions: [{ sub: 0 }] },
|
|
760
|
+
{ bucket: '1#stream|0["b"]', checksum: 1, count: 1, priority: 1, subscriptions: [{ sub: 0 }, { sub: 1 }] }
|
|
761
|
+
],
|
|
762
|
+
last_op_id: '1',
|
|
763
|
+
write_checkpoint: undefined,
|
|
764
|
+
streams: [{ name: 'stream', is_default: false, errors: [] }]
|
|
765
|
+
}
|
|
766
|
+
});
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
test('overlap between default and custom subscription', async () => {
|
|
770
|
+
const state = checksumState(true, {
|
|
771
|
+
syncRequest: {
|
|
772
|
+
streams: {
|
|
773
|
+
subscriptions: [{ stream: 'stream', parameters: { ids: '["a", "default"]' }, override_priority: 1 }]
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
const line = await state.buildNextCheckpointLine({
|
|
779
|
+
base: storage.makeCheckpoint(1n),
|
|
780
|
+
writeCheckpoint: null,
|
|
781
|
+
update: CHECKPOINT_INVALIDATE_ALL
|
|
782
|
+
})!;
|
|
783
|
+
line?.advance();
|
|
784
|
+
expect(line?.checkpointLine).toEqual({
|
|
785
|
+
checkpoint: {
|
|
786
|
+
buckets: [
|
|
787
|
+
{ bucket: '1#stream|0["a"]', checksum: 1, count: 1, priority: 1, subscriptions: [{ sub: 0 }] },
|
|
788
|
+
{
|
|
789
|
+
bucket: '1#stream|0["default"]',
|
|
790
|
+
checksum: 1,
|
|
791
|
+
count: 1,
|
|
792
|
+
priority: 1,
|
|
793
|
+
subscriptions: [{ sub: 0 }, { default: 0 }]
|
|
794
|
+
}
|
|
795
|
+
],
|
|
796
|
+
last_op_id: '1',
|
|
797
|
+
write_checkpoint: undefined,
|
|
798
|
+
streams: [{ name: 'stream', is_default: true, errors: [] }]
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
test('reports errors', async () => {
|
|
804
|
+
const state = checksumState(true, {
|
|
805
|
+
syncRequest: {
|
|
806
|
+
streams: {
|
|
807
|
+
subscriptions: [
|
|
808
|
+
{ stream: 'stream', parameters: { ids: '["a", "b"]' }, override_priority: 1 },
|
|
809
|
+
{ stream: 'stream', parameters: { ids: 'invalid json' }, override_priority: null }
|
|
810
|
+
]
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
|
|
815
|
+
const line = await state.buildNextCheckpointLine({
|
|
816
|
+
base: storage.makeCheckpoint(1n),
|
|
817
|
+
writeCheckpoint: null,
|
|
818
|
+
update: CHECKPOINT_INVALIDATE_ALL
|
|
819
|
+
})!;
|
|
820
|
+
line?.advance();
|
|
821
|
+
expect(line?.checkpointLine).toEqual({
|
|
822
|
+
checkpoint: {
|
|
823
|
+
buckets: [
|
|
824
|
+
{ bucket: '1#stream|0["a"]', checksum: 1, count: 1, priority: 1, subscriptions: [{ sub: 0 }] },
|
|
825
|
+
{ bucket: '1#stream|0["b"]', checksum: 1, count: 1, priority: 1, subscriptions: [{ sub: 0 }] },
|
|
826
|
+
{
|
|
827
|
+
bucket: '1#stream|0["default"]',
|
|
828
|
+
checksum: 1,
|
|
829
|
+
count: 1,
|
|
830
|
+
priority: 3,
|
|
831
|
+
subscriptions: [{ default: 0 }]
|
|
832
|
+
}
|
|
833
|
+
],
|
|
834
|
+
last_op_id: '1',
|
|
835
|
+
write_checkpoint: undefined,
|
|
836
|
+
streams: [
|
|
837
|
+
{
|
|
838
|
+
name: 'stream',
|
|
839
|
+
is_default: true,
|
|
840
|
+
errors: [
|
|
841
|
+
{
|
|
842
|
+
message: 'Error evaluating bucket ids: Unexpected token \'i\', "invalid json" is not valid JSON',
|
|
843
|
+
subscription: 1
|
|
844
|
+
}
|
|
845
|
+
]
|
|
846
|
+
}
|
|
847
|
+
]
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
});
|
|
851
|
+
});
|
|
554
852
|
});
|
|
555
853
|
|
|
556
854
|
class MockBucketChecksumStateStorage implements BucketChecksumStateStorage {
|