@powersync/service-core 0.0.0-dev-20241001150444 → 0.0.0-dev-20241002180742
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 +10 -5
- package/dist/api/RouteAPI.d.ts +1 -4
- package/dist/api/diagnostics.js.map +1 -1
- package/dist/api/schema.js +6 -2
- package/dist/api/schema.js.map +1 -1
- package/dist/auth/CachedKeyCollector.js.map +1 -1
- package/dist/auth/KeySpec.js.map +1 -1
- package/dist/auth/KeyStore.js.map +1 -1
- package/dist/auth/LeakyBucket.js.map +1 -1
- package/dist/auth/RemoteJWKSCollector.d.ts +0 -2
- package/dist/auth/RemoteJWKSCollector.js.map +1 -1
- package/dist/db/mongo.js.map +1 -1
- package/dist/entry/cli-entry.js.map +1 -1
- package/dist/entry/commands/compact-action.js.map +1 -1
- package/dist/entry/commands/migrate-action.js.map +1 -1
- package/dist/entry/commands/teardown-action.js.map +1 -1
- package/dist/locks/MongoLocks.js.map +1 -1
- package/dist/metrics/Metrics.js.map +1 -1
- package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
- package/dist/migrations/executor.js.map +1 -1
- package/dist/migrations/migrations.js.map +1 -1
- package/dist/migrations/store/migration-store.js.map +1 -1
- package/dist/modules/ModuleManager.js.map +1 -1
- package/dist/replication/AbstractReplicationJob.d.ts +0 -1
- package/dist/replication/AbstractReplicator.js.map +1 -1
- package/dist/replication/ErrorRateLimiter.d.ts +0 -1
- package/dist/replication/ReplicationEngine.js.map +1 -1
- package/dist/replication/ReplicationModule.js.map +1 -1
- package/dist/routes/RouterEngine.js.map +1 -1
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/configure-fastify.d.ts +21 -7
- package/dist/routes/configure-rsocket.d.ts +0 -1
- package/dist/routes/configure-rsocket.js.map +1 -1
- package/dist/routes/endpoints/admin.d.ts +42 -12
- package/dist/routes/endpoints/admin.js.map +1 -1
- package/dist/routes/endpoints/checkpointing.js.map +1 -1
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/endpoints/sync-rules.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.d.ts +0 -1
- package/dist/routes/endpoints/sync-stream.js.map +1 -1
- package/dist/routes/hooks.js.map +1 -1
- package/dist/routes/route-register.js.map +1 -1
- package/dist/runner/teardown.js.map +1 -1
- package/dist/storage/BucketStorage.d.ts +0 -1
- package/dist/storage/BucketStorage.js.map +1 -1
- package/dist/storage/ChecksumCache.d.ts +19 -1
- package/dist/storage/ChecksumCache.js +8 -1
- package/dist/storage/ChecksumCache.js.map +1 -1
- package/dist/storage/MongoBucketStorage.d.ts +0 -1
- package/dist/storage/MongoBucketStorage.js +1 -1
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/StorageEngine.js.map +1 -1
- package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
- package/dist/storage/mongo/MongoCompactor.js.map +1 -1
- package/dist/storage/mongo/MongoIdSequence.js.map +1 -1
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
- package/dist/storage/mongo/MongoSyncBucketStorage.js +14 -4
- package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/mongo/OperationBatch.js.map +1 -1
- package/dist/storage/mongo/PersistedBatch.js.map +1 -1
- package/dist/storage/mongo/config.js.map +1 -1
- package/dist/storage/mongo/util.js.map +1 -1
- package/dist/sync/BroadcastIterable.d.ts +0 -1
- package/dist/sync/BroadcastIterable.js.map +1 -1
- package/dist/sync/LastValueSink.d.ts +0 -1
- package/dist/sync/LastValueSink.js.map +1 -1
- package/dist/sync/merge.d.ts +0 -1
- package/dist/sync/merge.js.map +1 -1
- package/dist/sync/safeRace.js.map +1 -1
- package/dist/sync/sync.d.ts +0 -1
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/util.d.ts +0 -2
- package/dist/sync/util.js.map +1 -1
- package/dist/util/Mutex.js.map +1 -1
- package/dist/util/config/collectors/config-collector.js.map +1 -1
- package/dist/util/config/collectors/impl/base64-config-collector.js.map +1 -1
- package/dist/util/config/collectors/impl/filesystem-config-collector.js.map +1 -1
- package/dist/util/config/compound-config-collector.js +1 -1
- package/dist/util/config/compound-config-collector.js.map +1 -1
- package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js.map +1 -1
- package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js.map +1 -1
- package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js.map +1 -1
- package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -1
- package/dist/util/config.js.map +1 -1
- package/dist/util/memory-tracking.js.map +1 -1
- package/dist/util/protocol-types.d.ts +0 -65
- package/dist/util/protocol-types.js +0 -7
- package/dist/util/protocol-types.js.map +1 -1
- package/dist/util/secs.js.map +1 -1
- package/dist/util/utils.d.ts +2 -1
- package/dist/util/utils.js +9 -2
- package/dist/util/utils.js.map +1 -1
- package/package.json +8 -8
- package/src/api/RouteAPI.ts +1 -4
- package/src/api/schema.ts +6 -2
- package/src/auth/RemoteJWKSCollector.ts +4 -1
- package/src/storage/ChecksumCache.ts +32 -2
- package/src/storage/mongo/MongoCompactor.ts +5 -1
- package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +4 -1
- package/src/storage/mongo/MongoSyncBucketStorage.ts +18 -8
- package/src/storage/mongo/MongoSyncRulesLock.ts +6 -2
- package/src/storage/mongo/PersistedBatch.ts +4 -1
- package/src/util/protocol-types.ts +0 -89
- package/src/util/utils.ts +11 -3
- package/test/src/__snapshots__/sync.test.ts.snap +7 -7
- package/test/src/checksum_cache.test.ts +26 -19
- package/test/src/compacting.test.ts +81 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +7 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ChecksumCache, FetchChecksums, FetchPartialBucketChecksum } from '@/storage/ChecksumCache.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { ChecksumCache, FetchChecksums, FetchPartialBucketChecksum, PartialChecksum } from '@/storage/ChecksumCache.js';
|
|
2
|
+
import { OpId } from '@/util/protocol-types.js';
|
|
3
|
+
import { addChecksums } from '@/util/util-index.js';
|
|
4
4
|
import * as crypto from 'node:crypto';
|
|
5
5
|
import { describe, expect, it } from 'vitest';
|
|
6
6
|
|
|
@@ -13,28 +13,22 @@ function testHash(bucket: string, checkpoint: OpId) {
|
|
|
13
13
|
return hash;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
function testPartialHash(request: FetchPartialBucketChecksum):
|
|
16
|
+
function testPartialHash(request: FetchPartialBucketChecksum): PartialChecksum {
|
|
17
17
|
if (request.start) {
|
|
18
18
|
const a = testHash(request.bucket, request.start);
|
|
19
19
|
const b = testHash(request.bucket, request.end);
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
// Subtract a
|
|
28
|
-
bucket: request.bucket,
|
|
29
|
-
checksum: -a,
|
|
30
|
-
count: -Number(request.start)
|
|
31
|
-
}
|
|
32
|
-
);
|
|
20
|
+
return {
|
|
21
|
+
bucket: request.bucket,
|
|
22
|
+
partialCount: Number(request.end) - Number(request.start),
|
|
23
|
+
partialChecksum: addChecksums(b, -a),
|
|
24
|
+
isFullChecksum: false
|
|
25
|
+
};
|
|
33
26
|
} else {
|
|
34
27
|
return {
|
|
35
28
|
bucket: request.bucket,
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
partialChecksum: testHash(request.bucket, request.end),
|
|
30
|
+
partialCount: Number(request.end),
|
|
31
|
+
isFullChecksum: true
|
|
38
32
|
};
|
|
39
33
|
}
|
|
40
34
|
}
|
|
@@ -433,4 +427,17 @@ describe('checksum cache', function () {
|
|
|
433
427
|
[{ bucket: 'test2', end: '123' }]
|
|
434
428
|
]);
|
|
435
429
|
});
|
|
430
|
+
|
|
431
|
+
it('should handle CLEAR/isFullChecksum checksums', async function () {
|
|
432
|
+
let lookups: FetchPartialBucketChecksum[][] = [];
|
|
433
|
+
const cache = factory(async (batch) => {
|
|
434
|
+
lookups.push(batch);
|
|
435
|
+
// This forces a `isFullChecksum: true` result
|
|
436
|
+
delete batch[0].start;
|
|
437
|
+
return fetchTestChecksums(batch);
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
expect(await cache.getChecksums('123', ['test'])).toEqual([TEST_123]);
|
|
441
|
+
expect(await cache.getChecksums('1234', ['test'])).toEqual([TEST_1234]);
|
|
442
|
+
});
|
|
436
443
|
});
|
|
@@ -61,6 +61,7 @@ bucket_definitions:
|
|
|
61
61
|
|
|
62
62
|
const batchBefore = await oneFromAsync(storage.getBucketDataBatch(checkpoint, new Map([['global[]', '0']])));
|
|
63
63
|
const dataBefore = batchBefore.batch.data;
|
|
64
|
+
const checksumBefore = await storage.getChecksums(checkpoint, ['global[]']);
|
|
64
65
|
|
|
65
66
|
expect(dataBefore).toMatchObject([
|
|
66
67
|
{
|
|
@@ -87,6 +88,7 @@ bucket_definitions:
|
|
|
87
88
|
|
|
88
89
|
const batchAfter = await oneFromAsync(storage.getBucketDataBatch(checkpoint, new Map([['global[]', '0']])));
|
|
89
90
|
const dataAfter = batchAfter.batch.data;
|
|
91
|
+
const checksumAfter = await storage.getChecksums(checkpoint, ['global[]']);
|
|
90
92
|
|
|
91
93
|
expect(batchAfter.targetOp).toEqual(3n);
|
|
92
94
|
expect(dataAfter).toMatchObject([
|
|
@@ -109,6 +111,8 @@ bucket_definitions:
|
|
|
109
111
|
}
|
|
110
112
|
]);
|
|
111
113
|
|
|
114
|
+
expect(checksumBefore.get('global[]')).toEqual(checksumAfter.get('global[]'));
|
|
115
|
+
|
|
112
116
|
validateCompactedBucket(dataBefore, dataAfter);
|
|
113
117
|
});
|
|
114
118
|
|
|
@@ -163,6 +167,7 @@ bucket_definitions:
|
|
|
163
167
|
|
|
164
168
|
const batchBefore = await oneFromAsync(storage.getBucketDataBatch(checkpoint, new Map([['global[]', '0']])));
|
|
165
169
|
const dataBefore = batchBefore.batch.data;
|
|
170
|
+
const checksumBefore = await storage.getChecksums(checkpoint, ['global[]']);
|
|
166
171
|
|
|
167
172
|
expect(dataBefore).toMatchObject([
|
|
168
173
|
{
|
|
@@ -195,6 +200,7 @@ bucket_definitions:
|
|
|
195
200
|
|
|
196
201
|
const batchAfter = await oneFromAsync(storage.getBucketDataBatch(checkpoint, new Map([['global[]', '0']])));
|
|
197
202
|
const dataAfter = batchAfter.batch.data;
|
|
203
|
+
const checksumAfter = await storage.getChecksums(checkpoint, ['global[]']);
|
|
198
204
|
|
|
199
205
|
expect(batchAfter.targetOp).toEqual(4n);
|
|
200
206
|
expect(dataAfter).toMatchObject([
|
|
@@ -210,7 +216,82 @@ bucket_definitions:
|
|
|
210
216
|
op_id: '4'
|
|
211
217
|
}
|
|
212
218
|
]);
|
|
219
|
+
expect(checksumBefore.get('global[]')).toEqual(checksumAfter.get('global[]'));
|
|
213
220
|
|
|
214
221
|
validateCompactedBucket(dataBefore, dataAfter);
|
|
215
222
|
});
|
|
223
|
+
|
|
224
|
+
test('compacting (3)', async () => {
|
|
225
|
+
const sync_rules = testRules(`
|
|
226
|
+
bucket_definitions:
|
|
227
|
+
global:
|
|
228
|
+
data: [select * from test]
|
|
229
|
+
`);
|
|
230
|
+
|
|
231
|
+
const storage = (await factory()).getInstance(sync_rules);
|
|
232
|
+
|
|
233
|
+
const result = await storage.startBatch(BATCH_OPTIONS, async (batch) => {
|
|
234
|
+
await batch.save({
|
|
235
|
+
sourceTable: TEST_TABLE,
|
|
236
|
+
tag: 'insert',
|
|
237
|
+
after: {
|
|
238
|
+
id: 't1'
|
|
239
|
+
},
|
|
240
|
+
afterReplicaId: 't1'
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
await batch.save({
|
|
244
|
+
sourceTable: TEST_TABLE,
|
|
245
|
+
tag: 'insert',
|
|
246
|
+
after: {
|
|
247
|
+
id: 't2'
|
|
248
|
+
},
|
|
249
|
+
afterReplicaId: 't2'
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
await batch.save({
|
|
253
|
+
sourceTable: TEST_TABLE,
|
|
254
|
+
tag: 'delete',
|
|
255
|
+
before: {
|
|
256
|
+
id: 't1'
|
|
257
|
+
},
|
|
258
|
+
beforeReplicaId: 't1'
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
const checkpoint1 = result!.flushed_op;
|
|
263
|
+
const checksumBefore = await storage.getChecksums(checkpoint1, ['global[]']);
|
|
264
|
+
|
|
265
|
+
const result2 = await storage.startBatch(BATCH_OPTIONS, async (batch) => {
|
|
266
|
+
await batch.save({
|
|
267
|
+
sourceTable: TEST_TABLE,
|
|
268
|
+
tag: 'delete',
|
|
269
|
+
before: {
|
|
270
|
+
id: 't2'
|
|
271
|
+
},
|
|
272
|
+
beforeReplicaId: 't2'
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
const checkpoint2 = result2!.flushed_op;
|
|
276
|
+
|
|
277
|
+
await storage.compact(compactOptions);
|
|
278
|
+
|
|
279
|
+
const batchAfter = await oneFromAsync(storage.getBucketDataBatch(checkpoint2, new Map([['global[]', '0']])));
|
|
280
|
+
const dataAfter = batchAfter.batch.data;
|
|
281
|
+
const checksumAfter = await storage.getChecksums(checkpoint2, ['global[]']);
|
|
282
|
+
|
|
283
|
+
expect(batchAfter.targetOp).toEqual(4n);
|
|
284
|
+
expect(dataAfter).toMatchObject([
|
|
285
|
+
{
|
|
286
|
+
checksum: 1874612650,
|
|
287
|
+
op: 'CLEAR',
|
|
288
|
+
op_id: '4'
|
|
289
|
+
}
|
|
290
|
+
]);
|
|
291
|
+
expect(checksumAfter.get('global[]')).toEqual({
|
|
292
|
+
bucket: 'global[]',
|
|
293
|
+
count: 1,
|
|
294
|
+
checksum: 1874612650
|
|
295
|
+
});
|
|
296
|
+
});
|
|
216
297
|
}
|