@powersync/service-core 0.0.0-dev-20250304151813 → 0.0.0-dev-20250306152715
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 +18 -4
- package/dist/api/api-index.d.ts +1 -0
- package/dist/api/api-index.js +1 -0
- package/dist/api/api-index.js.map +1 -1
- package/dist/api/api-metrics.d.ts +11 -0
- package/dist/api/api-metrics.js +30 -0
- package/dist/api/api-metrics.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/metrics/MetricsEngine.d.ts +21 -0
- package/dist/metrics/MetricsEngine.js +79 -0
- package/dist/metrics/MetricsEngine.js.map +1 -0
- package/dist/metrics/metrics-index.d.ts +4 -0
- package/dist/metrics/metrics-index.js +5 -0
- package/dist/metrics/metrics-index.js.map +1 -0
- package/dist/metrics/metrics-interfaces.d.ts +36 -0
- package/dist/metrics/metrics-interfaces.js +6 -0
- package/dist/metrics/metrics-interfaces.js.map +1 -0
- package/dist/metrics/open-telemetry/OpenTelemetryMetricsFactory.d.ts +10 -0
- package/dist/metrics/open-telemetry/OpenTelemetryMetricsFactory.js +51 -0
- package/dist/metrics/open-telemetry/OpenTelemetryMetricsFactory.js.map +1 -0
- package/dist/metrics/open-telemetry/util.d.ts +6 -0
- package/dist/metrics/open-telemetry/util.js +56 -0
- package/dist/metrics/open-telemetry/util.js.map +1 -0
- package/dist/replication/AbstractReplicationJob.d.ts +2 -0
- package/dist/replication/AbstractReplicationJob.js.map +1 -1
- package/dist/replication/AbstractReplicator.d.ts +3 -0
- package/dist/replication/AbstractReplicator.js +3 -0
- package/dist/replication/AbstractReplicator.js.map +1 -1
- package/dist/replication/ReplicationModule.d.ts +7 -0
- package/dist/replication/ReplicationModule.js +1 -0
- package/dist/replication/ReplicationModule.js.map +1 -1
- package/dist/replication/replication-index.d.ts +1 -0
- package/dist/replication/replication-index.js +1 -0
- package/dist/replication/replication-index.js.map +1 -1
- package/dist/replication/replication-metrics.d.ts +11 -0
- package/dist/replication/replication-metrics.js +39 -0
- package/dist/replication/replication-metrics.js.map +1 -0
- package/dist/routes/configure-fastify.d.ts +3 -3
- package/dist/routes/endpoints/checkpointing.d.ts +6 -6
- package/dist/routes/endpoints/socket-route.js +5 -5
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.js +6 -6
- package/dist/routes/endpoints/sync-stream.js.map +1 -1
- package/dist/storage/BucketStorageBatch.d.ts +2 -1
- package/dist/storage/BucketStorageBatch.js.map +1 -1
- package/dist/storage/ChecksumCache.d.ts +6 -6
- package/dist/storage/ChecksumCache.js +5 -6
- package/dist/storage/ChecksumCache.js.map +1 -1
- package/dist/storage/SyncRulesBucketStorage.d.ts +9 -9
- package/dist/storage/storage-index.d.ts +1 -0
- package/dist/storage/storage-index.js +1 -0
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/storage/storage-metrics.d.ts +4 -0
- package/dist/storage/storage-metrics.js +56 -0
- package/dist/storage/storage-metrics.js.map +1 -0
- package/dist/sync/BucketChecksumState.d.ts +3 -3
- package/dist/sync/BucketChecksumState.js +3 -3
- package/dist/sync/BucketChecksumState.js.map +1 -1
- package/dist/sync/RequestTracker.d.ts +3 -0
- package/dist/sync/RequestTracker.js +8 -3
- package/dist/sync/RequestTracker.js.map +1 -1
- package/dist/sync/sync.d.ts +1 -1
- package/dist/sync/sync.js +8 -6
- package/dist/sync/sync.js.map +1 -1
- package/dist/system/ServiceContext.d.ts +3 -3
- package/dist/system/ServiceContext.js +7 -3
- package/dist/system/ServiceContext.js.map +1 -1
- package/dist/util/protocol-types.d.ts +10 -10
- package/dist/util/utils.d.ts +12 -2
- package/dist/util/utils.js +5 -1
- package/dist/util/utils.js.map +1 -1
- package/package.json +8 -8
- package/src/api/api-index.ts +1 -0
- package/src/api/api-metrics.ts +35 -0
- package/src/index.ts +2 -2
- package/src/metrics/MetricsEngine.ts +98 -0
- package/src/metrics/metrics-index.ts +4 -0
- package/src/metrics/metrics-interfaces.ts +41 -0
- package/src/metrics/open-telemetry/OpenTelemetryMetricsFactory.ts +66 -0
- package/src/metrics/open-telemetry/util.ts +74 -0
- package/src/replication/AbstractReplicationJob.ts +2 -0
- package/src/replication/AbstractReplicator.ts +7 -0
- package/src/replication/ReplicationModule.ts +10 -0
- package/src/replication/replication-index.ts +1 -0
- package/src/replication/replication-metrics.ts +45 -0
- package/src/routes/endpoints/socket-route.ts +6 -5
- package/src/routes/endpoints/sync-stream.ts +7 -6
- package/src/storage/BucketStorageBatch.ts +2 -1
- package/src/storage/ChecksumCache.ts +13 -14
- package/src/storage/SyncRulesBucketStorage.ts +10 -10
- package/src/storage/storage-index.ts +1 -0
- package/src/storage/storage-metrics.ts +67 -0
- package/src/sync/BucketChecksumState.ts +7 -7
- package/src/sync/RequestTracker.ts +9 -3
- package/src/sync/sync.ts +10 -8
- package/src/system/ServiceContext.ts +9 -4
- package/src/util/protocol-types.ts +10 -10
- package/src/util/utils.ts +13 -2
- package/test/src/checksum_cache.test.ts +83 -84
- package/test/src/sync/BucketChecksumState.test.ts +47 -41
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/metrics/Metrics.d.ts +0 -30
- package/dist/metrics/Metrics.js +0 -202
- package/dist/metrics/Metrics.js.map +0 -1
- package/src/metrics/Metrics.ts +0 -255
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
BucketChecksumStateStorage,
|
|
5
5
|
CHECKPOINT_INVALIDATE_ALL,
|
|
6
6
|
ChecksumMap,
|
|
7
|
-
|
|
7
|
+
InternalOpId,
|
|
8
8
|
SyncContext,
|
|
9
9
|
WatchFilterEvent
|
|
10
10
|
} from '@/index.js';
|
|
@@ -66,7 +66,7 @@ bucket_definitions:
|
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
const line = (await state.buildNextCheckpointLine({
|
|
69
|
-
base: { checkpoint:
|
|
69
|
+
base: { checkpoint: 1n, lsn: '1' },
|
|
70
70
|
writeCheckpoint: null,
|
|
71
71
|
update: CHECKPOINT_INVALIDATE_ALL
|
|
72
72
|
}))!;
|
|
@@ -84,17 +84,17 @@ bucket_definitions:
|
|
|
84
84
|
}
|
|
85
85
|
]);
|
|
86
86
|
// This is the bucket data to be fetched
|
|
87
|
-
expect(state.getFilteredBucketPositions(line.bucketsToFetch)).toEqual(new Map([['global[]',
|
|
87
|
+
expect(state.getFilteredBucketPositions(line.bucketsToFetch)).toEqual(new Map([['global[]', 0n]]));
|
|
88
88
|
|
|
89
89
|
// This similuates the bucket data being sent
|
|
90
|
-
state.updateBucketPosition({ bucket: 'global[]', nextAfter:
|
|
90
|
+
state.updateBucketPosition({ bucket: 'global[]', nextAfter: 1n, hasMore: false });
|
|
91
91
|
|
|
92
92
|
// Update bucket storage state
|
|
93
93
|
storage.updateTestChecksum({ bucket: 'global[]', checksum: 2, count: 2 });
|
|
94
94
|
|
|
95
95
|
// Now we get a new line
|
|
96
96
|
const line2 = (await state.buildNextCheckpointLine({
|
|
97
|
-
base: { checkpoint:
|
|
97
|
+
base: { checkpoint: 2n, lsn: '2' },
|
|
98
98
|
writeCheckpoint: null,
|
|
99
99
|
update: {
|
|
100
100
|
updatedDataBuckets: ['global[]'],
|
|
@@ -111,7 +111,7 @@ bucket_definitions:
|
|
|
111
111
|
write_checkpoint: undefined
|
|
112
112
|
}
|
|
113
113
|
});
|
|
114
|
-
expect(state.getFilteredBucketPositions(line2.bucketsToFetch)).toEqual(new Map([['global[]',
|
|
114
|
+
expect(state.getFilteredBucketPositions(line2.bucketsToFetch)).toEqual(new Map([['global[]', 1n]]));
|
|
115
115
|
});
|
|
116
116
|
|
|
117
117
|
test('global bucket with initial state', async () => {
|
|
@@ -125,14 +125,14 @@ bucket_definitions:
|
|
|
125
125
|
const state = new BucketChecksumState({
|
|
126
126
|
syncContext,
|
|
127
127
|
// Client sets the initial state here
|
|
128
|
-
initialBucketPositions: [{ name: 'global[]', after:
|
|
128
|
+
initialBucketPositions: [{ name: 'global[]', after: 1n }],
|
|
129
129
|
syncParams: new RequestParameters({ sub: '' }, {}),
|
|
130
130
|
syncRules: SYNC_RULES_GLOBAL,
|
|
131
131
|
bucketStorage: storage
|
|
132
132
|
});
|
|
133
133
|
|
|
134
134
|
const line = (await state.buildNextCheckpointLine({
|
|
135
|
-
base: { checkpoint:
|
|
135
|
+
base: { checkpoint: 1n, lsn: '1' },
|
|
136
136
|
writeCheckpoint: null,
|
|
137
137
|
update: CHECKPOINT_INVALIDATE_ALL
|
|
138
138
|
}))!;
|
|
@@ -150,7 +150,7 @@ bucket_definitions:
|
|
|
150
150
|
}
|
|
151
151
|
]);
|
|
152
152
|
// This is the main difference between this and the previous test
|
|
153
|
-
expect(state.getFilteredBucketPositions(line.bucketsToFetch)).toEqual(new Map([['global[]',
|
|
153
|
+
expect(state.getFilteredBucketPositions(line.bucketsToFetch)).toEqual(new Map([['global[]', 1n]]));
|
|
154
154
|
});
|
|
155
155
|
|
|
156
156
|
test('multiple static buckets', async () => {
|
|
@@ -167,7 +167,7 @@ bucket_definitions:
|
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
const line = (await state.buildNextCheckpointLine({
|
|
170
|
-
base: { checkpoint:
|
|
170
|
+
base: { checkpoint: 1n, lsn: '1' },
|
|
171
171
|
writeCheckpoint: null,
|
|
172
172
|
update: CHECKPOINT_INVALIDATE_ALL
|
|
173
173
|
}))!;
|
|
@@ -196,7 +196,7 @@ bucket_definitions:
|
|
|
196
196
|
storage.updateTestChecksum({ bucket: 'global[2]', checksum: 2, count: 2 });
|
|
197
197
|
|
|
198
198
|
const line2 = (await state.buildNextCheckpointLine({
|
|
199
|
-
base: { checkpoint:
|
|
199
|
+
base: { checkpoint: 2n, lsn: '2' },
|
|
200
200
|
writeCheckpoint: null,
|
|
201
201
|
update: {
|
|
202
202
|
...CHECKPOINT_INVALIDATE_ALL,
|
|
@@ -226,7 +226,7 @@ bucket_definitions:
|
|
|
226
226
|
const state = new BucketChecksumState({
|
|
227
227
|
syncContext,
|
|
228
228
|
// Client sets the initial state here
|
|
229
|
-
initialBucketPositions: [{ name: 'something_here[]', after:
|
|
229
|
+
initialBucketPositions: [{ name: 'something_here[]', after: 1n }],
|
|
230
230
|
syncParams: new RequestParameters({ sub: '' }, {}),
|
|
231
231
|
syncRules: SYNC_RULES_GLOBAL,
|
|
232
232
|
bucketStorage: storage
|
|
@@ -235,7 +235,7 @@ bucket_definitions:
|
|
|
235
235
|
storage.updateTestChecksum({ bucket: 'global[]', checksum: 1, count: 1 });
|
|
236
236
|
|
|
237
237
|
const line = (await state.buildNextCheckpointLine({
|
|
238
|
-
base: { checkpoint:
|
|
238
|
+
base: { checkpoint: 1n, lsn: '1' },
|
|
239
239
|
writeCheckpoint: null,
|
|
240
240
|
update: CHECKPOINT_INVALIDATE_ALL
|
|
241
241
|
}))!;
|
|
@@ -252,7 +252,7 @@ bucket_definitions:
|
|
|
252
252
|
priority: 3
|
|
253
253
|
}
|
|
254
254
|
]);
|
|
255
|
-
expect(state.getFilteredBucketPositions(line.bucketsToFetch)).toEqual(new Map([['global[]',
|
|
255
|
+
expect(state.getFilteredBucketPositions(line.bucketsToFetch)).toEqual(new Map([['global[]', 0n]]));
|
|
256
256
|
});
|
|
257
257
|
|
|
258
258
|
test('invalidating individual bucket', async () => {
|
|
@@ -274,19 +274,19 @@ bucket_definitions:
|
|
|
274
274
|
// storage.filter = state.checkpointFilter;
|
|
275
275
|
|
|
276
276
|
await state.buildNextCheckpointLine({
|
|
277
|
-
base: { checkpoint:
|
|
277
|
+
base: { checkpoint: 1n, lsn: '1' },
|
|
278
278
|
writeCheckpoint: null,
|
|
279
279
|
update: CHECKPOINT_INVALIDATE_ALL
|
|
280
280
|
});
|
|
281
281
|
|
|
282
|
-
state.updateBucketPosition({ bucket: 'global[1]', nextAfter:
|
|
283
|
-
state.updateBucketPosition({ bucket: 'global[2]', nextAfter:
|
|
282
|
+
state.updateBucketPosition({ bucket: 'global[1]', nextAfter: 1n, hasMore: false });
|
|
283
|
+
state.updateBucketPosition({ bucket: 'global[2]', nextAfter: 1n, hasMore: false });
|
|
284
284
|
|
|
285
285
|
storage.updateTestChecksum({ bucket: 'global[1]', checksum: 2, count: 2 });
|
|
286
286
|
storage.updateTestChecksum({ bucket: 'global[2]', checksum: 2, count: 2 });
|
|
287
287
|
|
|
288
288
|
const line2 = (await state.buildNextCheckpointLine({
|
|
289
|
-
base: { checkpoint:
|
|
289
|
+
base: { checkpoint: 2n, lsn: '2' },
|
|
290
290
|
writeCheckpoint: null,
|
|
291
291
|
update: {
|
|
292
292
|
...CHECKPOINT_INVALIDATE_ALL,
|
|
@@ -330,7 +330,7 @@ bucket_definitions:
|
|
|
330
330
|
storage.updateTestChecksum({ bucket: 'global[2]', checksum: 1, count: 1 });
|
|
331
331
|
|
|
332
332
|
await state.buildNextCheckpointLine({
|
|
333
|
-
base: { checkpoint:
|
|
333
|
+
base: { checkpoint: 1n, lsn: '1' },
|
|
334
334
|
writeCheckpoint: null,
|
|
335
335
|
update: CHECKPOINT_INVALIDATE_ALL
|
|
336
336
|
});
|
|
@@ -339,7 +339,7 @@ bucket_definitions:
|
|
|
339
339
|
storage.updateTestChecksum({ bucket: 'global[2]', checksum: 2, count: 2 });
|
|
340
340
|
|
|
341
341
|
const line2 = (await state.buildNextCheckpointLine({
|
|
342
|
-
base: { checkpoint:
|
|
342
|
+
base: { checkpoint: 2n, lsn: '2' },
|
|
343
343
|
writeCheckpoint: null,
|
|
344
344
|
// Invalidate the state - will re-check all buckets
|
|
345
345
|
update: CHECKPOINT_INVALIDATE_ALL
|
|
@@ -375,7 +375,7 @@ bucket_definitions:
|
|
|
375
375
|
});
|
|
376
376
|
|
|
377
377
|
const line = (await state.buildNextCheckpointLine({
|
|
378
|
-
base: { checkpoint:
|
|
378
|
+
base: { checkpoint: 3n, lsn: '3' },
|
|
379
379
|
writeCheckpoint: null,
|
|
380
380
|
update: CHECKPOINT_INVALIDATE_ALL
|
|
381
381
|
}))!;
|
|
@@ -403,19 +403,19 @@ bucket_definitions:
|
|
|
403
403
|
// This is the bucket data to be fetched
|
|
404
404
|
expect(state.getFilteredBucketPositions(line.bucketsToFetch)).toEqual(
|
|
405
405
|
new Map([
|
|
406
|
-
['global[1]',
|
|
407
|
-
['global[2]',
|
|
406
|
+
['global[1]', 0n],
|
|
407
|
+
['global[2]', 0n]
|
|
408
408
|
])
|
|
409
409
|
);
|
|
410
410
|
|
|
411
411
|
// No data changes here.
|
|
412
412
|
// We simulate partial data sent, before a checkpoint is interrupted.
|
|
413
|
-
state.updateBucketPosition({ bucket: 'global[1]', nextAfter:
|
|
414
|
-
state.updateBucketPosition({ bucket: 'global[2]', nextAfter:
|
|
413
|
+
state.updateBucketPosition({ bucket: 'global[1]', nextAfter: 3n, hasMore: false });
|
|
414
|
+
state.updateBucketPosition({ bucket: 'global[2]', nextAfter: 1n, hasMore: true });
|
|
415
415
|
storage.updateTestChecksum({ bucket: 'global[1]', checksum: 4, count: 4 });
|
|
416
416
|
|
|
417
417
|
const line2 = (await state.buildNextCheckpointLine({
|
|
418
|
-
base: { checkpoint:
|
|
418
|
+
base: { checkpoint: 4n, lsn: '4' },
|
|
419
419
|
writeCheckpoint: null,
|
|
420
420
|
update: {
|
|
421
421
|
...CHECKPOINT_INVALIDATE_ALL,
|
|
@@ -452,8 +452,8 @@ bucket_definitions:
|
|
|
452
452
|
|
|
453
453
|
expect(state.getFilteredBucketPositions(line2.bucketsToFetch)).toEqual(
|
|
454
454
|
new Map([
|
|
455
|
-
['global[1]',
|
|
456
|
-
['global[2]',
|
|
455
|
+
['global[1]', 3n],
|
|
456
|
+
['global[2]', 1n]
|
|
457
457
|
])
|
|
458
458
|
);
|
|
459
459
|
});
|
|
@@ -472,14 +472,17 @@ bucket_definitions:
|
|
|
472
472
|
bucketStorage: storage
|
|
473
473
|
});
|
|
474
474
|
|
|
475
|
-
storage.getParameterSets = async (
|
|
476
|
-
|
|
475
|
+
storage.getParameterSets = async (
|
|
476
|
+
checkpoint: InternalOpId,
|
|
477
|
+
lookups: SqliteJsonValue[][]
|
|
478
|
+
): Promise<SqliteJsonRow[]> => {
|
|
479
|
+
expect(checkpoint).toEqual(1n);
|
|
477
480
|
expect(lookups).toEqual([['by_project', '1', 'u1']]);
|
|
478
481
|
return [{ id: 1 }, { id: 2 }];
|
|
479
482
|
};
|
|
480
483
|
|
|
481
484
|
const line = (await state.buildNextCheckpointLine({
|
|
482
|
-
base: { checkpoint:
|
|
485
|
+
base: { checkpoint: 1n, lsn: '1' },
|
|
483
486
|
writeCheckpoint: null,
|
|
484
487
|
update: CHECKPOINT_INVALIDATE_ALL
|
|
485
488
|
}))!;
|
|
@@ -506,23 +509,26 @@ bucket_definitions:
|
|
|
506
509
|
// This is the bucket data to be fetched
|
|
507
510
|
expect(state.getFilteredBucketPositions(line.bucketsToFetch)).toEqual(
|
|
508
511
|
new Map([
|
|
509
|
-
['by_project[1]',
|
|
510
|
-
['by_project[2]',
|
|
512
|
+
['by_project[1]', 0n],
|
|
513
|
+
['by_project[2]', 0n]
|
|
511
514
|
])
|
|
512
515
|
);
|
|
513
516
|
|
|
514
|
-
state.updateBucketPosition({ bucket: 'by_project[1]', nextAfter:
|
|
515
|
-
state.updateBucketPosition({ bucket: 'by_project[2]', nextAfter:
|
|
517
|
+
state.updateBucketPosition({ bucket: 'by_project[1]', nextAfter: 1n, hasMore: false });
|
|
518
|
+
state.updateBucketPosition({ bucket: 'by_project[2]', nextAfter: 1n, hasMore: false });
|
|
516
519
|
|
|
517
|
-
storage.getParameterSets = async (
|
|
518
|
-
|
|
520
|
+
storage.getParameterSets = async (
|
|
521
|
+
checkpoint: InternalOpId,
|
|
522
|
+
lookups: SqliteJsonValue[][]
|
|
523
|
+
): Promise<SqliteJsonRow[]> => {
|
|
524
|
+
expect(checkpoint).toEqual(2n);
|
|
519
525
|
expect(lookups).toEqual([['by_project', '1', 'u1']]);
|
|
520
526
|
return [{ id: 1 }, { id: 2 }, { id: 3 }];
|
|
521
527
|
};
|
|
522
528
|
|
|
523
529
|
// Now we get a new line
|
|
524
530
|
const line2 = (await state.buildNextCheckpointLine({
|
|
525
|
-
base: { checkpoint:
|
|
531
|
+
base: { checkpoint: 2n, lsn: '2' },
|
|
526
532
|
writeCheckpoint: null,
|
|
527
533
|
update: {
|
|
528
534
|
invalidateDataBuckets: false,
|
|
@@ -539,7 +545,7 @@ bucket_definitions:
|
|
|
539
545
|
write_checkpoint: undefined
|
|
540
546
|
}
|
|
541
547
|
});
|
|
542
|
-
expect(state.getFilteredBucketPositions(line2.bucketsToFetch)).toEqual(new Map([['by_project[3]',
|
|
548
|
+
expect(state.getFilteredBucketPositions(line2.bucketsToFetch)).toEqual(new Map([['by_project[3]', 0n]]));
|
|
543
549
|
});
|
|
544
550
|
});
|
|
545
551
|
|
|
@@ -558,7 +564,7 @@ class MockBucketChecksumStateStorage implements BucketChecksumStateStorage {
|
|
|
558
564
|
this.filter?.({ invalidate: true });
|
|
559
565
|
}
|
|
560
566
|
|
|
561
|
-
async getChecksums(checkpoint:
|
|
567
|
+
async getChecksums(checkpoint: InternalOpId, buckets: string[]): Promise<ChecksumMap> {
|
|
562
568
|
return new Map<string, BucketChecksum>(
|
|
563
569
|
buckets.map((bucket) => {
|
|
564
570
|
const checksum = this.state.get(bucket);
|
|
@@ -574,7 +580,7 @@ class MockBucketChecksumStateStorage implements BucketChecksumStateStorage {
|
|
|
574
580
|
);
|
|
575
581
|
}
|
|
576
582
|
|
|
577
|
-
async getParameterSets(checkpoint:
|
|
583
|
+
async getParameterSets(checkpoint: InternalOpId, lookups: SqliteJsonValue[][]): Promise<SqliteJsonRow[]> {
|
|
578
584
|
throw new Error('Method not implemented.');
|
|
579
585
|
}
|
|
580
586
|
}
|