@powersync/service-core 1.23.0 → 1.23.2
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 +22 -0
- package/dist/api/RouteAPI.d.ts +25 -11
- package/dist/replication/AbstractReplicator.d.ts +20 -1
- package/dist/replication/AbstractReplicator.js +106 -47
- package/dist/replication/AbstractReplicator.js.map +1 -1
- package/dist/routes/RouterEngine.d.ts +1 -0
- package/dist/routes/RouterEngine.js +6 -1
- package/dist/routes/RouterEngine.js.map +1 -1
- package/dist/routes/configure-fastify.d.ts +52 -44
- package/dist/routes/configure-fastify.js +15 -2
- package/dist/routes/configure-fastify.js.map +1 -1
- package/dist/routes/endpoints/admin.js +2 -1
- package/dist/routes/endpoints/admin.js.map +1 -1
- package/dist/routes/endpoints/checkpointing.js +1 -3
- package/dist/routes/endpoints/checkpointing.js.map +1 -1
- package/dist/storage/BucketStorageBatch.d.ts +60 -11
- package/dist/storage/BucketStorageBatch.js.map +1 -1
- package/dist/storage/ChecksumCache.d.ts +11 -6
- package/dist/storage/ChecksumCache.js +5 -4
- package/dist/storage/ChecksumCache.js.map +1 -1
- package/dist/storage/PersistedSyncConfigContent.d.ts +3 -0
- package/dist/storage/PersistedSyncConfigContent.js +2 -0
- package/dist/storage/PersistedSyncConfigContent.js.map +1 -1
- package/dist/storage/SyncRulesBucketStorage.d.ts +35 -5
- package/dist/storage/SyncRulesBucketStorage.js.map +1 -1
- package/dist/storage/WriteCheckpointAPI.d.ts +1 -1
- package/dist/sync/BucketChecksumState.d.ts +5 -2
- package/dist/sync/BucketChecksumState.js +36 -8
- package/dist/sync/BucketChecksumState.js.map +1 -1
- package/dist/sync/RequestTracker.d.ts +7 -0
- package/dist/sync/RequestTracker.js +12 -0
- package/dist/sync/RequestTracker.js.map +1 -1
- package/dist/sync/sync.js +118 -38
- package/dist/sync/sync.js.map +1 -1
- package/dist/system/ServiceContext.d.ts +2 -0
- package/dist/system/ServiceContext.js +2 -0
- package/dist/system/ServiceContext.js.map +1 -1
- package/dist/tracing/PerformanceTracer.d.ts +7 -1
- package/dist/tracing/PerformanceTracer.js +8 -0
- package/dist/tracing/PerformanceTracer.js.map +1 -1
- package/dist/util/checkpointing.d.ts +3 -8
- package/dist/util/checkpointing.js +1 -16
- package/dist/util/checkpointing.js.map +1 -1
- package/dist/util/config/compound-config-collector.js +10 -2
- package/dist/util/config/compound-config-collector.js.map +1 -1
- package/dist/util/config/defaults.d.ts +1 -0
- package/dist/util/config/defaults.js +1 -0
- package/dist/util/config/defaults.js.map +1 -1
- package/dist/util/config/types.d.ts +1 -0
- package/dist/util/util-index.d.ts +1 -0
- package/dist/util/util-index.js +1 -0
- package/dist/util/util-index.js.map +1 -1
- package/dist/util/utils.d.ts +1 -1
- package/dist/util/utils.js +1 -1
- package/dist/util/write-checkpoint-batcher.d.ts +19 -0
- package/dist/util/write-checkpoint-batcher.js +90 -0
- package/dist/util/write-checkpoint-batcher.js.map +1 -0
- package/package.json +5 -5
- package/src/api/RouteAPI.ts +25 -11
- package/src/replication/AbstractReplicator.ts +134 -47
- package/src/routes/RouterEngine.ts +7 -1
- package/src/routes/configure-fastify.ts +25 -2
- package/src/routes/endpoints/admin.ts +2 -1
- package/src/routes/endpoints/checkpointing.ts +1 -4
- package/src/storage/BucketStorageBatch.ts +61 -11
- package/src/storage/ChecksumCache.ts +27 -14
- package/src/storage/PersistedSyncConfigContent.ts +4 -0
- package/src/storage/SyncRulesBucketStorage.ts +42 -5
- package/src/storage/WriteCheckpointAPI.ts +1 -1
- package/src/sync/BucketChecksumState.ts +65 -8
- package/src/sync/RequestTracker.ts +20 -0
- package/src/sync/sync.ts +148 -44
- package/src/system/ServiceContext.ts +7 -0
- package/src/tracing/PerformanceTracer.ts +18 -1
- package/src/util/checkpointing.ts +3 -22
- package/src/util/config/compound-config-collector.ts +13 -1
- package/src/util/config/defaults.ts +1 -0
- package/src/util/config/types.ts +1 -0
- package/src/util/util-index.ts +1 -0
- package/src/util/utils.ts +1 -1
- package/src/util/write-checkpoint-batcher.ts +122 -0
- package/test/src/checksum_cache.test.ts +22 -0
- package/test/src/config.test.ts +42 -0
- package/test/src/diagnostics.test.ts +13 -12
- package/test/src/routes/admin.test.ts +12 -10
- package/test/src/sync/BucketChecksumState.test.ts +41 -1
- package/test/src/util/checkpointing.test.ts +170 -0
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @powersync/service-core
|
|
2
2
|
|
|
3
|
+
## 1.23.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 71d4a0a: Add logs for checkpoint_complete to assist with debugging. Remove "sync lock" logs.
|
|
8
|
+
- e4f683d: [MongoDB Storage] Add experimental option to allow reading data from secondaries.
|
|
9
|
+
- 71d4a0a: Fix edge case where the service can return incomplete data. This could happen when using bucket priorities, and a checkpoint is invalidated by the compact process while syncing.
|
|
10
|
+
- c2edf86: Add `api.parameters.bucket_count_cache_ttl_minutes` configuration option.
|
|
11
|
+
- df9ab1e: Batch concurrent write checkpoint requests and increase request limits to improve throughput.
|
|
12
|
+
- Updated dependencies [a6ae678]
|
|
13
|
+
- Updated dependencies [c2edf86]
|
|
14
|
+
- @powersync/service-sync-rules@0.38.1
|
|
15
|
+
- @powersync/service-types@0.16.1
|
|
16
|
+
- @powersync/lib-services-framework@0.9.7
|
|
17
|
+
- @powersync/service-rsocket-router@0.2.23
|
|
18
|
+
|
|
19
|
+
## 1.23.1
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- 7e65360: Restructure replication locks for updated sync config.
|
|
24
|
+
|
|
3
25
|
## 1.23.0
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
package/dist/api/RouteAPI.d.ts
CHANGED
|
@@ -20,7 +20,8 @@ export interface SlotWalBudgetOptions {
|
|
|
20
20
|
slotName: string;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Source-specific capabilities used by admin routes, sync config validation,
|
|
24
|
+
* checkpointing, diagnostics, and the sync API.
|
|
24
25
|
*/
|
|
25
26
|
export interface RouteAPI {
|
|
26
27
|
/**
|
|
@@ -33,16 +34,17 @@ export interface RouteAPI {
|
|
|
33
34
|
*/
|
|
34
35
|
getConnectionStatus(): Promise<types.ConnectionStatusV2>;
|
|
35
36
|
/**
|
|
36
|
-
*
|
|
37
|
+
* Expand sync config table patterns into table metadata from the source connection.
|
|
38
|
+
*
|
|
39
|
+
* This is used by validation and diagnostics paths to explain what will be
|
|
40
|
+
* replicated for the current sync config.
|
|
37
41
|
*
|
|
38
42
|
* @param tablePatterns A set of table patterns which typically come from
|
|
39
43
|
* the tables listed in sync config definitions.
|
|
40
44
|
*
|
|
41
45
|
* @param sqlSyncRules
|
|
42
|
-
* @returns
|
|
43
|
-
*
|
|
44
|
-
* tables to ensure syncing should function according to the input
|
|
45
|
-
* pattern. Debug errors and warnings are reported per table.
|
|
46
|
+
* @returns Matching tables or collections, their columns or fields where available,
|
|
47
|
+
* and per-table warnings or errors for the requested table patterns.
|
|
46
48
|
*/
|
|
47
49
|
getDebugTablesInfo(tablePatterns: TablePattern[], sqlSyncRules: SyncConfig): Promise<PatternResult[]>;
|
|
48
50
|
/**
|
|
@@ -59,13 +61,20 @@ export interface RouteAPI {
|
|
|
59
61
|
/**
|
|
60
62
|
* Get the current LSN or equivalent replication HEAD position identifier.
|
|
61
63
|
*
|
|
62
|
-
* The position is provided to the callback
|
|
63
|
-
*
|
|
64
|
+
* The position is provided to the callback so the caller can persist its
|
|
65
|
+
* write-checkpoint mapping before the source adapter forces any required
|
|
66
|
+
* source-side marker or keepalive. After the callback returns, the adapter
|
|
67
|
+
* must ensure that the replication stream will observe this position or a
|
|
68
|
+
* greater one, even when the source is otherwise idle.
|
|
64
69
|
*/
|
|
65
70
|
createReplicationHead<T>(callback: ReplicationHeadCallback<T>): Promise<T>;
|
|
66
71
|
/**
|
|
67
|
-
* @returns The
|
|
68
|
-
*
|
|
72
|
+
* @returns The connected source schema in service-friendly table and column
|
|
73
|
+
* formats. Strict-schema sources should include actual tables,
|
|
74
|
+
* collections, columns, and types. Schemaless sources should return
|
|
75
|
+
* the best metadata available and document validation limitations in
|
|
76
|
+
* their adapter behavior. This is typically used to validate sync
|
|
77
|
+
* config and generate client schemas.
|
|
69
78
|
*/
|
|
70
79
|
getConnectionSchema(): Promise<types.DatabaseSchema[]>;
|
|
71
80
|
/**
|
|
@@ -78,7 +87,12 @@ export interface RouteAPI {
|
|
|
78
87
|
*/
|
|
79
88
|
shutdown(): Promise<void>;
|
|
80
89
|
/**
|
|
81
|
-
* Get
|
|
90
|
+
* Get source-specific sync config parsing defaults, such as the default
|
|
91
|
+
* schema or database to use when sync config references an unqualified table
|
|
92
|
+
* name.
|
|
93
|
+
*
|
|
94
|
+
* This is used wherever sync config is parsed for this source, including
|
|
95
|
+
* validation, diagnostics, and sync routing.
|
|
82
96
|
*/
|
|
83
97
|
getParseSyncRulesOptions(): ParseSyncConfigOptions;
|
|
84
98
|
}
|
|
@@ -28,7 +28,7 @@ export interface AbstractReplicatorOptions {
|
|
|
28
28
|
export declare abstract class AbstractReplicator<T extends AbstractReplicationJob = AbstractReplicationJob> {
|
|
29
29
|
private options;
|
|
30
30
|
protected logger: winston.Logger;
|
|
31
|
-
private
|
|
31
|
+
private lastReplicationStreamInfoLogs;
|
|
32
32
|
/**
|
|
33
33
|
* Map of replication jobs by replication stream job id. Usually there is only one running job, but there could be two
|
|
34
34
|
* when transitioning to a new replication stream.
|
|
@@ -48,6 +48,11 @@ export declare abstract class AbstractReplicator<T extends AbstractReplicationJo
|
|
|
48
48
|
private lastPing;
|
|
49
49
|
private abortController;
|
|
50
50
|
protected constructor(options: AbstractReplicatorOptions);
|
|
51
|
+
/**
|
|
52
|
+
* Create the source-specific replication job for a locked storage stream.
|
|
53
|
+
*
|
|
54
|
+
* The job owns the per-stream snapshot and streaming work for this attempt.
|
|
55
|
+
*/
|
|
51
56
|
abstract createJob(options: CreateJobOptions): T;
|
|
52
57
|
/**
|
|
53
58
|
* Clean up any configuration or state for the specified replication stream on the datasource.
|
|
@@ -64,8 +69,22 @@ export declare abstract class AbstractReplicator<T extends AbstractReplicationJo
|
|
|
64
69
|
stop(): Promise<void>;
|
|
65
70
|
private runLoop;
|
|
66
71
|
private refresh;
|
|
72
|
+
private logReplicationStreamInfoOnce;
|
|
73
|
+
private clearReplicationStreamInfoLog;
|
|
74
|
+
/**
|
|
75
|
+
* When we load sync config from the filesystem/config source, we ignore any config loaded by other processes.
|
|
76
|
+
* The idea is that if a different process loads updated config, that process should process it, not this one.
|
|
77
|
+
*
|
|
78
|
+
* This specifically helps for cases with rolling deploys.
|
|
79
|
+
*
|
|
80
|
+
* This does not apply when sync config is loaded from the database/API, instead of in the config.
|
|
81
|
+
*/
|
|
82
|
+
private shouldHandleReplicationStream;
|
|
67
83
|
protected createJobId(syncRuleId: number): string;
|
|
68
84
|
protected terminateSyncRules(syncRuleStorage: storage.SyncRulesBucketStorage): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Check source connectivity using the replicator's decoded connection config.
|
|
87
|
+
*/
|
|
69
88
|
abstract testConnection(): Promise<ConnectionTestResult>;
|
|
70
89
|
/**
|
|
71
90
|
* Measure replication lag in milliseconds.
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { container, ErrorCode, logger } from '@powersync/lib-services-framework';
|
|
2
2
|
import { ReplicationMetric } from '@powersync/service-types';
|
|
3
3
|
import { hrtime } from 'node:process';
|
|
4
|
+
import { setTimeout as sleep } from 'node:timers/promises';
|
|
4
5
|
import * as storage from '../storage/storage-index.js';
|
|
5
6
|
// 1 minute
|
|
6
7
|
const PING_INTERVAL = 1000000000n * 60n;
|
|
8
|
+
// In the initial startup period, we use a short refresh interval. This helps to take over replication quickly in the case
|
|
9
|
+
// of rolling deploys. After the initial period, we switch to a longer refresh interval to reduce load.
|
|
10
|
+
const FAST_REFRESH_INTERVAL_MS = 500;
|
|
11
|
+
const FAST_REFRESH_TIMEOUT_MS = 120_000;
|
|
12
|
+
const REFRESH_INTERVAL_MS = 5_000;
|
|
7
13
|
/**
|
|
8
14
|
* A replicator manages the mechanics for replicating data from a data source to a storage bucket.
|
|
9
15
|
* This includes copying across the original data set and then keeping it in sync with the data source using Replication Jobs.
|
|
@@ -12,7 +18,7 @@ const PING_INTERVAL = 1000000000n * 60n;
|
|
|
12
18
|
export class AbstractReplicator {
|
|
13
19
|
options;
|
|
14
20
|
logger;
|
|
15
|
-
|
|
21
|
+
lastReplicationStreamInfoLogs = new Map();
|
|
16
22
|
/**
|
|
17
23
|
* Map of replication jobs by replication stream job id. Usually there is only one running job, but there could be two
|
|
18
24
|
* when transitioning to a new replication stream.
|
|
@@ -87,14 +93,17 @@ export class AbstractReplicator {
|
|
|
87
93
|
await Promise.all(promises);
|
|
88
94
|
}
|
|
89
95
|
async runLoop() {
|
|
90
|
-
const
|
|
96
|
+
const loadedSyncConfig = await this.syncRuleProvider.get();
|
|
91
97
|
let configuredLock = undefined;
|
|
92
|
-
if (
|
|
98
|
+
if (loadedSyncConfig != null) {
|
|
93
99
|
this.logger.info('Loaded sync config');
|
|
94
100
|
try {
|
|
95
101
|
// Configure new sync config, if they have changed.
|
|
96
102
|
// In that case, also immediately take out a lock, so that another process doesn't start replication on it.
|
|
97
|
-
|
|
103
|
+
// This upfront lock is mostly superseded by the replicationStreamLoadedSyncConfigMatch() check. However, that doesn't cover old
|
|
104
|
+
// versions before that check was added, so we keep the lock for now - for where te service version and sync config is updated at
|
|
105
|
+
// the same time.
|
|
106
|
+
const { lock } = await this.storage.configureSyncRules(storage.updateSyncRulesFromYaml(loadedSyncConfig, { lock: true, validate: this.syncRuleProvider.exitOnError }));
|
|
98
107
|
if (lock) {
|
|
99
108
|
configuredLock = lock;
|
|
100
109
|
}
|
|
@@ -109,10 +118,15 @@ export class AbstractReplicator {
|
|
|
109
118
|
else {
|
|
110
119
|
this.logger.info('No sync streams or rules configured - configure via API');
|
|
111
120
|
}
|
|
121
|
+
let useFastRefresh = true;
|
|
122
|
+
const fastRefreshDeadline = Date.now() + FAST_REFRESH_TIMEOUT_MS;
|
|
112
123
|
while (!this.stopped) {
|
|
113
124
|
await container.probes.touch();
|
|
114
125
|
try {
|
|
115
|
-
await this.refresh({
|
|
126
|
+
const refreshResult = await this.refresh({ configuredLock, loadedSyncConfig });
|
|
127
|
+
if (refreshResult.replicationJobStarted || Date.now() >= fastRefreshDeadline) {
|
|
128
|
+
useFastRefresh = false;
|
|
129
|
+
}
|
|
116
130
|
// The lock is only valid on the first refresh.
|
|
117
131
|
configuredLock = undefined;
|
|
118
132
|
// Ensure that the replication jobs' connections are kept alive.
|
|
@@ -130,21 +144,34 @@ export class AbstractReplicator {
|
|
|
130
144
|
catch (e) {
|
|
131
145
|
this.logger.error('Failed to refresh replication jobs', e);
|
|
132
146
|
}
|
|
133
|
-
|
|
147
|
+
if (Date.now() >= fastRefreshDeadline) {
|
|
148
|
+
useFastRefresh = false;
|
|
149
|
+
}
|
|
150
|
+
await sleep(useFastRefresh ? FAST_REFRESH_INTERVAL_MS : REFRESH_INTERVAL_MS);
|
|
134
151
|
}
|
|
135
152
|
}
|
|
136
153
|
async refresh(options) {
|
|
137
154
|
if (this.stopped) {
|
|
138
|
-
return;
|
|
155
|
+
return { replicationJobStarted: false };
|
|
139
156
|
}
|
|
140
|
-
let configuredLock = options?.
|
|
157
|
+
let configuredLock = options?.configuredLock;
|
|
158
|
+
let replicationJobStarted = false;
|
|
141
159
|
const existingJobs = new Map(this.replicationJobs.entries());
|
|
142
160
|
const replicatingStreams = await this.storage.getReplicatingReplicationStreams();
|
|
143
161
|
const newJobs = new Map();
|
|
162
|
+
const streamsToStart = [];
|
|
144
163
|
let activeJob = undefined;
|
|
145
164
|
for (let replicationStream of replicatingStreams) {
|
|
146
165
|
const jobId = replicationStream.replicationJobId;
|
|
147
166
|
const existingJob = existingJobs.get(jobId);
|
|
167
|
+
const syncConfigMismatchMessage = 'Ignoring replication stream for sync config not loaded by this process';
|
|
168
|
+
if (!this.shouldHandleReplicationStream(replicationStream, options?.loadedSyncConfig)) {
|
|
169
|
+
this.logReplicationStreamInfoOnce(replicationStream, 'sync-config-mismatch', () => {
|
|
170
|
+
replicationStream.logger.info(syncConfigMismatchMessage);
|
|
171
|
+
});
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
this.clearReplicationStreamInfoLog(replicationStream, 'sync-config-mismatch');
|
|
148
175
|
if (replicationStream.state == storage.SyncRuleState.ACTIVE && activeJob == null) {
|
|
149
176
|
activeJob = existingJob;
|
|
150
177
|
}
|
|
@@ -160,47 +187,11 @@ export class AbstractReplicator {
|
|
|
160
187
|
}
|
|
161
188
|
else {
|
|
162
189
|
// New sync config was found (or resume after restart)
|
|
163
|
-
|
|
164
|
-
let lock;
|
|
165
|
-
if (configuredLock?.sync_rules_id == replicationStream.replicationStreamId) {
|
|
166
|
-
lock = configuredLock;
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
lock = await replicationStream.lock();
|
|
170
|
-
}
|
|
171
|
-
const syncRuleStorage = this.storage.getInstance(replicationStream);
|
|
172
|
-
const newJob = this.createJob({
|
|
173
|
-
lock: lock,
|
|
174
|
-
storage: syncRuleStorage
|
|
175
|
-
});
|
|
176
|
-
newJobs.set(jobId, newJob);
|
|
177
|
-
newJob.start();
|
|
178
|
-
if (replicationStream.state == storage.SyncRuleState.ACTIVE) {
|
|
179
|
-
activeJob = newJob;
|
|
180
|
-
}
|
|
181
|
-
this.lockAlerted = false;
|
|
182
|
-
}
|
|
183
|
-
catch (e) {
|
|
184
|
-
if (e?.errorData?.code === ErrorCode.PSYNC_S1003) {
|
|
185
|
-
if (!this.lockAlerted) {
|
|
186
|
-
replicationStream.logger.info(`[${e.errorData.code}] ${e.errorData.description}`);
|
|
187
|
-
this.lockAlerted = true;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
// Could be a sync config parse error,
|
|
192
|
-
// for example from stricter validation that was added.
|
|
193
|
-
// This will be retried every couple of seconds.
|
|
194
|
-
// When new (valid) sync config is deployed and processed, this one be disabled.
|
|
195
|
-
replicationStream.logger.error('Failed to start replication for new sync config', e);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
190
|
+
streamsToStart.push(replicationStream);
|
|
198
191
|
}
|
|
199
192
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
// Stop any orphaned jobs that no longer have a replication stream.
|
|
203
|
-
// Termination happens below
|
|
193
|
+
// Stop any orphaned jobs that no longer have a replication stream before starting replacements.
|
|
194
|
+
// Termination happens below.
|
|
204
195
|
for (let job of existingJobs.values()) {
|
|
205
196
|
// Old - stop and clean up
|
|
206
197
|
try {
|
|
@@ -211,6 +202,46 @@ export class AbstractReplicator {
|
|
|
211
202
|
job.storage.logger.warn('Failed to stop old replication job', e);
|
|
212
203
|
}
|
|
213
204
|
}
|
|
205
|
+
for (let replicationStream of streamsToStart) {
|
|
206
|
+
const jobId = replicationStream.replicationJobId;
|
|
207
|
+
try {
|
|
208
|
+
let lock;
|
|
209
|
+
if (configuredLock?.sync_rules_id == replicationStream.replicationStreamId) {
|
|
210
|
+
lock = configuredLock;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
lock = await replicationStream.lock();
|
|
214
|
+
}
|
|
215
|
+
const syncRuleStorage = this.storage.getInstance(replicationStream);
|
|
216
|
+
const newJob = this.createJob({
|
|
217
|
+
lock: lock,
|
|
218
|
+
storage: syncRuleStorage
|
|
219
|
+
});
|
|
220
|
+
newJobs.set(jobId, newJob);
|
|
221
|
+
newJob.start();
|
|
222
|
+
replicationJobStarted = true;
|
|
223
|
+
if (replicationStream.state == storage.SyncRuleState.ACTIVE) {
|
|
224
|
+
activeJob = newJob;
|
|
225
|
+
}
|
|
226
|
+
this.lastReplicationStreamInfoLogs.delete(replicationStream.replicationStreamName);
|
|
227
|
+
}
|
|
228
|
+
catch (e) {
|
|
229
|
+
if (e?.errorData?.code === ErrorCode.PSYNC_S1003) {
|
|
230
|
+
this.logReplicationStreamInfoOnce(replicationStream, 'replication-stream-locked', () => {
|
|
231
|
+
replicationStream.logger.info(`[${e.errorData.code}] ${e.errorData.description}`);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
// Could be a sync config parse error,
|
|
236
|
+
// for example from stricter validation that was added.
|
|
237
|
+
// This will be retried every couple of seconds.
|
|
238
|
+
// When new (valid) sync config is deployed and processed, this one be disabled.
|
|
239
|
+
replicationStream.logger.error('Failed to start replication for new sync config', e);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
this.replicationJobs = newJobs;
|
|
244
|
+
this.activeReplicationJob = activeJob;
|
|
214
245
|
// Replication stream stopped previously, including by a different process.
|
|
215
246
|
const stopped = await this.storage.getStoppedReplicationStreams();
|
|
216
247
|
for (let replicationStream of stopped) {
|
|
@@ -231,6 +262,34 @@ export class AbstractReplicator {
|
|
|
231
262
|
});
|
|
232
263
|
this.clearingJobs.set(replicationStream.replicationStreamId, promise);
|
|
233
264
|
}
|
|
265
|
+
return { replicationJobStarted };
|
|
266
|
+
}
|
|
267
|
+
logReplicationStreamInfoOnce(replicationStream, category, log) {
|
|
268
|
+
if (this.lastReplicationStreamInfoLogs.get(replicationStream.replicationStreamName) == category) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
log();
|
|
272
|
+
this.lastReplicationStreamInfoLogs.set(replicationStream.replicationStreamName, category);
|
|
273
|
+
}
|
|
274
|
+
clearReplicationStreamInfoLog(replicationStream, category) {
|
|
275
|
+
if (this.lastReplicationStreamInfoLogs.get(replicationStream.replicationStreamName) == category) {
|
|
276
|
+
this.lastReplicationStreamInfoLogs.delete(replicationStream.replicationStreamName);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* When we load sync config from the filesystem/config source, we ignore any config loaded by other processes.
|
|
281
|
+
* The idea is that if a different process loads updated config, that process should process it, not this one.
|
|
282
|
+
*
|
|
283
|
+
* This specifically helps for cases with rolling deploys.
|
|
284
|
+
*
|
|
285
|
+
* This does not apply when sync config is loaded from the database/API, instead of in the config.
|
|
286
|
+
*/
|
|
287
|
+
shouldHandleReplicationStream(replicationStream, loadedSyncRules) {
|
|
288
|
+
if (loadedSyncRules == null) {
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
const processingConfig = replicationStream.syncConfigContent.find((syncConfig) => syncConfig.syncConfigState == storage.SyncRuleState.PROCESSING);
|
|
292
|
+
return processingConfig == null || processingConfig.sync_rules_content == loadedSyncRules;
|
|
234
293
|
}
|
|
235
294
|
createJobId(syncRuleId) {
|
|
236
295
|
return `${this.id}-${syncRuleId}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractReplicator.js","sourceRoot":"","sources":["../../src/replication/AbstractReplicator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"AbstractReplicator.js","sourceRoot":"","sources":["../../src/replication/AbstractReplicator.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,17 +19,22 @@ export class RouterEngine {
|
|
|
19
19
|
this.closed = false;
|
|
20
20
|
this.routes = {
|
|
21
21
|
api_routes: [],
|
|
22
|
+
checkpointing_routes: [],
|
|
22
23
|
stream_routes: [],
|
|
23
24
|
socket_routes: []
|
|
24
25
|
};
|
|
25
26
|
}
|
|
26
27
|
registerRoutes(routes) {
|
|
27
28
|
this.routes.api_routes.push(...(routes.api_routes ?? []));
|
|
29
|
+
this.routes.checkpointing_routes.push(...(routes.checkpointing_routes ?? []));
|
|
28
30
|
this.routes.stream_routes.push(...(routes.stream_routes ?? []));
|
|
29
31
|
this.routes.socket_routes.push(...(routes.socket_routes ?? []));
|
|
30
32
|
}
|
|
31
33
|
get hasRoutes() {
|
|
32
|
-
return (this.routes.api_routes.length > 0 ||
|
|
34
|
+
return (this.routes.api_routes.length > 0 ||
|
|
35
|
+
this.routes.checkpointing_routes.length > 0 ||
|
|
36
|
+
this.routes.stream_routes.length > 0 ||
|
|
37
|
+
this.routes.socket_routes.length > 0);
|
|
33
38
|
}
|
|
34
39
|
registerAPI(api) {
|
|
35
40
|
if (this.api) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouterEngine.js","sourceRoot":"","sources":["../../src/routes/RouterEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"RouterEngine.js","sourceRoot":"","sources":["../../src/routes/RouterEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@ export type RouteRegistrationOptions = {
|
|
|
16
16
|
*/
|
|
17
17
|
export type RouteDefinitions = {
|
|
18
18
|
api?: Partial<RouteRegistrationOptions>;
|
|
19
|
+
checkpointing?: Partial<RouteRegistrationOptions>;
|
|
19
20
|
sync_stream?: Partial<RouteRegistrationOptions>;
|
|
20
21
|
};
|
|
21
22
|
export type FastifyServerConfig = {
|
|
@@ -656,50 +657,6 @@ export declare const DEFAULT_ROUTE_OPTIONS: {
|
|
|
656
657
|
}[];
|
|
657
658
|
content?: string | undefined;
|
|
658
659
|
}>;
|
|
659
|
-
}) | (import("@powersync/lib-services-framework").Endpoint<{
|
|
660
|
-
client_id?: string | undefined;
|
|
661
|
-
}, {
|
|
662
|
-
checkpoint: bigint;
|
|
663
|
-
}, import("./router.js").Context, import("./router.js").RequestEndpointHandlerPayload<{
|
|
664
|
-
client_id?: string | undefined;
|
|
665
|
-
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>, import("@powersync/lib-services-framework").EndpointHandler<import("./router.js").RequestEndpointHandlerPayload<{
|
|
666
|
-
client_id?: string | undefined;
|
|
667
|
-
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>, {
|
|
668
|
-
checkpoint: bigint;
|
|
669
|
-
}>> & {
|
|
670
|
-
path: string;
|
|
671
|
-
method: import("@powersync/lib-services-framework").HTTPMethod.GET;
|
|
672
|
-
authorize: (payload: import("./router.js").RequestEndpointHandlerPayload) => Promise<import("@powersync/lib-services-framework").AuthorizationResponse>;
|
|
673
|
-
validator: import("@powersync/lib-services-framework").MicroValidator<{
|
|
674
|
-
client_id?: string | undefined;
|
|
675
|
-
}, string[]>;
|
|
676
|
-
handler: (payload: import("./router.js").RequestEndpointHandlerPayload<{
|
|
677
|
-
client_id?: string | undefined;
|
|
678
|
-
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>) => Promise<{
|
|
679
|
-
checkpoint: bigint;
|
|
680
|
-
}>;
|
|
681
|
-
}) | (import("@powersync/lib-services-framework").Endpoint<{
|
|
682
|
-
client_id?: string | undefined;
|
|
683
|
-
}, {
|
|
684
|
-
write_checkpoint: string;
|
|
685
|
-
}, import("./router.js").Context, import("./router.js").RequestEndpointHandlerPayload<{
|
|
686
|
-
client_id?: string | undefined;
|
|
687
|
-
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>, import("@powersync/lib-services-framework").EndpointHandler<import("./router.js").RequestEndpointHandlerPayload<{
|
|
688
|
-
client_id?: string | undefined;
|
|
689
|
-
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>, {
|
|
690
|
-
write_checkpoint: string;
|
|
691
|
-
}>> & {
|
|
692
|
-
path: string;
|
|
693
|
-
method: import("@powersync/lib-services-framework").HTTPMethod.GET;
|
|
694
|
-
authorize: (payload: import("./router.js").RequestEndpointHandlerPayload) => Promise<import("@powersync/lib-services-framework").AuthorizationResponse>;
|
|
695
|
-
validator: import("@powersync/lib-services-framework").MicroValidator<{
|
|
696
|
-
client_id?: string | undefined;
|
|
697
|
-
}, string[]>;
|
|
698
|
-
handler: (payload: import("./router.js").RequestEndpointHandlerPayload<{
|
|
699
|
-
client_id?: string | undefined;
|
|
700
|
-
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>) => Promise<{
|
|
701
|
-
write_checkpoint: string;
|
|
702
|
-
}>;
|
|
703
660
|
}) | (import("@powersync/lib-services-framework").Endpoint<unknown, import("@powersync/lib-services-framework").RouterResponse<{
|
|
704
661
|
ready: boolean;
|
|
705
662
|
started: boolean;
|
|
@@ -805,6 +762,57 @@ export declare const DEFAULT_ROUTE_OPTIONS: {
|
|
|
805
762
|
max_queue_depth: number;
|
|
806
763
|
};
|
|
807
764
|
};
|
|
765
|
+
checkpointing: {
|
|
766
|
+
routes: ((import("@powersync/lib-services-framework").Endpoint<{
|
|
767
|
+
client_id?: string | undefined;
|
|
768
|
+
}, {
|
|
769
|
+
checkpoint: bigint;
|
|
770
|
+
}, import("./router.js").Context, import("./router.js").RequestEndpointHandlerPayload<{
|
|
771
|
+
client_id?: string | undefined;
|
|
772
|
+
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>, import("@powersync/lib-services-framework").EndpointHandler<import("./router.js").RequestEndpointHandlerPayload<{
|
|
773
|
+
client_id?: string | undefined;
|
|
774
|
+
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>, {
|
|
775
|
+
checkpoint: bigint;
|
|
776
|
+
}>> & {
|
|
777
|
+
path: string;
|
|
778
|
+
method: import("@powersync/lib-services-framework").HTTPMethod.GET;
|
|
779
|
+
authorize: (payload: import("./router.js").RequestEndpointHandlerPayload) => Promise<import("@powersync/lib-services-framework").AuthorizationResponse>;
|
|
780
|
+
validator: import("@powersync/lib-services-framework").MicroValidator<{
|
|
781
|
+
client_id?: string | undefined;
|
|
782
|
+
}, string[]>;
|
|
783
|
+
handler: (payload: import("./router.js").RequestEndpointHandlerPayload<{
|
|
784
|
+
client_id?: string | undefined;
|
|
785
|
+
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>) => Promise<{
|
|
786
|
+
checkpoint: bigint;
|
|
787
|
+
}>;
|
|
788
|
+
}) | (import("@powersync/lib-services-framework").Endpoint<{
|
|
789
|
+
client_id?: string | undefined;
|
|
790
|
+
}, {
|
|
791
|
+
write_checkpoint: string;
|
|
792
|
+
}, import("./router.js").Context, import("./router.js").RequestEndpointHandlerPayload<{
|
|
793
|
+
client_id?: string | undefined;
|
|
794
|
+
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>, import("@powersync/lib-services-framework").EndpointHandler<import("./router.js").RequestEndpointHandlerPayload<{
|
|
795
|
+
client_id?: string | undefined;
|
|
796
|
+
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>, {
|
|
797
|
+
write_checkpoint: string;
|
|
798
|
+
}>> & {
|
|
799
|
+
path: string;
|
|
800
|
+
method: import("@powersync/lib-services-framework").HTTPMethod.GET;
|
|
801
|
+
authorize: (payload: import("./router.js").RequestEndpointHandlerPayload) => Promise<import("@powersync/lib-services-framework").AuthorizationResponse>;
|
|
802
|
+
validator: import("@powersync/lib-services-framework").MicroValidator<{
|
|
803
|
+
client_id?: string | undefined;
|
|
804
|
+
}, string[]>;
|
|
805
|
+
handler: (payload: import("./router.js").RequestEndpointHandlerPayload<{
|
|
806
|
+
client_id?: string | undefined;
|
|
807
|
+
}, import("./router.js").Context, import("./router.js").BasicRouterRequest>) => Promise<{
|
|
808
|
+
write_checkpoint: string;
|
|
809
|
+
}>;
|
|
810
|
+
}))[];
|
|
811
|
+
queue_options: {
|
|
812
|
+
concurrency: number;
|
|
813
|
+
max_queue_depth: number;
|
|
814
|
+
};
|
|
815
|
+
};
|
|
808
816
|
sync_stream: {
|
|
809
817
|
routes: (import("@powersync/lib-services-framework").Endpoint<{
|
|
810
818
|
parameters?: Record<string, any> | undefined;
|
|
@@ -7,12 +7,20 @@ import { SYNC_STREAM_ROUTES } from './endpoints/sync-stream.js';
|
|
|
7
7
|
import { createRequestQueueHook } from './hooks.js';
|
|
8
8
|
export const DEFAULT_ROUTE_OPTIONS = {
|
|
9
9
|
api: {
|
|
10
|
-
routes: [...ADMIN_ROUTES, ...
|
|
10
|
+
routes: [...ADMIN_ROUTES, ...SYNC_RULES_ROUTES, ...PROBES_ROUTES],
|
|
11
11
|
queue_options: {
|
|
12
12
|
concurrency: 10,
|
|
13
13
|
max_queue_depth: 20
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
|
+
checkpointing: {
|
|
17
|
+
routes: [...CHECKPOINT_ROUTES],
|
|
18
|
+
queue_options: {
|
|
19
|
+
// Note that the values here has an effect on WriteCheckpointBatcher
|
|
20
|
+
concurrency: 100,
|
|
21
|
+
max_queue_depth: 100
|
|
22
|
+
}
|
|
23
|
+
},
|
|
16
24
|
sync_stream: {
|
|
17
25
|
routes: [...SYNC_STREAM_ROUTES],
|
|
18
26
|
queue_options: {
|
|
@@ -35,6 +43,7 @@ export function configureFastifyServer(server, options) {
|
|
|
35
43
|
};
|
|
36
44
|
// Set on the outer server so both child scopes inherit.
|
|
37
45
|
registerFastifyErrorHandler(server);
|
|
46
|
+
registerFastifyNotFoundHandler(server);
|
|
38
47
|
/**
|
|
39
48
|
* Fastify creates an encapsulated context for each `.register` call.
|
|
40
49
|
* Creating a separate context here to separate the concurrency limits for Admin APIs
|
|
@@ -43,10 +52,14 @@ export function configureFastifyServer(server, options) {
|
|
|
43
52
|
*/
|
|
44
53
|
server.register(async function (childContext) {
|
|
45
54
|
registerFastifyRoutes(childContext, generateContext, routes.api?.routes ?? DEFAULT_ROUTE_OPTIONS.api.routes);
|
|
46
|
-
registerFastifyNotFoundHandler(childContext);
|
|
47
55
|
// Limit the active concurrent requests
|
|
48
56
|
childContext.addHook('onRequest', createRequestQueueHook(routes.api?.queue_options ?? DEFAULT_ROUTE_OPTIONS.api.queue_options));
|
|
49
57
|
});
|
|
58
|
+
server.register(async function (childContext) {
|
|
59
|
+
registerFastifyRoutes(childContext, generateContext, routes.checkpointing?.routes ?? DEFAULT_ROUTE_OPTIONS.checkpointing.routes);
|
|
60
|
+
// Limit the active concurrent requests
|
|
61
|
+
childContext.addHook('onRequest', createRequestQueueHook(routes.checkpointing?.queue_options ?? DEFAULT_ROUTE_OPTIONS.checkpointing.queue_options));
|
|
62
|
+
});
|
|
50
63
|
// Create a separate context for concurrency queueing
|
|
51
64
|
server.register(async function (childContext) {
|
|
52
65
|
registerFastifyRoutes(childContext, generateContext, routes.sync_stream?.routes ?? DEFAULT_ROUTE_OPTIONS.sync_stream.routes);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure-fastify.js","sourceRoot":"","sources":["../../src/routes/configure-fastify.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,EAC9B,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;AAI7B,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;
|
|
1
|
+
{"version":3,"file":"configure-fastify.js","sourceRoot":"","sources":["../../src/routes/configure-fastify.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,EAC9B,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;AAI7B,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;AA2B9E,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,GAAG,EAAE;QACH,MAAM,EAAE,CAAC,GAAG,YAAY,EAAE,GAAG,iBAAiB,EAAE,GAAG,aAAa,CAAC;QACjE,aAAa,EAAE;YACb,WAAW,EAAE,EAAE;YACf,eAAe,EAAE,EAAE;SACpB;KACF;IACD,aAAa,EAAE;QACb,MAAM,EAAE,CAAC,GAAG,iBAAiB,CAAC;QAC9B,aAAa,EAAE;YACb,oEAAoE;YACpE,WAAW,EAAE,GAAG;YAChB,eAAe,EAAE,GAAG;SACrB;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,eAAe,EAAE,eAAe;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC;IACJ,CAAC,CAAC;IAEF,wDAAwD;IACxD,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,8BAA8B,CAAC,MAAM,CAAC,CAAC;IAEvC;;;;;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;QAE7G,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,MAAM,CAAC,QAAQ,CAAC,KAAK,WAAW,YAAY;QAC1C,qBAAqB,CACnB,YAAY,EACZ,eAAe,EACf,MAAM,CAAC,aAAa,EAAE,MAAM,IAAI,qBAAqB,CAAC,aAAa,CAAC,MAAM,CAC3E,CAAC;QAEF,uCAAuC;QACvC,YAAY,CAAC,OAAO,CAClB,WAAW,EACX,sBAAsB,CAAC,MAAM,CAAC,aAAa,EAAE,aAAa,IAAI,qBAAqB,CAAC,aAAa,CAAC,aAAa,CAAC,CACjH,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"}
|