@powersync/service-core 1.20.3 → 1.20.5
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 +30 -0
- package/dist/api/RouteAPI.d.ts +14 -0
- package/dist/api/api-index.d.ts +1 -1
- package/dist/api/api-index.js +1 -1
- package/dist/api/api-index.js.map +1 -1
- package/dist/api/api-metrics.js.map +1 -1
- package/dist/api/diagnostics.js +16 -14
- package/dist/api/diagnostics.js.map +1 -1
- package/dist/auth/CachedKeyCollector.js +1 -1
- package/dist/auth/CachedKeyCollector.js.map +1 -1
- package/dist/auth/CompoundKeyCollector.js.map +1 -1
- package/dist/auth/KeyStore.js.map +1 -1
- package/dist/auth/RemoteJWKSCollector.js.map +1 -1
- package/dist/auth/StaticKeyCollector.d.ts +1 -1
- package/dist/auth/StaticKeyCollector.js.map +1 -1
- package/dist/auth/StaticSupabaseKeyCollector.d.ts +1 -1
- package/dist/auth/StaticSupabaseKeyCollector.js.map +1 -1
- package/dist/entry/commands/teardown-action.js +1 -1
- package/dist/entry/commands/teardown-action.js.map +1 -1
- package/dist/entry/entry-index.d.ts +1 -1
- package/dist/entry/entry-index.js +1 -1
- package/dist/entry/entry-index.js.map +1 -1
- package/dist/events/EventsEngine.js +1 -1
- package/dist/events/EventsEngine.js.map +1 -1
- package/dist/metrics/MetricsEngine.d.ts +1 -1
- package/dist/metrics/RollingBucketMax.d.ts +28 -0
- package/dist/metrics/RollingBucketMax.js +80 -0
- package/dist/metrics/RollingBucketMax.js.map +1 -0
- package/dist/metrics/metrics-index.d.ts +3 -2
- package/dist/metrics/metrics-index.js +3 -2
- package/dist/metrics/metrics-index.js.map +1 -1
- package/dist/metrics/open-telemetry/util.js +1 -1
- package/dist/metrics/open-telemetry/util.js.map +1 -1
- package/dist/metrics/register-metrics.js +2 -2
- package/dist/metrics/register-metrics.js.map +1 -1
- package/dist/modules/AbstractModule.d.ts +1 -1
- package/dist/modules/AbstractModule.js.map +1 -1
- package/dist/modules/modules-index.d.ts +1 -1
- package/dist/modules/modules-index.js +1 -1
- package/dist/modules/modules-index.js.map +1 -1
- package/dist/replication/AbstractReplicationJob.d.ts +2 -2
- package/dist/replication/AbstractReplicator.d.ts +1 -1
- package/dist/replication/AbstractReplicator.js +10 -7
- package/dist/replication/AbstractReplicator.js.map +1 -1
- package/dist/replication/ReplicationLagTracker.d.ts +50 -0
- package/dist/replication/ReplicationLagTracker.js +78 -0
- package/dist/replication/ReplicationLagTracker.js.map +1 -0
- package/dist/replication/replication-index.d.ts +3 -2
- package/dist/replication/replication-index.js +3 -2
- package/dist/replication/replication-index.js.map +1 -1
- package/dist/replication/replication-metrics.js.map +1 -1
- package/dist/routes/configure-fastify.d.ts +59 -32
- package/dist/routes/endpoints/admin.d.ts +108 -54
- package/dist/routes/endpoints/sync-rules.js +3 -3
- package/dist/routes/endpoints/sync-rules.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.d.ts +10 -10
- package/dist/routes/hooks.js +1 -1
- package/dist/routes/hooks.js.map +1 -1
- package/dist/routes/route-register.js.map +1 -1
- package/dist/storage/BucketStorageBatch.d.ts +1 -1
- package/dist/storage/BucketStorageFactory.d.ts +5 -3
- package/dist/storage/BucketStorageFactory.js +10 -8
- package/dist/storage/BucketStorageFactory.js.map +1 -1
- package/dist/storage/ChecksumCache.js.map +1 -1
- package/dist/storage/PersistedSyncRulesContent.js +14 -2
- package/dist/storage/PersistedSyncRulesContent.js.map +1 -1
- package/dist/storage/ReplicationEventPayload.d.ts +1 -1
- package/dist/storage/SourceTable.d.ts +1 -1
- package/dist/storage/SourceTable.js.map +1 -1
- package/dist/storage/storage-index.d.ts +8 -8
- package/dist/storage/storage-index.js +8 -8
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/storage/storage-metrics.js.map +1 -1
- package/dist/streams/streams-index.d.ts +2 -2
- package/dist/streams/streams-index.js +2 -2
- package/dist/streams/streams-index.js.map +1 -1
- package/dist/sync/BucketChecksumState.js +4 -19
- package/dist/sync/BucketChecksumState.js.map +1 -1
- package/dist/sync/RequestTracker.js +1 -1
- package/dist/sync/RequestTracker.js.map +1 -1
- package/dist/sync/sync-index.d.ts +2 -2
- package/dist/sync/sync-index.js +2 -2
- package/dist/sync/sync-index.js.map +1 -1
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/util.js.map +1 -1
- package/dist/system/ServiceContext.d.ts +1 -1
- package/dist/system/ServiceContext.js +1 -1
- package/dist/system/ServiceContext.js.map +1 -1
- package/dist/util/config/collectors/impl/base64-config-collector.d.ts +1 -1
- package/dist/util/config/collectors/impl/base64-config-collector.js.map +1 -1
- package/dist/util/config/collectors/impl/filesystem-config-collector.d.ts +1 -1
- package/dist/util/config/collectors/impl/filesystem-config-collector.js +1 -1
- package/dist/util/config/collectors/impl/filesystem-config-collector.js.map +1 -1
- package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -1
- package/dist/util/config.js +1 -1
- package/dist/util/config.js.map +1 -1
- package/dist/util/errors.d.ts +3 -0
- package/dist/util/errors.js +15 -0
- package/dist/util/errors.js.map +1 -0
- package/dist/util/protocol-types.d.ts +2 -2
- package/dist/util/util-index.d.ts +1 -1
- package/dist/util/util-index.js +1 -1
- package/dist/util/util-index.js.map +1 -1
- package/dist/util/utils.d.ts +1 -1
- package/package.json +6 -6
- package/src/api/RouteAPI.ts +17 -0
- package/src/api/api-index.ts +1 -1
- package/src/api/api-metrics.ts +1 -1
- package/src/api/diagnostics.ts +18 -19
- package/src/auth/CachedKeyCollector.ts +2 -3
- package/src/auth/CompoundKeyCollector.ts +2 -3
- package/src/auth/KeyStore.ts +1 -1
- package/src/auth/RemoteJWKSCollector.ts +0 -1
- package/src/auth/StaticKeyCollector.ts +1 -1
- package/src/auth/StaticSupabaseKeyCollector.ts +1 -1
- package/src/entry/commands/teardown-action.ts +1 -1
- package/src/entry/entry-index.ts +1 -1
- package/src/events/EventsEngine.ts +1 -1
- package/src/metrics/MetricsEngine.ts +1 -1
- package/src/metrics/RollingBucketMax.ts +109 -0
- package/src/metrics/metrics-index.ts +3 -2
- package/src/metrics/open-telemetry/util.ts +1 -1
- package/src/metrics/register-metrics.ts +3 -3
- package/src/modules/AbstractModule.ts +1 -1
- package/src/modules/modules-index.ts +1 -1
- package/src/replication/AbstractReplicationJob.ts +2 -2
- package/src/replication/AbstractReplicator.ts +9 -7
- package/src/replication/ReplicationLagTracker.ts +86 -0
- package/src/replication/replication-index.ts +3 -2
- package/src/replication/replication-metrics.ts +1 -1
- package/src/routes/endpoints/sync-rules.ts +3 -5
- package/src/routes/hooks.ts +2 -2
- package/src/routes/route-register.ts +2 -10
- package/src/storage/BucketStorageBatch.ts +1 -1
- package/src/storage/BucketStorageFactory.ts +18 -14
- package/src/storage/ChecksumCache.ts +1 -1
- package/src/storage/PersistedSyncRulesContent.ts +18 -2
- package/src/storage/ReplicationEventPayload.ts +1 -1
- package/src/storage/SourceTable.ts +1 -1
- package/src/storage/storage-index.ts +8 -8
- package/src/storage/storage-metrics.ts +2 -2
- package/src/streams/streams-index.ts +2 -2
- package/src/sync/BucketChecksumState.ts +5 -21
- package/src/sync/RequestTracker.ts +1 -1
- package/src/sync/sync-index.ts +2 -2
- package/src/sync/sync.ts +1 -7
- package/src/sync/util.ts +1 -1
- package/src/system/ServiceContext.ts +1 -1
- package/src/util/config/collectors/impl/base64-config-collector.ts +1 -1
- package/src/util/config/collectors/impl/filesystem-config-collector.ts +2 -2
- package/src/util/config/sync-rules/sync-rules-provider.ts +1 -1
- package/src/util/config.ts +1 -1
- package/src/util/errors.ts +21 -0
- package/src/util/util-index.ts +1 -1
- package/src/util/utils.ts +1 -1
- package/test/src/ReplicationLagTracker.test.ts +53 -0
- package/test/src/RollingBucketMax.test.ts +106 -0
- package/test/src/auth.test.ts +7 -7
- package/test/src/module-loader.test.ts +1 -1
- package/test/src/routes/mocks.ts +1 -1
- package/test/src/routes/stream.test.ts +1 -2
- package/test/src/sync/BucketChecksumState.test.ts +2 -2
- package/test/src/util/protocol_types.test.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +1 -1
|
@@ -107,15 +107,17 @@ export abstract class AbstractReplicator<T extends AbstractReplicationJob = Abst
|
|
|
107
107
|
}, 1000);
|
|
108
108
|
});
|
|
109
109
|
this.metrics.getObservableGauge(ReplicationMetric.REPLICATION_LAG_SECONDS).setValueProvider(async () => {
|
|
110
|
-
|
|
110
|
+
try {
|
|
111
|
+
const lag = this.getReplicationLagMillis();
|
|
112
|
+
if (lag == null) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
// ms to seconds
|
|
116
|
+
return Math.round(lag / 1000);
|
|
117
|
+
} catch (e) {
|
|
111
118
|
this.logger.error('Failed to get replication lag', e);
|
|
112
119
|
return undefined;
|
|
113
|
-
});
|
|
114
|
-
if (lag == null) {
|
|
115
|
-
return undefined;
|
|
116
120
|
}
|
|
117
|
-
// ms to seconds
|
|
118
|
-
return Math.round(lag / 1000);
|
|
119
121
|
});
|
|
120
122
|
}
|
|
121
123
|
|
|
@@ -312,7 +314,7 @@ export abstract class AbstractReplicator<T extends AbstractReplicationJob = Abst
|
|
|
312
314
|
*
|
|
313
315
|
* "processing" replication streams are not taken into account for this metric.
|
|
314
316
|
*/
|
|
315
|
-
|
|
317
|
+
getReplicationLagMillis(): number | undefined {
|
|
316
318
|
return this.activeReplicationJob?.getReplicationLagMillis();
|
|
317
319
|
}
|
|
318
320
|
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { RollingBucketMax } from '../metrics/RollingBucketMax.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tracks replication lag across the current in-flight transaction and a rolling
|
|
5
|
+
* max of recently observed lag values.
|
|
6
|
+
*/
|
|
7
|
+
export class ReplicationLagTracker {
|
|
8
|
+
private readonly rollingReplicationLag = new RollingBucketMax();
|
|
9
|
+
private _oldestUncommittedChange: Date | null = null;
|
|
10
|
+
private _isStartingReplication = true;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The oldest source timestamp still part of the current in-flight work.
|
|
14
|
+
*/
|
|
15
|
+
get oldestUncommittedChange(): Date | null {
|
|
16
|
+
return this._oldestUncommittedChange;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* True until replication has seen its first completed commit or equivalent keepalive.
|
|
21
|
+
*/
|
|
22
|
+
get isStartingReplication(): boolean {
|
|
23
|
+
return this._isStartingReplication;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Registers the first source timestamp for the current in-flight work,
|
|
28
|
+
* for example the start of a transaction
|
|
29
|
+
*/
|
|
30
|
+
trackUncommittedChange(timestamp: Date | null | undefined): void {
|
|
31
|
+
if (this._oldestUncommittedChange == null && timestamp != null) {
|
|
32
|
+
this._oldestUncommittedChange = timestamp;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Clears the current in-flight timestamp without changing startup state.
|
|
38
|
+
*/
|
|
39
|
+
clearUncommittedChange(): void {
|
|
40
|
+
this._oldestUncommittedChange = null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Marks replication as started even if no committed transaction lag was recorded.
|
|
45
|
+
*/
|
|
46
|
+
markStarted(): void {
|
|
47
|
+
this._isStartingReplication = false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Mark the current pending changes as "committed".
|
|
52
|
+
*
|
|
53
|
+
* Records the current in-flight lag into the rolling window and clears it.
|
|
54
|
+
* The current lag is calculated as the differnence between current time and the oldest change,
|
|
55
|
+
* as marked by trackUncommittedChange.
|
|
56
|
+
*/
|
|
57
|
+
markCommitted(timestampMs = Date.now()): void {
|
|
58
|
+
if (this._oldestUncommittedChange != null) {
|
|
59
|
+
this.rollingReplicationLag.report(timestampMs - this._oldestUncommittedChange.getTime(), timestampMs);
|
|
60
|
+
}
|
|
61
|
+
this.clearUncommittedChange();
|
|
62
|
+
this.markStarted();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Returns the lag for the current in-flight work.
|
|
67
|
+
*
|
|
68
|
+
* 0 if idle (no pending changes to replicate).
|
|
69
|
+
*
|
|
70
|
+
* undefined when replication is still starting up.
|
|
71
|
+
*/
|
|
72
|
+
getCurrentLagMillis(timestampMs = Date.now()): number | undefined {
|
|
73
|
+
if (this._oldestUncommittedChange == null) {
|
|
74
|
+
return this._isStartingReplication ? undefined : 0;
|
|
75
|
+
}
|
|
76
|
+
return timestampMs - this._oldestUncommittedChange.getTime();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Returns the rolling lag metric value, including the current in-flight lag when present.
|
|
81
|
+
*/
|
|
82
|
+
getLagMillis(timestampMs = Date.now()): number | undefined {
|
|
83
|
+
this.rollingReplicationLag.report(this.getCurrentLagMillis(timestampMs), timestampMs);
|
|
84
|
+
return this.rollingReplicationLag.getRollingMax(timestampMs);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export * from './AbstractReplicationJob.js';
|
|
2
2
|
export * from './AbstractReplicator.js';
|
|
3
3
|
export * from './ErrorRateLimiter.js';
|
|
4
|
+
export * from './RelationCache.js';
|
|
5
|
+
export * from './replication-metrics.js';
|
|
4
6
|
export * from './ReplicationEngine.js';
|
|
7
|
+
export * from './ReplicationLagTracker.js';
|
|
5
8
|
export * from './ReplicationModule.js';
|
|
6
|
-
export * from './replication-metrics.js';
|
|
7
|
-
export * from './RelationCache.js';
|
|
@@ -4,9 +4,9 @@ import type { FastifyPluginAsync } from 'fastify';
|
|
|
4
4
|
import * as t from 'ts-codec';
|
|
5
5
|
|
|
6
6
|
import { RouteAPI } from '../../api/RouteAPI.js';
|
|
7
|
+
import { updateSyncRulesFromConfig, updateSyncRulesFromYaml } from '../../storage/BucketStorageFactory.js';
|
|
7
8
|
import { authApi } from '../auth.js';
|
|
8
9
|
import { routeDefinition } from '../router.js';
|
|
9
|
-
import { updateSyncRulesFromConfig, updateSyncRulesFromYaml } from '../../storage/BucketStorageFactory.js';
|
|
10
10
|
|
|
11
11
|
const DeploySyncRulesRequest = t.object({
|
|
12
12
|
content: t.string
|
|
@@ -56,7 +56,7 @@ export const deploySyncRules = routeDefinition({
|
|
|
56
56
|
|
|
57
57
|
try {
|
|
58
58
|
const apiHandler = service_context.routerEngine.getAPI();
|
|
59
|
-
syncConfig = SqlSyncRules.fromYaml(
|
|
59
|
+
syncConfig = SqlSyncRules.fromYaml(content, {
|
|
60
60
|
...apiHandler.getParseSyncRulesOptions(),
|
|
61
61
|
// We don't do any schema-level validation at this point
|
|
62
62
|
schema: undefined
|
|
@@ -70,9 +70,7 @@ export const deploySyncRules = routeDefinition({
|
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
const sync_rules = await storageEngine.activeBucketStorage.updateSyncRules(
|
|
74
|
-
updateSyncRulesFromConfig(syncConfig.config)
|
|
75
|
-
);
|
|
73
|
+
const sync_rules = await storageEngine.activeBucketStorage.updateSyncRules(updateSyncRulesFromConfig(syncConfig));
|
|
76
74
|
|
|
77
75
|
return {
|
|
78
76
|
slot_name: sync_rules.slot_name
|
package/src/routes/hooks.ts
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import type fastify from 'fastify';
|
|
2
2
|
import * as uuid from 'uuid';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
ErrorCode,
|
|
6
|
-
errors,
|
|
7
|
-
HTTPMethod,
|
|
8
|
-
logger,
|
|
9
|
-
RouteNotFound,
|
|
10
|
-
router,
|
|
11
|
-
ServiceError
|
|
12
|
-
} from '@powersync/lib-services-framework';
|
|
13
|
-
import { Context, ContextProvider, RequestEndpoint, RequestEndpointHandlerPayload } from './router.js';
|
|
4
|
+
import { errors, HTTPMethod, logger, RouteNotFound, router, ServiceError } from '@powersync/lib-services-framework';
|
|
14
5
|
import { FastifyReply } from 'fastify';
|
|
6
|
+
import { Context, ContextProvider, RequestEndpoint, RequestEndpointHandlerPayload } from './router.js';
|
|
15
7
|
|
|
16
8
|
export type FastifyEndpoint<I, O, C> = RequestEndpoint<I, O, C> & {
|
|
17
9
|
parse?: boolean;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ObserverClient } from '@powersync/lib-services-framework';
|
|
2
2
|
import { EvaluatedParameters, EvaluatedRow, SqliteRow, ToastableSqliteRow } from '@powersync/service-sync-rules';
|
|
3
3
|
import { BSON } from 'bson';
|
|
4
|
+
import { InternalOpId } from '../util/utils.js';
|
|
4
5
|
import { ReplicationEventPayload } from './ReplicationEventPayload.js';
|
|
5
6
|
import { SourceTable, TableSnapshotStatus } from './SourceTable.js';
|
|
6
7
|
import { BatchedCustomWriteCheckpointOptions } from './storage-index.js';
|
|
7
|
-
import { InternalOpId } from '../util/utils.js';
|
|
8
8
|
|
|
9
9
|
export const DEFAULT_BUCKET_BATCH_COMMIT_OPTIONS: ResolvedBucketBatchCommitOptions = {
|
|
10
10
|
createEmptyCheckpoints: true,
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { BaseObserver, logger } from '@powersync/lib-services-framework';
|
|
2
|
-
import { ParseSyncRulesOptions, PersistedSyncRules, PersistedSyncRulesContent } from './PersistedSyncRulesContent.js';
|
|
3
|
-
import { ReplicationEventPayload } from './ReplicationEventPayload.js';
|
|
4
|
-
import { ReplicationLock } from './ReplicationLock.js';
|
|
5
|
-
import { SyncRulesBucketStorage } from './SyncRulesBucketStorage.js';
|
|
6
|
-
import { ReportStorage } from './ReportStorage.js';
|
|
7
2
|
import {
|
|
8
3
|
PrecompiledSyncConfig,
|
|
9
4
|
SerializedCompatibilityContext,
|
|
10
5
|
serializeSyncPlan,
|
|
11
6
|
SqlSyncRules,
|
|
12
|
-
|
|
7
|
+
SyncConfigWithErrors
|
|
13
8
|
} from '@powersync/service-sync-rules';
|
|
9
|
+
import { ReplicationError } from '@powersync/service-types';
|
|
10
|
+
import { syncConfigYamlErrorToReplicationError } from '../util/errors.js';
|
|
11
|
+
import { ParseSyncRulesOptions, PersistedSyncRules, PersistedSyncRulesContent } from './PersistedSyncRulesContent.js';
|
|
12
|
+
import { ReplicationEventPayload } from './ReplicationEventPayload.js';
|
|
13
|
+
import { ReplicationLock } from './ReplicationLock.js';
|
|
14
|
+
import { ReportStorage } from './ReportStorage.js';
|
|
15
|
+
import { SyncRulesBucketStorage } from './SyncRulesBucketStorage.js';
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Represents a configured storage provider.
|
|
@@ -178,13 +180,14 @@ export interface SerializedSyncPlan {
|
|
|
178
180
|
* them.
|
|
179
181
|
*/
|
|
180
182
|
eventDescriptors: Record<string, string[]>;
|
|
183
|
+
errors?: ReplicationError[];
|
|
181
184
|
}
|
|
182
185
|
|
|
183
186
|
export function updateSyncRulesFromYaml(
|
|
184
187
|
content: string,
|
|
185
188
|
options?: Omit<UpdateSyncRulesOptions, 'config'> & { validate?: boolean }
|
|
186
189
|
): UpdateSyncRulesOptions {
|
|
187
|
-
const
|
|
190
|
+
const config = SqlSyncRules.fromYaml(content, {
|
|
188
191
|
// No schema-based validation at this point
|
|
189
192
|
schema: undefined,
|
|
190
193
|
defaultSchema: 'not_applicable', // Not needed for validation
|
|
@@ -195,24 +198,25 @@ export function updateSyncRulesFromYaml(
|
|
|
195
198
|
}
|
|
196
199
|
|
|
197
200
|
export function updateSyncRulesFromConfig(
|
|
198
|
-
|
|
201
|
+
{ config, errors }: SyncConfigWithErrors,
|
|
199
202
|
options?: Omit<UpdateSyncRulesOptions, 'config'>
|
|
200
203
|
): UpdateSyncRulesOptions {
|
|
201
204
|
let plan: SerializedSyncPlan | null = null;
|
|
202
|
-
if (
|
|
205
|
+
if (config instanceof PrecompiledSyncConfig) {
|
|
203
206
|
const eventDescriptors: Record<string, string[]> = {};
|
|
204
|
-
for (const event of
|
|
207
|
+
for (const event of config.eventDescriptors) {
|
|
205
208
|
eventDescriptors[event.name] = event.sourceQueries.map((q) => q.sql);
|
|
206
209
|
}
|
|
207
210
|
|
|
208
211
|
plan = {
|
|
209
|
-
compatibility:
|
|
210
|
-
plan: serializeSyncPlan(
|
|
211
|
-
eventDescriptors
|
|
212
|
+
compatibility: config.compatibility.serialize(),
|
|
213
|
+
plan: serializeSyncPlan(config.plan),
|
|
214
|
+
eventDescriptors,
|
|
215
|
+
errors: errors.map((e) => syncConfigYamlErrorToReplicationError(e))
|
|
212
216
|
};
|
|
213
217
|
}
|
|
214
218
|
|
|
215
|
-
return { config: { yaml:
|
|
219
|
+
return { config: { yaml: config.content, plan }, ...options };
|
|
216
220
|
}
|
|
217
221
|
|
|
218
222
|
export interface GetIntanceOptions {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OrderedSet } from '@js-sdsl/ordered-set';
|
|
2
|
-
import { LRUCache } from 'lru-cache/min';
|
|
3
2
|
import { BucketDataSource } from '@powersync/service-sync-rules';
|
|
3
|
+
import { LRUCache } from 'lru-cache/min';
|
|
4
4
|
import { BucketChecksum } from '../util/protocol-types.js';
|
|
5
5
|
import { addBucketChecksums, ChecksumMap, InternalOpId, PartialChecksum } from '../util/utils.js';
|
|
6
6
|
import { BucketChecksumRequest } from './SyncRulesBucketStorage.js';
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
CompatibilityOption,
|
|
5
5
|
DEFAULT_HYDRATION_STATE,
|
|
6
6
|
deserializeSyncPlan,
|
|
7
|
+
ErrorLocation,
|
|
7
8
|
HydratedSyncRules,
|
|
8
9
|
HydrationState,
|
|
9
10
|
javaScriptExpressionEngine,
|
|
@@ -11,7 +12,8 @@ import {
|
|
|
11
12
|
SqlEventDescriptor,
|
|
12
13
|
SqlSyncRules,
|
|
13
14
|
SyncConfigWithErrors,
|
|
14
|
-
versionedHydrationState
|
|
15
|
+
versionedHydrationState,
|
|
16
|
+
YamlError
|
|
15
17
|
} from '@powersync/service-sync-rules';
|
|
16
18
|
import { SerializedSyncPlan, UpdateSyncRulesOptions } from './BucketStorageFactory.js';
|
|
17
19
|
import { ReplicationLock } from './ReplicationLock.js';
|
|
@@ -101,7 +103,21 @@ export abstract class PersistedSyncRulesContent implements PersistedSyncRulesCon
|
|
|
101
103
|
sourceText: this.sync_rules_content
|
|
102
104
|
});
|
|
103
105
|
|
|
104
|
-
|
|
106
|
+
const errors: YamlError[] = [];
|
|
107
|
+
if (this.compiled_plan.errors) {
|
|
108
|
+
for (const error of this.compiled_plan.errors) {
|
|
109
|
+
const location: ErrorLocation | undefined = error.location && {
|
|
110
|
+
start: error.location.start_offset,
|
|
111
|
+
end: error.location.end_offset
|
|
112
|
+
};
|
|
113
|
+
const asYamlError = new YamlError(new Error(error.message), location);
|
|
114
|
+
asYamlError.type = error.level;
|
|
115
|
+
|
|
116
|
+
errors.push(asYamlError);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
config = { config: precompiled, errors };
|
|
105
121
|
} else {
|
|
106
122
|
config = SqlSyncRules.fromYaml(this.sync_rules_content, options);
|
|
107
123
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as sync_rules from '@powersync/service-sync-rules';
|
|
2
|
-
import { SourceTable } from './SourceTable.js';
|
|
3
2
|
import { BucketStorageBatch, SaveOp } from './BucketStorageBatch.js';
|
|
3
|
+
import { SourceTable } from './SourceTable.js';
|
|
4
4
|
|
|
5
5
|
export type EventData = {
|
|
6
6
|
op: SaveOp;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_TAG } from '@powersync/service-sync-rules';
|
|
2
|
+
import { bson } from '../index.js';
|
|
2
3
|
import * as util from '../util/util-index.js';
|
|
3
4
|
import { ColumnDescriptor, SourceEntityDescriptor } from './SourceEntity.js';
|
|
4
|
-
import { bson } from '../index.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Format of the id depends on the bucket storage module. It should be consistent within the module.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
export * from './bson.js';
|
|
2
2
|
export * from './BucketStorage.js';
|
|
3
|
+
export * from './BucketStorageBatch.js';
|
|
4
|
+
export * from './BucketStorageFactory.js';
|
|
3
5
|
export * from './ChecksumCache.js';
|
|
6
|
+
export * from './PersistedSyncRulesContent.js';
|
|
4
7
|
export * from './ReplicationEventPayload.js';
|
|
8
|
+
export * from './ReplicationLock.js';
|
|
9
|
+
export * from './ReportStorage.js';
|
|
5
10
|
export * from './SourceEntity.js';
|
|
6
11
|
export * from './SourceTable.js';
|
|
12
|
+
export * from './storage-metrics.js';
|
|
7
13
|
export * from './StorageEngine.js';
|
|
8
14
|
export * from './StorageProvider.js';
|
|
9
|
-
export * from './storage-metrics.js';
|
|
10
|
-
export * from './WriteCheckpointAPI.js';
|
|
11
|
-
export * from './BucketStorageFactory.js';
|
|
12
|
-
export * from './BucketStorageBatch.js';
|
|
13
|
-
export * from './SyncRulesBucketStorage.js';
|
|
14
|
-
export * from './PersistedSyncRulesContent.js';
|
|
15
|
-
export * from './ReplicationLock.js';
|
|
16
|
-
export * from './ReportStorage.js';
|
|
17
15
|
export * from './StorageVersionConfig.js';
|
|
16
|
+
export * from './SyncRulesBucketStorage.js';
|
|
17
|
+
export * from './WriteCheckpointAPI.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { MetricsEngine } from '../metrics/MetricsEngine.js';
|
|
2
1
|
import { logger } from '@powersync/lib-services-framework';
|
|
3
|
-
import { BucketStorageFactory, StorageMetrics } from './BucketStorageFactory.js';
|
|
4
2
|
import { StorageMetric } from '@powersync/service-types';
|
|
3
|
+
import { MetricsEngine } from '../metrics/MetricsEngine.js';
|
|
4
|
+
import { BucketStorageFactory, StorageMetrics } from './BucketStorageFactory.js';
|
|
5
5
|
|
|
6
6
|
export function createCoreStorageMetrics(engine: MetricsEngine): void {
|
|
7
7
|
engine.createObservableGauge({
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
BucketDescription,
|
|
3
2
|
BucketParameterQuerier,
|
|
4
3
|
BucketPriority,
|
|
5
4
|
BucketSource,
|
|
6
5
|
HydratedSyncRules,
|
|
6
|
+
mergeBuckets,
|
|
7
7
|
QuerierError,
|
|
8
8
|
RequestedStream,
|
|
9
9
|
RequestParameters,
|
|
10
|
-
ResolvedBucket
|
|
11
|
-
mergeBuckets
|
|
10
|
+
ResolvedBucket
|
|
12
11
|
} from '@powersync/service-sync-rules';
|
|
13
12
|
|
|
14
13
|
import * as storage from '../storage/storage-index.js';
|
|
@@ -445,6 +444,7 @@ export class BucketParameterState {
|
|
|
445
444
|
const subscription = explicitStreamSubscriptions[i];
|
|
446
445
|
|
|
447
446
|
const syncRuleStream: RequestedStream = {
|
|
447
|
+
priorityOverride: subscription.override_priority as BucketPriority | null,
|
|
448
448
|
parameters: subscription.parameters ?? {},
|
|
449
449
|
opaque_id: i
|
|
450
450
|
};
|
|
@@ -480,25 +480,9 @@ export class BucketParameterState {
|
|
|
480
480
|
* reference default buckets by their stream index instead of duplicating the name on wire.
|
|
481
481
|
*/
|
|
482
482
|
translateResolvedBucket(description: ResolvedBucket, lookupIndex: Map<string, number>): util.ClientBucketDescription {
|
|
483
|
-
// If the client is overriding the priority of any stream that yields this bucket, sync the bucket with that
|
|
484
|
-
// priority.
|
|
485
|
-
let priorityOverride: BucketPriority | null = null;
|
|
486
|
-
for (const reason of description.inclusion_reasons) {
|
|
487
|
-
if (reason != 'default') {
|
|
488
|
-
const requestedPriority = this.explicitStreamSubscriptions[reason.subscription]?.override_priority;
|
|
489
|
-
if (requestedPriority != null) {
|
|
490
|
-
if (priorityOverride == null) {
|
|
491
|
-
priorityOverride = requestedPriority as BucketPriority;
|
|
492
|
-
} else {
|
|
493
|
-
priorityOverride = Math.min(requestedPriority, priorityOverride) as BucketPriority;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
483
|
return {
|
|
500
484
|
bucket: description.bucket,
|
|
501
|
-
priority:
|
|
485
|
+
priority: description.priority,
|
|
502
486
|
subscriptions: description.inclusion_reasons.map((reason) => {
|
|
503
487
|
if (reason == 'default') {
|
|
504
488
|
const stream = description.definition;
|
|
@@ -533,7 +517,7 @@ export class BucketParameterState {
|
|
|
533
517
|
|
|
534
518
|
let errorMessage = error.message;
|
|
535
519
|
const logData: any = {
|
|
536
|
-
checkpoint: checkpoint,
|
|
520
|
+
checkpoint: checkpoint.base.checkpoint,
|
|
537
521
|
user_id: this.syncParams.userId,
|
|
538
522
|
parameter_query_results: update.buckets.length
|
|
539
523
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { MetricsEngine } from '../metrics/MetricsEngine.js';
|
|
2
2
|
|
|
3
|
+
import { ServiceAssertionError } from '@powersync/lib-services-framework';
|
|
3
4
|
import { APIMetric } from '@powersync/service-types';
|
|
4
5
|
import { SyncBucketData } from '../util/protocol-types.js';
|
|
5
|
-
import { ServiceAssertionError } from '@powersync/lib-services-framework';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Record sync stats per request stream.
|
package/src/sync/sync-index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
export * from './BucketChecksumState.js';
|
|
1
2
|
export * from './RequestTracker.js';
|
|
2
3
|
export * from './safeRace.js';
|
|
3
4
|
export * from './sync.js';
|
|
4
|
-
export * from './util.js';
|
|
5
|
-
export * from './BucketChecksumState.js';
|
|
6
5
|
export * from './SyncContext.js';
|
|
6
|
+
export * from './util.js';
|
package/src/sync/sync.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { JSONBig, JsonContainer } from '@powersync/service-jsonbig';
|
|
2
|
-
import {
|
|
3
|
-
BucketDescription,
|
|
4
|
-
BucketPriority,
|
|
5
|
-
HydratedSyncRules,
|
|
6
|
-
ResolvedBucket,
|
|
7
|
-
SqliteJsonValue
|
|
8
|
-
} from '@powersync/service-sync-rules';
|
|
2
|
+
import { BucketPriority, HydratedSyncRules, ResolvedBucket, SqliteJsonValue } from '@powersync/service-sync-rules';
|
|
9
3
|
|
|
10
4
|
import { AbortError } from 'ix/aborterror.js';
|
|
11
5
|
|
package/src/sync/util.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as timers from 'timers/promises';
|
|
2
2
|
|
|
3
3
|
import { SemaphoreInterface } from 'async-mutex';
|
|
4
|
+
import { serialize } from 'bson';
|
|
4
5
|
import * as util from '../util/util-index.js';
|
|
5
6
|
import { RequestTracker } from './RequestTracker.js';
|
|
6
|
-
import { serialize } from 'bson';
|
|
7
7
|
|
|
8
8
|
export type TokenStreamOptions = {
|
|
9
9
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { container, LifeCycledSystem, MigrationManager, ServiceIdentifier } from '@powersync/lib-services-framework';
|
|
2
2
|
|
|
3
|
+
import { EventsEngine } from '../events/EventsEngine.js';
|
|
3
4
|
import { framework } from '../index.js';
|
|
4
5
|
import * as metrics from '../metrics/MetricsEngine.js';
|
|
5
6
|
import { PowerSyncMigrationManager } from '../migrations/PowerSyncMigrationManager.js';
|
|
@@ -8,7 +9,6 @@ import * as routes from '../routes/routes-index.js';
|
|
|
8
9
|
import * as storage from '../storage/storage-index.js';
|
|
9
10
|
import { SyncContext } from '../sync/SyncContext.js';
|
|
10
11
|
import * as utils from '../util/util-index.js';
|
|
11
|
-
import { EventsEngine } from '../events/EventsEngine.js';
|
|
12
12
|
|
|
13
13
|
export interface ServiceContext {
|
|
14
14
|
configuration: utils.ResolvedPowerSyncConfig;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
|
|
4
|
-
import { ConfigCollector, ConfigFileFormat } from '../config-collector.js';
|
|
5
|
-
import { RunnerConfig } from '../../types.js';
|
|
6
4
|
import { logger } from '@powersync/lib-services-framework';
|
|
5
|
+
import { RunnerConfig } from '../../types.js';
|
|
6
|
+
import { ConfigCollector, ConfigFileFormat } from '../config-collector.js';
|
|
7
7
|
|
|
8
8
|
export class FileSystemConfigCollector extends ConfigCollector {
|
|
9
9
|
get name(): string {
|
package/src/util/config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
2
|
import winston from 'winston';
|
|
3
3
|
|
|
4
|
-
import { container,
|
|
4
|
+
import { container, DEFAULT_LOG_FORMAT, DEFAULT_LOG_LEVEL, LogFormat, logger } from '@powersync/lib-services-framework';
|
|
5
5
|
import { configFile } from '@powersync/service-types';
|
|
6
6
|
import { ResolvedPowerSyncConfig, RunnerConfig } from './config/types.js';
|
|
7
7
|
import { CompoundConfigCollector } from './util-index.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { YamlError } from '@powersync/service-sync-rules';
|
|
2
|
+
import { ReplicationError } from '@powersync/service-types';
|
|
3
|
+
|
|
4
|
+
export function syncConfigYamlErrorToReplicationError(
|
|
5
|
+
{ type, message, location }: YamlError,
|
|
6
|
+
ts?: string
|
|
7
|
+
): ReplicationError {
|
|
8
|
+
const error: ReplicationError = {
|
|
9
|
+
level: type,
|
|
10
|
+
message,
|
|
11
|
+
ts
|
|
12
|
+
};
|
|
13
|
+
if (location != null) {
|
|
14
|
+
error.location = {
|
|
15
|
+
start_offset: location.start,
|
|
16
|
+
end_offset: location.end
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return error;
|
|
21
|
+
}
|
package/src/util/util-index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './alerting.js';
|
|
2
|
+
export * from './checkpointing.js';
|
|
2
3
|
export * from './env.js';
|
|
3
4
|
export * from './lsn.js';
|
|
4
5
|
export * from './memory-tracking.js';
|
|
@@ -6,7 +7,6 @@ export * from './Mutex.js';
|
|
|
6
7
|
export * from './protocol-types.js';
|
|
7
8
|
export * from './secs.js';
|
|
8
9
|
export * from './utils.js';
|
|
9
|
-
export * from './checkpointing.js';
|
|
10
10
|
export * from './version.js';
|
|
11
11
|
|
|
12
12
|
export * from './config.js';
|
package/src/util/utils.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as sync_rules from '@powersync/service-sync-rules';
|
|
|
2
2
|
import * as bson from 'bson';
|
|
3
3
|
import crypto from 'crypto';
|
|
4
4
|
import * as uuid from 'uuid';
|
|
5
|
-
import { BucketChecksum,
|
|
5
|
+
import { BucketChecksum, OplogEntry, ProtocolOpId } from './protocol-types.js';
|
|
6
6
|
|
|
7
7
|
import * as storage from '../storage/storage-index.js';
|
|
8
8
|
|