@powersync/service-core 0.0.0-dev-20250827091123 → 0.0.0-dev-20250828090417
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 -12
- package/dist/api/api-metrics.js +5 -0
- package/dist/api/api-metrics.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.js.map +1 -1
- package/dist/routes/endpoints/socket-route.js +23 -18
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.js +14 -24
- package/dist/routes/endpoints/sync-stream.js.map +1 -1
- package/dist/routes/router.d.ts +3 -3
- package/dist/storage/BucketStorage.d.ts +1 -1
- package/dist/storage/BucketStorage.js.map +1 -1
- package/dist/storage/BucketStorageFactory.d.ts +0 -2
- 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/StorageEngine.d.ts +2 -2
- package/dist/storage/StorageEngine.js.map +1 -1
- package/dist/storage/StorageProvider.d.ts +1 -3
- package/dist/storage/SyncRulesBucketStorage.d.ts +9 -0
- package/dist/storage/SyncRulesBucketStorage.js.map +1 -1
- package/dist/storage/storage-index.d.ts +0 -1
- package/dist/storage/storage-index.js +0 -1
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/sync/BucketChecksumState.d.ts +7 -3
- package/dist/sync/BucketChecksumState.js +5 -4
- 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 +2 -2
- 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/system/ServiceContext.d.ts +0 -3
- package/dist/system/ServiceContext.js +1 -10
- package/dist/system/ServiceContext.js.map +1 -1
- package/dist/util/utils.d.ts +17 -2
- package/dist/util/utils.js +33 -9
- package/dist/util/utils.js.map +1 -1
- package/package.json +13 -13
- package/src/api/api-metrics.ts +6 -0
- package/src/metrics/open-telemetry/util.ts +22 -21
- package/src/routes/compression.ts +75 -0
- package/src/routes/configure-fastify.ts +1 -0
- package/src/routes/endpoints/socket-route.ts +24 -19
- package/src/routes/endpoints/sync-stream.ts +15 -24
- package/src/routes/router.ts +3 -3
- package/src/storage/BucketStorage.ts +2 -2
- package/src/storage/BucketStorageFactory.ts +0 -2
- package/src/storage/ChecksumCache.ts +8 -22
- package/src/storage/StorageEngine.ts +3 -3
- package/src/storage/StorageProvider.ts +1 -3
- package/src/storage/SyncRulesBucketStorage.ts +12 -0
- package/src/storage/storage-index.ts +0 -1
- package/src/sync/BucketChecksumState.ts +12 -6
- package/src/sync/RequestTracker.ts +27 -2
- package/src/sync/sync.ts +3 -3
- package/src/sync/util.ts +1 -1
- package/src/system/ServiceContext.ts +1 -13
- package/src/util/utils.ts +55 -11
- 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 +48 -26
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/events/EventsEngine.d.ts +0 -14
- package/dist/events/EventsEngine.js +0 -33
- package/dist/events/EventsEngine.js.map +0 -1
- package/dist/storage/ReportStorage.d.ts +0 -36
- package/dist/storage/ReportStorage.js +0 -2
- package/dist/storage/ReportStorage.js.map +0 -1
- package/src/events/EventsEngine.ts +0 -38
- package/src/storage/ReportStorage.ts +0 -39
package/CHANGELOG.md
CHANGED
|
@@ -1,30 +1,36 @@
|
|
|
1
1
|
# @powersync/service-core
|
|
2
2
|
|
|
3
|
-
## 0.0.0-dev-
|
|
3
|
+
## 0.0.0-dev-20250828090417
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- c821420: Create a persisted checksum cache when compacting buckets.
|
|
8
|
+
- c27e1c8: Upgrade Node, Sentry, Fastify and OpenTelemetry dependencies.
|
|
9
|
+
- f56acce: Enable permessage-deflate for websockets.
|
|
10
|
+
- 86807d0: Support gzip and zstd compression in http streams.
|
|
4
11
|
|
|
5
12
|
### Patch Changes
|
|
6
13
|
|
|
7
14
|
- d2be184: Refactor interface between service and sync rule bindings in preparation for sync streams.
|
|
8
15
|
- 29a368e: Fix inconsistencies between binary data being requested and actually being sent.
|
|
9
|
-
-
|
|
10
|
-
- 0fad466: Added sdk reporting to storage
|
|
11
|
-
- a700ec9: Reporting mongo storage added to storage engine.
|
|
16
|
+
- 6315334: [MongoDB Storage] Increase checksum timeouts
|
|
12
17
|
- 060b829: Update license abbreviation to FSL-1.1-ALv2.
|
|
13
18
|
- d49bebe: - Hooked up the MySQL binlog heartbeat events with the bucket batch keepalive mechanism.
|
|
14
19
|
Heartbeat events will now update the latest keepalive timestamp in the sync rules.
|
|
15
20
|
- Updated dependencies [b0b8ae9]
|
|
16
21
|
- Updated dependencies [d2be184]
|
|
17
|
-
- Updated dependencies [f1d187b]
|
|
18
|
-
- Updated dependencies [0fad466]
|
|
19
22
|
- Updated dependencies [5284fb5]
|
|
23
|
+
- Updated dependencies [18435a4]
|
|
20
24
|
- Updated dependencies [5284fb5]
|
|
21
|
-
- Updated dependencies [
|
|
25
|
+
- Updated dependencies [f56acce]
|
|
26
|
+
- Updated dependencies [6fd0242]
|
|
27
|
+
- Updated dependencies [86807d0]
|
|
22
28
|
- Updated dependencies [060b829]
|
|
23
|
-
- @powersync/service-sync-rules@0.0.0-dev-
|
|
24
|
-
- @powersync/service-
|
|
25
|
-
- @powersync/
|
|
26
|
-
- @powersync/
|
|
27
|
-
- @powersync/service-jsonbig@0.0.0-dev-
|
|
29
|
+
- @powersync/service-sync-rules@0.0.0-dev-20250828090417
|
|
30
|
+
- @powersync/service-rsocket-router@0.0.0-dev-20250828090417
|
|
31
|
+
- @powersync/service-types@0.0.0-dev-20250828090417
|
|
32
|
+
- @powersync/lib-services-framework@0.0.0-dev-20250828090417
|
|
33
|
+
- @powersync/service-jsonbig@0.0.0-dev-20250828090417
|
|
28
34
|
|
|
29
35
|
## 1.14.0
|
|
30
36
|
|
package/dist/api/api-metrics.js
CHANGED
|
@@ -9,6 +9,11 @@ export function createCoreAPIMetrics(engine) {
|
|
|
9
9
|
description: 'Uncompressed size of synced data',
|
|
10
10
|
unit: 'bytes'
|
|
11
11
|
});
|
|
12
|
+
engine.createCounter({
|
|
13
|
+
name: APIMetric.DATA_SENT_BYTES,
|
|
14
|
+
description: 'Size of data sent to clients, after compression if applicable',
|
|
15
|
+
unit: 'bytes'
|
|
16
|
+
});
|
|
12
17
|
engine.createCounter({
|
|
13
18
|
name: APIMetric.OPERATIONS_SYNCED,
|
|
14
19
|
description: 'Number of operations synced'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-metrics.js","sourceRoot":"","sources":["../../src/api/api-metrics.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAqB;IACxD,MAAM,CAAC,aAAa,CAAC;QACnB,IAAI,EAAE,SAAS,CAAC,iBAAiB;QACjC,WAAW,EAAE,kCAAkC;QAC/C,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;IAEH,MAAM,CAAC,aAAa,CAAC;QACnB,IAAI,EAAE,SAAS,CAAC,iBAAiB;QACjC,WAAW,EAAE,6BAA6B;KAC3C,CAAC,CAAC;IAEH,MAAM,CAAC,mBAAmB,CAAC;QACzB,IAAI,EAAE,SAAS,CAAC,sBAAsB;QACtC,WAAW,EAAE,uCAAuC;KACrD,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAqB;IAC5D,MAAM,sBAAsB,GAAG,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IAEzF,yFAAyF;IACzF,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC"}
|
|
1
|
+
{"version":3,"file":"api-metrics.js","sourceRoot":"","sources":["../../src/api/api-metrics.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAqB;IACxD,MAAM,CAAC,aAAa,CAAC;QACnB,IAAI,EAAE,SAAS,CAAC,iBAAiB;QACjC,WAAW,EAAE,kCAAkC;QAC/C,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;IAEH,MAAM,CAAC,aAAa,CAAC;QACnB,IAAI,EAAE,SAAS,CAAC,eAAe;QAC/B,WAAW,EAAE,+DAA+D;QAC5E,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;IAEH,MAAM,CAAC,aAAa,CAAC;QACnB,IAAI,EAAE,SAAS,CAAC,iBAAiB;QACjC,WAAW,EAAE,6BAA6B;KAC3C,CAAC,CAAC;IAEH,MAAM,CAAC,mBAAmB,CAAC;QACzB,IAAI,EAAE,SAAS,CAAC,sBAAsB;QACtC,WAAW,EAAE,uCAAuC;KACrD,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAqB;IAC5D,MAAM,sBAAsB,GAAG,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IAEzF,yFAAyF;IACzF,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
1
|
import { ServiceContext } from '../../system/ServiceContext.js';
|
|
2
2
|
import { MetricsFactory } from '../metrics-interfaces.js';
|
|
3
|
-
export interface RuntimeMetadata {
|
|
4
|
-
[key: string]: string | number | undefined;
|
|
5
|
-
}
|
|
6
3
|
export declare function createOpenTelemetryMetricsFactory(context: ServiceContext): MetricsFactory;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
|
|
2
|
-
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';
|
|
3
1
|
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';
|
|
3
|
+
import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
|
|
6
4
|
import { logger } from '@powersync/lib-services-framework';
|
|
5
|
+
import { OpenTelemetryMetricsFactory } from './OpenTelemetryMetricsFactory.js';
|
|
7
6
|
import pkg from '../../../package.json' with { type: 'json' };
|
|
7
|
+
import { resourceFromAttributes } from '@opentelemetry/resources';
|
|
8
8
|
export function createOpenTelemetryMetricsFactory(context) {
|
|
9
9
|
const { configuration, lifeCycleEngine, storageEngine } = context;
|
|
10
10
|
const configuredExporters = [];
|
|
@@ -30,27 +30,32 @@ export function createOpenTelemetryMetricsFactory(context) {
|
|
|
30
30
|
});
|
|
31
31
|
configuredExporters.push(periodicExporter);
|
|
32
32
|
}
|
|
33
|
-
let
|
|
34
|
-
const
|
|
35
|
-
|
|
33
|
+
let resolvedInstanceId;
|
|
34
|
+
const instanceIdPromise = new Promise((resolve) => {
|
|
35
|
+
resolvedInstanceId = resolve;
|
|
36
36
|
});
|
|
37
37
|
lifeCycleEngine.withLifecycle(null, {
|
|
38
38
|
start: async () => {
|
|
39
39
|
const bucketStorage = storageEngine.activeBucketStorage;
|
|
40
40
|
try {
|
|
41
41
|
const instanceId = await bucketStorage.getPowerSyncInstanceId();
|
|
42
|
-
|
|
42
|
+
resolvedInstanceId(instanceId);
|
|
43
43
|
}
|
|
44
44
|
catch (err) {
|
|
45
|
-
|
|
45
|
+
resolvedInstanceId('Unknown');
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
|
+
const resource = resourceFromAttributes({
|
|
50
|
+
['service']: 'PowerSync',
|
|
51
|
+
['service.version']: pkg.version,
|
|
52
|
+
['instance_id']: instanceIdPromise
|
|
53
|
+
});
|
|
54
|
+
// This triggers OpenTelemetry to resolve the async attributes (instanceIdPromise).
|
|
55
|
+
// This will never reject, and we don't specifically need to wait for it.
|
|
56
|
+
resource.waitForAsyncAttributes?.();
|
|
49
57
|
const meterProvider = new MeterProvider({
|
|
50
|
-
resource
|
|
51
|
-
['service']: 'PowerSync',
|
|
52
|
-
['service.version']: pkg.version
|
|
53
|
-
}, runtimeMetadata),
|
|
58
|
+
resource,
|
|
54
59
|
readers: configuredExporters
|
|
55
60
|
});
|
|
56
61
|
lifeCycleEngine.withLifecycle(meterProvider, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/metrics/open-telemetry/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/metrics/open-telemetry/util.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type Negotiator from 'negotiator';
|
|
2
|
+
import { Readable } from 'node:stream';
|
|
3
|
+
import { RequestTracker } from '../sync/RequestTracker.js';
|
|
4
|
+
/**
|
|
5
|
+
* Compress a streamed response.
|
|
6
|
+
*
|
|
7
|
+
* `@fastify/compress` can do something similar, but does not appear to work as well on streamed responses.
|
|
8
|
+
* The manual implementation is simple enough, and gives us more control over the low-level details.
|
|
9
|
+
*
|
|
10
|
+
* @param negotiator Negotiator from the request, to negotiate response encoding
|
|
11
|
+
* @param stream plain-text stream
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
export declare function maybeCompressResponseStream(negotiator: Negotiator, stream: Readable, tracker: RequestTracker): {
|
|
15
|
+
stream: Readable;
|
|
16
|
+
encodingHeaders: {
|
|
17
|
+
'content-encoding'?: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { PassThrough, pipeline, Transform } from 'node:stream';
|
|
2
|
+
import * as zlib from 'node:zlib';
|
|
3
|
+
/**
|
|
4
|
+
* Compress a streamed response.
|
|
5
|
+
*
|
|
6
|
+
* `@fastify/compress` can do something similar, but does not appear to work as well on streamed responses.
|
|
7
|
+
* The manual implementation is simple enough, and gives us more control over the low-level details.
|
|
8
|
+
*
|
|
9
|
+
* @param negotiator Negotiator from the request, to negotiate response encoding
|
|
10
|
+
* @param stream plain-text stream
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
export function maybeCompressResponseStream(negotiator, stream, tracker) {
|
|
14
|
+
const encoding = negotiator.encoding(['identity', 'gzip', 'zstd'], { preferred: 'zstd' });
|
|
15
|
+
const transform = createCompressionTransform(encoding);
|
|
16
|
+
if (transform == null) {
|
|
17
|
+
// No matching compression supported - leave stream as-is
|
|
18
|
+
return {
|
|
19
|
+
stream,
|
|
20
|
+
encodingHeaders: {}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
tracker.setCompressed(encoding);
|
|
25
|
+
return {
|
|
26
|
+
stream: transformStream(stream, transform, tracker),
|
|
27
|
+
encodingHeaders: { 'content-encoding': encoding }
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function createCompressionTransform(encoding) {
|
|
32
|
+
if (encoding == 'zstd') {
|
|
33
|
+
// Available since Node v23.8.0, v22.15.0
|
|
34
|
+
// This does the actual compression in a background thread pool.
|
|
35
|
+
return zlib.createZstdCompress({
|
|
36
|
+
// We need to flush the frame after every new input chunk, to avoid delaying data
|
|
37
|
+
// in the output stream.
|
|
38
|
+
flush: zlib.constants.ZSTD_e_flush,
|
|
39
|
+
params: {
|
|
40
|
+
// Default compression level is 3. We reduce this slightly to limit CPU overhead
|
|
41
|
+
[zlib.constants.ZSTD_c_compressionLevel]: 2
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
else if (encoding == 'gzip') {
|
|
46
|
+
return zlib.createGzip({
|
|
47
|
+
// We need to flush the frame after every new input chunk, to avoid delaying data
|
|
48
|
+
// in the output stream.
|
|
49
|
+
flush: zlib.constants.Z_SYNC_FLUSH
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
function transformStream(source, transform, tracker) {
|
|
55
|
+
// pipe does not forward error events automatically, resulting in unhandled error
|
|
56
|
+
// events. This forwards it.
|
|
57
|
+
const out = new PassThrough();
|
|
58
|
+
const trackingTransform = new Transform({
|
|
59
|
+
transform(chunk, _encoding, callback) {
|
|
60
|
+
tracker.addCompressedDataSent(chunk.length);
|
|
61
|
+
callback(null, chunk);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
pipeline(source, transform, trackingTransform, out, (err) => {
|
|
65
|
+
if (err)
|
|
66
|
+
out.destroy(err);
|
|
67
|
+
});
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=compression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression.js","sourceRoot":"","sources":["../../src/routes/compression.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAY,SAAS,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC;;;;;;;;;GASG;AACH,MAAM,UAAU,2BAA2B,CACzC,UAAsB,EACtB,MAAgB,EAChB,OAAuB;IAEvB,MAAM,QAAQ,GAAI,UAAkB,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IACnG,MAAM,SAAS,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;QACtB,yDAAyD;QACzD,OAAO;YACL,MAAM;YACN,eAAe,EAAE,EAAE;SACpB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAChC,OAAO;YACL,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC;YACnD,eAAe,EAAE,EAAE,kBAAkB,EAAE,QAAQ,EAAE;SAClD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B,CAAC,QAA4B;IAC9D,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;QACvB,yCAAyC;QACzC,gEAAgE;QAChE,OAAO,IAAI,CAAC,kBAAkB,CAAC;YAC7B,iFAAiF;YACjF,wBAAwB;YACxB,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY;YAClC,MAAM,EAAE;gBACN,gFAAgF;gBAChF,CAAC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,EAAE,CAAC;aAC5C;SACF,CAAC,CAAC;IACL,CAAC;SAAM,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,UAAU,CAAC;YACrB,iFAAiF;YACjF,wBAAwB;YACxB,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY;SACnC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,eAAe,CAAC,MAAgB,EAAE,SAAoB,EAAE,OAAuB;IACtF,iFAAiF;IACjF,4BAA4B;IAC5B,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;IAC9B,MAAM,iBAAiB,GAAG,IAAI,SAAS,CAAC;QACtC,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ;YAClC,OAAO,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC5C,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxB,CAAC;KACF,CAAC,CAAC;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;QAC1D,IAAI,GAAG;YAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure-fastify.js","sourceRoot":"","sources":["../../src/routes/configure-fastify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"configure-fastify.js","sourceRoot":"","sources":["../../src/routes/configure-fastify.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,8BAA8B,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAI5F,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAA4B,MAAM,YAAY,CAAC;AA0B9E,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,GAAG,EAAE;QACH,MAAM,EAAE,CAAC,GAAG,YAAY,EAAE,GAAG,iBAAiB,EAAE,GAAG,iBAAiB,EAAE,GAAG,aAAa,CAAC;QACvF,aAAa,EAAE;YACb,WAAW,EAAE,EAAE;YACf,eAAe,EAAE,EAAE;SACpB;KACF;IACD,WAAW,EAAE;QACX,MAAM,EAAE,CAAC,GAAG,kBAAkB,CAAC;QAC/B,aAAa,EAAE;YACb,WAAW,EAAE,GAAG;YAChB,eAAe,EAAE,CAAC;SACnB;KACF;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA+B,EAAE,OAA4B;IAClG,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,qBAAqB,EAAE,GAAG,OAAO,CAAC;IAEpE,MAAM,eAAe,GAAoB,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QAClE,OAAO;YACL,OAAO,EAAE,SAAS;YAClB,eAAe,EAAE,eAAe;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC;IACJ,CAAC,CAAC;IAEF;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,WAAW,YAAY;QAC1C,qBAAqB,CAAC,YAAY,EAAE,eAAe,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,IAAI,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7G,8BAA8B,CAAC,YAAY,CAAC,CAAC;QAE7C,uCAAuC;QACvC,YAAY,CAAC,OAAO,CAClB,WAAW,EACX,sBAAsB,CAAC,MAAM,CAAC,GAAG,EAAE,aAAa,IAAI,qBAAqB,CAAC,GAAG,CAAC,aAAa,CAAC,CAC7F,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,qDAAqD;IACrD,MAAM,CAAC,QAAQ,CAAC,KAAK,WAAW,YAAY;QAC1C,qBAAqB,CACnB,YAAY,EACZ,eAAe,EACf,MAAM,CAAC,WAAW,EAAE,MAAM,IAAI,qBAAqB,CAAC,WAAW,CAAC,MAAM,CACvE,CAAC;QACF,uCAAuC;QACvC,YAAY,CAAC,OAAO,CAClB,WAAW,EACX,sBAAsB,CAAC,MAAM,CAAC,WAAW,EAAE,aAAa,IAAI,qBAAqB,CAAC,WAAW,CAAC,aAAa,CAAC,CAC7G,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -2,27 +2,19 @@ import { ErrorCode, errors, schema } from '@powersync/lib-services-framework';
|
|
|
2
2
|
import * as sync from '../../sync/sync-index.js';
|
|
3
3
|
import * as util from '../../util/util-index.js';
|
|
4
4
|
import { SyncRoutes } from './sync-stream.js';
|
|
5
|
-
import { APIMetric
|
|
5
|
+
import { APIMetric } from '@powersync/service-types';
|
|
6
6
|
export const syncStreamReactive = (router) => router.reactiveStream(SyncRoutes.STREAM, {
|
|
7
7
|
validator: schema.createTsCodecValidator(util.StreamingSyncRequest, { allowAdditional: true }),
|
|
8
|
-
handler: async ({ context, params, responder, observer, initialN, signal: upstreamSignal }) => {
|
|
8
|
+
handler: async ({ context, params, responder, observer, initialN, signal: upstreamSignal, connection }) => {
|
|
9
9
|
const { service_context, logger } = context;
|
|
10
10
|
const { routerEngine, metricsEngine, syncContext } = service_context;
|
|
11
|
-
const streamStart = Date.now();
|
|
12
11
|
logger.defaultMeta = {
|
|
13
12
|
...logger.defaultMeta,
|
|
14
13
|
user_id: context.token_payload?.sub,
|
|
15
14
|
client_id: params.client_id,
|
|
16
15
|
user_agent: context.user_agent
|
|
17
16
|
};
|
|
18
|
-
const
|
|
19
|
-
client_id: params.client_id ?? '',
|
|
20
|
-
user_id: context.user_id,
|
|
21
|
-
user_agent: context.user_agent,
|
|
22
|
-
// At this point the token_payload is guaranteed to be present
|
|
23
|
-
jwt_exp: new Date(context.token_payload.exp * 1000),
|
|
24
|
-
connected_at: new Date(streamStart)
|
|
25
|
-
};
|
|
17
|
+
const streamStart = Date.now();
|
|
26
18
|
// Best effort guess on why the stream was closed.
|
|
27
19
|
// We use the `??=` operator everywhere, so that we catch the first relevant
|
|
28
20
|
// event, which is usually the most specific.
|
|
@@ -69,13 +61,19 @@ export const syncStreamReactive = (router) => router.reactiveStream(SyncRoutes.S
|
|
|
69
61
|
controller.abort();
|
|
70
62
|
});
|
|
71
63
|
metricsEngine.getUpDownCounter(APIMetric.CONCURRENT_CONNECTIONS).add(1);
|
|
72
|
-
service_context.eventsEngine.emit(event_types.EventsEngineEventType.SDK_CONNECT_EVENT, sdkData);
|
|
73
64
|
const tracker = new sync.RequestTracker(metricsEngine);
|
|
65
|
+
if (connection.tracker.encoding) {
|
|
66
|
+
// Must be set before we start the stream
|
|
67
|
+
tracker.setCompressed(connection.tracker.encoding);
|
|
68
|
+
}
|
|
74
69
|
try {
|
|
75
70
|
for await (const data of sync.streamResponse({
|
|
76
71
|
syncContext: syncContext,
|
|
77
72
|
bucketStorage: bucketStorage,
|
|
78
|
-
syncRules:
|
|
73
|
+
syncRules: {
|
|
74
|
+
syncRules,
|
|
75
|
+
version: bucketStorage.group_id
|
|
76
|
+
},
|
|
79
77
|
params: {
|
|
80
78
|
...params
|
|
81
79
|
},
|
|
@@ -99,7 +97,7 @@ export const syncStreamReactive = (router) => router.reactiveStream(SyncRoutes.S
|
|
|
99
97
|
const serialized = sync.syncLineToBson(data);
|
|
100
98
|
responder.onNext({ data: serialized }, false);
|
|
101
99
|
requestedN--;
|
|
102
|
-
tracker.
|
|
100
|
+
tracker.addPlaintextDataSynced(serialized.length);
|
|
103
101
|
}
|
|
104
102
|
if (requestedN <= 0 && !signal.aborted) {
|
|
105
103
|
await new Promise((resolve) => {
|
|
@@ -137,16 +135,23 @@ export const syncStreamReactive = (router) => router.reactiveStream(SyncRoutes.S
|
|
|
137
135
|
responder.onComplete();
|
|
138
136
|
removeStopHandler();
|
|
139
137
|
disposer();
|
|
138
|
+
if (connection.tracker.encoding) {
|
|
139
|
+
// Technically, this may not be unique to this specific stream, since there could be multiple
|
|
140
|
+
// rsocket streams on the same websocket connection. We don't have a way to track compressed bytes
|
|
141
|
+
// on individual streams, and we generally expect 1 stream per connection, so this is a reasonable
|
|
142
|
+
// approximation.
|
|
143
|
+
// If there are multiple streams, bytes written would be split arbitrarily across them, but the
|
|
144
|
+
// total should be correct.
|
|
145
|
+
// For non-compressed cases, this is tracked by the stream itself.
|
|
146
|
+
const socketBytes = connection.tracker.getBytesWritten();
|
|
147
|
+
tracker.addCompressedDataSent(socketBytes);
|
|
148
|
+
}
|
|
140
149
|
logger.info(`Sync stream complete`, {
|
|
141
150
|
...tracker.getLogMeta(),
|
|
142
151
|
stream_ms: Date.now() - streamStart,
|
|
143
152
|
close_reason: closeReason ?? 'unknown'
|
|
144
153
|
});
|
|
145
154
|
metricsEngine.getUpDownCounter(APIMetric.CONCURRENT_CONNECTIONS).add(-1);
|
|
146
|
-
service_context.eventsEngine.emit(event_types.EventsEngineEventType.SDK_DISCONNECT_EVENT, {
|
|
147
|
-
...sdkData,
|
|
148
|
-
disconnected_at: new Date()
|
|
149
|
-
});
|
|
150
155
|
}
|
|
151
156
|
}
|
|
152
157
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-route.js","sourceRoot":"","sources":["../../../src/routes/endpoints/socket-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"socket-route.js","sourceRoot":"","sources":["../../../src/routes/endpoints/socket-route.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { ErrorCode, errors, router, schema } from '@powersync/lib-services-framework';
|
|
2
|
-
import { Readable } from 'stream';
|
|
3
2
|
import Negotiator from 'negotiator';
|
|
3
|
+
import { Readable } from 'stream';
|
|
4
4
|
import * as sync from '../../sync/sync-index.js';
|
|
5
5
|
import * as util from '../../util/util-index.js';
|
|
6
6
|
import { authUser } from '../auth.js';
|
|
7
7
|
import { routeDefinition } from '../router.js';
|
|
8
|
-
import { APIMetric
|
|
8
|
+
import { APIMetric } from '@powersync/service-types';
|
|
9
|
+
import { maybeCompressResponseStream } from '../compression.js';
|
|
9
10
|
export var SyncRoutes;
|
|
10
11
|
(function (SyncRoutes) {
|
|
11
12
|
SyncRoutes["STREAM"] = "/sync/stream";
|
|
@@ -19,15 +20,16 @@ export const syncStreamed = routeDefinition({
|
|
|
19
20
|
authorize: authUser,
|
|
20
21
|
validator: schema.createTsCodecValidator(util.StreamingSyncRequest, { allowAdditional: true }),
|
|
21
22
|
handler: async (payload) => {
|
|
22
|
-
const { service_context, logger
|
|
23
|
+
const { service_context, logger } = payload.context;
|
|
23
24
|
const { routerEngine, storageEngine, metricsEngine, syncContext } = service_context;
|
|
24
25
|
const headers = payload.request.headers;
|
|
25
26
|
const userAgent = headers['x-user-agent'] ?? headers['user-agent'];
|
|
26
27
|
const clientId = payload.params.client_id;
|
|
27
28
|
const streamStart = Date.now();
|
|
29
|
+
const negotiator = new Negotiator(payload.request);
|
|
28
30
|
// This falls back to JSON unless there's preference for the bson-stream in the Accept header.
|
|
29
31
|
const useBson = payload.request.headers.accept
|
|
30
|
-
?
|
|
32
|
+
? negotiator.mediaType(supportedContentTypes) == concatenatedBsonContentType
|
|
31
33
|
: false;
|
|
32
34
|
logger.defaultMeta = {
|
|
33
35
|
...logger.defaultMeta,
|
|
@@ -36,14 +38,6 @@ export const syncStreamed = routeDefinition({
|
|
|
36
38
|
user_id: payload.context.user_id,
|
|
37
39
|
bson: useBson
|
|
38
40
|
};
|
|
39
|
-
const sdkData = {
|
|
40
|
-
client_id: clientId ?? '',
|
|
41
|
-
user_id: payload.context.user_id,
|
|
42
|
-
user_agent: userAgent,
|
|
43
|
-
// At this point the token_payload is guaranteed to be present
|
|
44
|
-
jwt_exp: new Date(token_payload.exp * 1000),
|
|
45
|
-
connected_at: new Date(streamStart)
|
|
46
|
-
};
|
|
47
41
|
if (routerEngine.closed) {
|
|
48
42
|
throw new errors.ServiceError({
|
|
49
43
|
status: 503,
|
|
@@ -64,11 +58,13 @@ export const syncStreamed = routeDefinition({
|
|
|
64
58
|
const tracker = new sync.RequestTracker(metricsEngine);
|
|
65
59
|
try {
|
|
66
60
|
metricsEngine.getUpDownCounter(APIMetric.CONCURRENT_CONNECTIONS).add(1);
|
|
67
|
-
service_context.eventsEngine.emit(event_types.EventsEngineEventType.SDK_CONNECT_EVENT, sdkData);
|
|
68
61
|
const syncLines = sync.streamResponse({
|
|
69
62
|
syncContext: syncContext,
|
|
70
63
|
bucketStorage,
|
|
71
|
-
syncRules:
|
|
64
|
+
syncRules: {
|
|
65
|
+
syncRules,
|
|
66
|
+
version: bucketStorage.group_id
|
|
67
|
+
},
|
|
72
68
|
params: payload.params,
|
|
73
69
|
token: payload.context.token_payload,
|
|
74
70
|
tracker,
|
|
@@ -77,10 +73,11 @@ export const syncStreamed = routeDefinition({
|
|
|
77
73
|
isEncodingAsBson: useBson
|
|
78
74
|
});
|
|
79
75
|
const byteContents = useBson ? sync.bsonLines(syncLines) : sync.ndjson(syncLines);
|
|
80
|
-
const
|
|
76
|
+
const plainStream = Readable.from(sync.transformToBytesTracked(byteContents, tracker), {
|
|
81
77
|
objectMode: false,
|
|
82
78
|
highWaterMark: 16 * 1024
|
|
83
79
|
});
|
|
80
|
+
const { stream, encodingHeaders } = maybeCompressResponseStream(negotiator, plainStream, tracker);
|
|
84
81
|
// Best effort guess on why the stream was closed.
|
|
85
82
|
// We use the `??=` operator everywhere, so that we catch the first relevant
|
|
86
83
|
// event, which is usually the most specific.
|
|
@@ -109,7 +106,8 @@ export const syncStreamed = routeDefinition({
|
|
|
109
106
|
return new router.RouterResponse({
|
|
110
107
|
status: 200,
|
|
111
108
|
headers: {
|
|
112
|
-
'Content-Type': useBson ? concatenatedBsonContentType : ndJsonContentType
|
|
109
|
+
'Content-Type': useBson ? concatenatedBsonContentType : ndJsonContentType,
|
|
110
|
+
...encodingHeaders
|
|
113
111
|
},
|
|
114
112
|
data: stream,
|
|
115
113
|
afterSend: async (details) => {
|
|
@@ -118,10 +116,6 @@ export const syncStreamed = routeDefinition({
|
|
|
118
116
|
}
|
|
119
117
|
controller.abort();
|
|
120
118
|
metricsEngine.getUpDownCounter(APIMetric.CONCURRENT_CONNECTIONS).add(-1);
|
|
121
|
-
service_context.eventsEngine.emit(event_types.EventsEngineEventType.SDK_DISCONNECT_EVENT, {
|
|
122
|
-
...sdkData,
|
|
123
|
-
disconnected_at: new Date()
|
|
124
|
-
});
|
|
125
119
|
logger.info(`Sync stream complete`, {
|
|
126
120
|
...tracker.getLogMeta(),
|
|
127
121
|
stream_ms: Date.now() - streamStart,
|
|
@@ -133,10 +127,6 @@ export const syncStreamed = routeDefinition({
|
|
|
133
127
|
catch (ex) {
|
|
134
128
|
controller.abort();
|
|
135
129
|
metricsEngine.getUpDownCounter(APIMetric.CONCURRENT_CONNECTIONS).add(-1);
|
|
136
|
-
service_context.eventsEngine.emit(event_types.EventsEngineEventType.SDK_DISCONNECT_EVENT, {
|
|
137
|
-
...sdkData,
|
|
138
|
-
disconnected_at: new Date()
|
|
139
|
-
});
|
|
140
130
|
}
|
|
141
131
|
}
|
|
142
132
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-stream.js","sourceRoot":"","sources":["../../../src/routes/endpoints/sync-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AACtF,OAAO,
|
|
1
|
+
{"version":3,"file":"sync-stream.js","sourceRoot":"","sources":["../../../src/routes/endpoints/sync-stream.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/router.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { router, Logger } from '@powersync/lib-services-framework';
|
|
2
2
|
import type { JwtPayload } from '../auth/auth-index.js';
|
|
3
3
|
import { ServiceContext } from '../system/ServiceContext.js';
|
|
4
4
|
/**
|
|
@@ -23,10 +23,10 @@ export type BasicRouterRequest = {
|
|
|
23
23
|
protocol: string;
|
|
24
24
|
hostname: string;
|
|
25
25
|
};
|
|
26
|
-
export type
|
|
26
|
+
export type ConextProviderOptions = {
|
|
27
27
|
logger: Logger;
|
|
28
28
|
};
|
|
29
|
-
export type ContextProvider = (request: BasicRouterRequest, options:
|
|
29
|
+
export type ContextProvider = (request: BasicRouterRequest, options: ConextProviderOptions) => Promise<Context>;
|
|
30
30
|
export type RequestEndpoint<I, O, C = Context, Payload = RequestEndpointHandlerPayload<I, C, BasicRouterRequest>> = router.Endpoint<I, O, C, Payload> & {};
|
|
31
31
|
export type RequestEndpointHandlerPayload<I = any, C = Context, Request = BasicRouterRequest> = router.EndpointHandlerPayload<I, C> & {
|
|
32
32
|
request: Request;
|
|
@@ -34,4 +34,4 @@ export declare enum SyncRuleState {
|
|
|
34
34
|
}
|
|
35
35
|
export declare const DEFAULT_DOCUMENT_BATCH_LIMIT = 1000;
|
|
36
36
|
export declare const DEFAULT_DOCUMENT_CHUNK_LIMIT_BYTES: number;
|
|
37
|
-
export declare function mergeToast(record: ToastableSqliteRow
|
|
37
|
+
export declare function mergeToast<V>(record: ToastableSqliteRow<V>, persisted: ToastableSqliteRow<V>): ToastableSqliteRow<V>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BucketStorage.js","sourceRoot":"","sources":["../../src/storage/BucketStorage.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,aAkCX;AAlCD,WAAY,aAAa;IACvB;;;;;OAKG;IACH,0CAAyB,CAAA;IAEzB;;;;OAIG;IACH,kCAAiB,CAAA;IACjB;;;OAGG;IACH,8BAAa,CAAA;IACb;;;OAGG;IACH,0CAAyB,CAAA;IAEzB;;;;;;OAMG;IACH,oCAAmB,CAAA;AACrB,CAAC,EAlCW,aAAa,KAAb,aAAa,QAkCxB;AAED,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AACjD,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAElE,MAAM,UAAU,UAAU,
|
|
1
|
+
{"version":3,"file":"BucketStorage.js","sourceRoot":"","sources":["../../src/storage/BucketStorage.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,aAkCX;AAlCD,WAAY,aAAa;IACvB;;;;;OAKG;IACH,0CAAyB,CAAA;IAEzB;;;;OAIG;IACH,kCAAiB,CAAA;IACjB;;;OAGG;IACH,8BAAa,CAAA;IACb;;;OAGG;IACH,0CAAyB,CAAA;IAEzB;;;;;;OAMG;IACH,oCAAmB,CAAA;AACrB,CAAC,EAlCW,aAAa,KAAb,aAAa,QAkCxB;AAED,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AACjD,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAElE,MAAM,UAAU,UAAU,CAAI,MAA6B,EAAE,SAAgC;IAC3F,MAAM,SAAS,GAA0B,EAAE,CAAC;IAC5C,KAAK,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;YACtC,SAAS,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -3,7 +3,6 @@ import { ParseSyncRulesOptions, PersistedSyncRules, PersistedSyncRulesContent }
|
|
|
3
3
|
import { ReplicationEventPayload } from './ReplicationEventPayload.js';
|
|
4
4
|
import { ReplicationLock } from './ReplicationLock.js';
|
|
5
5
|
import { SyncRulesBucketStorage } from './SyncRulesBucketStorage.js';
|
|
6
|
-
import { ReportStorage } from './ReportStorage.js';
|
|
7
6
|
/**
|
|
8
7
|
* Represents a configured storage provider.
|
|
9
8
|
*
|
|
@@ -144,4 +143,3 @@ export interface TestStorageOptions {
|
|
|
144
143
|
doNotClear?: boolean;
|
|
145
144
|
}
|
|
146
145
|
export type TestStorageFactory = (options?: TestStorageOptions) => Promise<BucketStorageFactory>;
|
|
147
|
-
export type TestReportStorageFactory = (options?: TestStorageOptions) => Promise<ReportStorage>;
|
|
@@ -1,28 +1,12 @@
|
|
|
1
1
|
import { BucketChecksum } from '../util/protocol-types.js';
|
|
2
|
-
import { ChecksumMap, InternalOpId } from '../util/utils.js';
|
|
3
|
-
export interface PartialChecksum {
|
|
4
|
-
bucket: string;
|
|
5
|
-
/**
|
|
6
|
-
* 32-bit unsigned hash.
|
|
7
|
-
*/
|
|
8
|
-
partialChecksum: number;
|
|
9
|
-
/**
|
|
10
|
-
* Count of operations - informational only.
|
|
11
|
-
*/
|
|
12
|
-
partialCount: number;
|
|
13
|
-
/**
|
|
14
|
-
* True if the queried operations contains (starts with) a CLEAR
|
|
15
|
-
* operation, indicating that the partial checksum is the full
|
|
16
|
-
* checksum, and must not be added to a previously-cached checksum.
|
|
17
|
-
*/
|
|
18
|
-
isFullChecksum: boolean;
|
|
19
|
-
}
|
|
2
|
+
import { ChecksumMap, InternalOpId, PartialChecksum } from '../util/utils.js';
|
|
20
3
|
export interface FetchPartialBucketChecksum {
|
|
21
4
|
bucket: string;
|
|
22
5
|
start?: InternalOpId;
|
|
23
6
|
end: InternalOpId;
|
|
24
7
|
}
|
|
25
|
-
export type
|
|
8
|
+
export type PartialOrFullChecksum = PartialChecksum | BucketChecksum;
|
|
9
|
+
export type PartialChecksumMap = Map<string, PartialOrFullChecksum>;
|
|
26
10
|
export type FetchChecksums = (batch: FetchPartialBucketChecksum[]) => Promise<PartialChecksumMap>;
|
|
27
11
|
export interface ChecksumCacheOptions {
|
|
28
12
|
/**
|
|
@@ -56,6 +40,7 @@ export declare class ChecksumCache {
|
|
|
56
40
|
private bucketCheckpoints;
|
|
57
41
|
private fetchChecksums;
|
|
58
42
|
constructor(options: ChecksumCacheOptions);
|
|
43
|
+
clear(): void;
|
|
59
44
|
getChecksums(checkpoint: InternalOpId, buckets: string[]): Promise<BucketChecksum[]>;
|
|
60
45
|
/**
|
|
61
46
|
* Get bucket checksums for a checkpoint.
|
|
@@ -65,6 +65,10 @@ export class ChecksumCache {
|
|
|
65
65
|
allowStale: false
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
|
+
clear() {
|
|
69
|
+
this.cache.clear();
|
|
70
|
+
this.bucketCheckpoints.clear();
|
|
71
|
+
}
|
|
68
72
|
async getChecksums(checkpoint, buckets) {
|
|
69
73
|
const checksums = await this.getChecksumMap(checkpoint, buckets);
|
|
70
74
|
// Return results in the same order as the request
|