@rocicorp/zero 1.11.0-canary.5 → 1.11.0-canary.7
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/out/analyze-query/src/analyze-cli.js +2 -2
- package/out/analyze-query/src/analyze-cli.js.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js +27 -4
- package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/sqlite-store.d.ts +11 -0
- package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
- package/out/replicache/src/kv/sqlite-store.js +43 -3
- package/out/replicache/src/kv/sqlite-store.js.map +1 -1
- package/out/shared/src/error.d.ts +11 -0
- package/out/shared/src/error.d.ts.map +1 -1
- package/out/shared/src/error.js +35 -1
- package/out/shared/src/error.js.map +1 -1
- package/out/shared/src/map.d.ts +7 -2
- package/out/shared/src/map.d.ts.map +1 -1
- package/out/shared/src/map.js.map +1 -1
- package/out/zero/package.js +2 -2
- package/out/zero/package.js.map +1 -1
- package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
- package/out/zero-cache/src/config/normalize.js +7 -1
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +9 -2
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +26 -7
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +15 -6
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/main.d.ts.map +1 -1
- package/out/zero-cache/src/server/main.js +8 -1
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/mutator.js +2 -0
- package/out/zero-cache/src/server/mutator.js.map +1 -1
- package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
- package/out/zero-cache/src/server/reaper.js +2 -0
- package/out/zero-cache/src/server/reaper.js.map +1 -1
- package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/server/replicator.js +2 -0
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.js +3 -0
- package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +2 -0
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js +14 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +15 -3
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +2 -2
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +68 -8
- package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js +58 -7
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -4
- package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-log-codec.js +28 -8
- package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +3 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +6 -4
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +6 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +86 -51
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.js +4 -4
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +3 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.js +54 -20
- package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +6 -1
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +27 -9
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.d.ts +2 -2
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +8 -5
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +51 -24
- package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts +5 -0
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +7 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +2 -1
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/profz.d.ts +7 -0
- package/out/zero-cache/src/services/profz.d.ts.map +1 -0
- package/out/zero-cache/src/services/profz.js +105 -0
- package/out/zero-cache/src/services/profz.js.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +5 -4
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +20 -22
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -1
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +6 -6
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +19 -14
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -1
- package/out/zero-cache/src/services/runner.d.ts.map +1 -1
- package/out/zero-cache/src/services/runner.js +1 -1
- package/out/zero-cache/src/services/runner.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts +17 -0
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +59 -0
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts +51 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +78 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +18 -6
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +174 -6
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/processes.d.ts +32 -0
- package/out/zero-cache/src/types/processes.d.ts.map +1 -1
- package/out/zero-cache/src/types/processes.js +43 -4
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/profiler.d.ts +12 -0
- package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
- package/out/zero-cache/src/types/profiler.js +46 -1
- package/out/zero-cache/src/types/profiler.js.map +1 -1
- package/out/zero-cache/src/workers/connection.js +3 -3
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +21 -16
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +10 -1
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +46 -0
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +12 -8
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-protocol/src/down.d.ts +27 -27
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-react/src/use-query.js +50 -3
- package/out/zero-react/src/use-query.js.map +1 -1
- package/out/zero-solid/src/use-query.js +1 -2
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zql/src/ivm/data.d.ts.map +1 -1
- package/out/zql/src/ivm/data.js +8 -3
- package/out/zql/src/ivm/data.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +6 -1
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zqlite/src/db.d.ts +9 -1
- package/out/zqlite/src/db.d.ts.map +1 -1
- package/out/zqlite/src/db.js +8 -2
- package/out/zqlite/src/db.js.map +1 -1
- package/package.json +2 -2
|
@@ -11,6 +11,7 @@ import { Subscription } from "../../types/subscription.js";
|
|
|
11
11
|
import { AutoResetSignal, ensureReplicationConfig, markResetRequired } from "./schema/tables.js";
|
|
12
12
|
import { publishReplicationError, replicationStatusError } from "../replicator/replication-status.js";
|
|
13
13
|
import "./change-streamer.js";
|
|
14
|
+
import { serializeChangeStreamDataWithChange } from "./change-log-codec.js";
|
|
14
15
|
import { SQLiteChangeLogReader } from "./sqlite-change-log-reader.js";
|
|
15
16
|
import { ChangeLogInitializer, replicaInitializationSource } from "./change-log-initializer.js";
|
|
16
17
|
import { Forwarder } from "./forwarder.js";
|
|
@@ -32,7 +33,7 @@ import { getDefaultHighWaterMark } from "node:stream";
|
|
|
32
33
|
* Performs initialization and schema migrations to initialize a ChangeStreamerImpl.
|
|
33
34
|
*/
|
|
34
35
|
async function initializeStreamer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, changeSource, replicationStatusPublisher, subscriptionState, backupConfig, purgeLock, autoReset, opts, setTimeoutFn = setTimeout) {
|
|
35
|
-
await ensureReplicationConfig(lc, changeDB, subscriptionState, shard, autoReset, purgeLock ?? void 0, setTimeoutFn);
|
|
36
|
+
await ensureReplicationConfig(lc, changeDB, subscriptionState, shard, autoReset, purgeLock ?? void 0, setTimeoutFn, opts.pgChangeLogEnabled);
|
|
36
37
|
const changeDBProvider = (applicationName, max) => postgres(defu({
|
|
37
38
|
max,
|
|
38
39
|
connection: { ["application_name"]: applicationName }
|
|
@@ -188,6 +189,7 @@ var ChangeStreamerImpl = class {
|
|
|
188
189
|
#replicaVersion;
|
|
189
190
|
#source;
|
|
190
191
|
#storer;
|
|
192
|
+
#pgChangeLogEnabled;
|
|
191
193
|
#forwarder;
|
|
192
194
|
#reservations;
|
|
193
195
|
#replicationStatusPublisher;
|
|
@@ -237,6 +239,11 @@ var ChangeStreamerImpl = class {
|
|
|
237
239
|
this.#changeDBProvider = changeDBProvider;
|
|
238
240
|
this.#replicaVersion = replicaVersion;
|
|
239
241
|
this.#source = source;
|
|
242
|
+
this.#pgChangeLogEnabled = opts.pgChangeLogEnabled;
|
|
243
|
+
if (!this.#pgChangeLogEnabled) {
|
|
244
|
+
assert(opts.sqliteChangeLogWriter && opts.sqliteChangeLogPurge && opts.sqliteCatchup && opts.sqliteChangeLogServe?.readPercent === 100 && opts.sqliteChangeLogServe.coldReadPercent === 100 && backupConfig?.litestreamVersion === "v5", "disabling the PG change log requires SQLite serving at 100 percent and a v5 backup");
|
|
245
|
+
assert(opts.sqliteChangeLogCompare === void 0, "SQLite change-log comparison requires the PG change log");
|
|
246
|
+
}
|
|
240
247
|
this.#storer = new Storer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDBProvider, replicaVersion, (consumed) => this.#acker.trackPgChangeLog(consumed[2].watermark), (err) => this.stop(err), opts);
|
|
241
248
|
this.#forwarder = new Forwarder(lc, {
|
|
242
249
|
flowControlConsensusTimeoutProportion: opts.flowControlConsensusTimeoutProportion,
|
|
@@ -277,12 +284,13 @@ var ChangeStreamerImpl = class {
|
|
|
277
284
|
}) : void 0;
|
|
278
285
|
this.#purgeScheduler = opts.sqliteChangeLogPurge && this.#changeLogWriter ? new SQLiteChangeLogPurgeScheduler(lc, () => this.#changeLogWriter?.connection, () => this.#forwarder.getAcks(), opts.sqliteChangeLogPurge) : void 0;
|
|
279
286
|
this.#acker = new UpstreamAcker({
|
|
280
|
-
trackPgChangeLog:
|
|
287
|
+
trackPgChangeLog: this.#pgChangeLogEnabled,
|
|
281
288
|
trackBackup: backupConfig?.litestreamVersion === "v5"
|
|
282
289
|
});
|
|
283
|
-
const
|
|
290
|
+
const replicaFileForInitialization = opts.sqliteChangeLogCompare?.replicaFile ?? (!this.#pgChangeLogEnabled ? opts.sqliteChangeLogWriter?.replicaFile : void 0);
|
|
291
|
+
const replicaSource = replicaFileForInitialization ? replicaInitializationSource(lc, replicaFileForInitialization) : void 0;
|
|
284
292
|
this.#initializer = new ChangeLogInitializer(lc, {
|
|
285
|
-
initFromPgChangeLog:
|
|
293
|
+
initFromPgChangeLog: this.#pgChangeLogEnabled,
|
|
286
294
|
initFromReplica: replicaSource !== void 0
|
|
287
295
|
}, {
|
|
288
296
|
pgChangeLog: () => this.#storer.getStartStreamInitializationParameters(),
|
|
@@ -294,7 +302,7 @@ var ChangeStreamerImpl = class {
|
|
|
294
302
|
...opts.sqliteCatchup,
|
|
295
303
|
cleanupGuard: opts.sqliteCatchup.cleanupGuard ?? this.#purgeScheduler?.cleanupGuard
|
|
296
304
|
} : void 0;
|
|
297
|
-
this.#comparator = opts.sqliteChangeLogCompare && opts.sqliteChangeLogWriter && opts.sqliteCatchup ? new SQLiteChangeLogComparator(lc, shard, opts.sqliteCatchup.changeLogFile, opts.sqliteChangeLogWriter.identity, this.#storer, {
|
|
305
|
+
this.#comparator = this.#pgChangeLogEnabled && opts.sqliteChangeLogCompare && opts.sqliteChangeLogWriter && opts.sqliteCatchup ? new SQLiteChangeLogComparator(lc, shard, opts.sqliteCatchup.changeLogFile, opts.sqliteChangeLogWriter.identity, this.#storer, {
|
|
298
306
|
setTimeoutFn,
|
|
299
307
|
...opts.sqliteChangeLogCompare
|
|
300
308
|
}) : void 0;
|
|
@@ -322,7 +330,7 @@ var ChangeStreamerImpl = class {
|
|
|
322
330
|
const { lastWatermark, backfillRequests } = await this.#initializer.initialize();
|
|
323
331
|
this.#lastForwardedCommitWatermark = lastWatermark;
|
|
324
332
|
const stream = await this.#source.startStream(lastWatermark, backfillRequests);
|
|
325
|
-
this.#storer.run().catch((e) => stream.changes.cancel(e));
|
|
333
|
+
if (this.#pgChangeLogEnabled) this.#storer.run().catch((e) => stream.changes.cancel(e));
|
|
326
334
|
this.#stream = stream;
|
|
327
335
|
if (this.#state.resetBackoff() > REPLICATION_STATUS_ERROR_DELAY_THRESHOLD_MS) this.#replicationStatusPublisher.publish(this.#lc, "Replicating", `Replicating from ${lastWatermark}`);
|
|
328
336
|
watermark = null;
|
|
@@ -353,8 +361,10 @@ var ChangeStreamerImpl = class {
|
|
|
353
361
|
if (watermark === null) throw new UnrecoverableError(`${type} change (${msg.tag}) received before 'begin' message`);
|
|
354
362
|
break;
|
|
355
363
|
}
|
|
356
|
-
const
|
|
357
|
-
|
|
364
|
+
const serialized = serializeChangeStreamDataWithChange(change);
|
|
365
|
+
const { json } = serialized;
|
|
366
|
+
if (this.#pgChangeLogEnabled) this.#storer.store(watermark, change, serialized);
|
|
367
|
+
this.#changeLogWriter?.write(change, json, serialized.change);
|
|
358
368
|
const entry = [
|
|
359
369
|
watermark,
|
|
360
370
|
change[1].tag,
|
|
@@ -371,7 +381,7 @@ var ChangeStreamerImpl = class {
|
|
|
371
381
|
unflushedBytes = 0;
|
|
372
382
|
}
|
|
373
383
|
if (type === "commit" || type === "rollback") watermark = null;
|
|
374
|
-
const readyForMore = this.#storer.readyForMore();
|
|
384
|
+
const readyForMore = this.#pgChangeLogEnabled ? this.#storer.readyForMore() : void 0;
|
|
375
385
|
if (readyForMore) await promiseOrAbort(readyForMore, stream.changes.signal, this.#state.signal);
|
|
376
386
|
}
|
|
377
387
|
} catch (e) {
|
|
@@ -382,7 +392,7 @@ var ChangeStreamerImpl = class {
|
|
|
382
392
|
}
|
|
383
393
|
if (watermark) {
|
|
384
394
|
this.#lc.warn?.(`aborting interrupted transaction ${watermark}`);
|
|
385
|
-
this.#storer.abort();
|
|
395
|
+
if (this.#pgChangeLogEnabled) this.#storer.abort();
|
|
386
396
|
this.#changeLogWriter?.abort();
|
|
387
397
|
this.#purgeScheduler?.onWriterIdle();
|
|
388
398
|
this.#forwarder.forward([
|
|
@@ -434,14 +444,19 @@ var ChangeStreamerImpl = class {
|
|
|
434
444
|
} else {
|
|
435
445
|
lc.info?.(`adding subscriber ${subscriber.id}`);
|
|
436
446
|
const catchupFromPG = () => {
|
|
447
|
+
assert(this.#pgChangeLogEnabled, "cannot catch up from a disabled PG change log");
|
|
437
448
|
cleanupSubscriber = removeFromForwarder;
|
|
438
449
|
this.#forwarder.add(subscriber);
|
|
439
450
|
this.#storer.catchup(subscriber, mode);
|
|
440
451
|
};
|
|
441
|
-
const
|
|
442
|
-
if (!
|
|
443
|
-
else {
|
|
444
|
-
|
|
452
|
+
const sqliteDecision = this.#selectSQLiteCatchup(lc, ctx);
|
|
453
|
+
if (!sqliteDecision) catchupFromPG();
|
|
454
|
+
else if (sqliteDecision.kind === "rejected") {
|
|
455
|
+
lc.warn?.(`${sqliteDecision.terminal ? "rejecting" : "ending"} subscription for ${ctx.id}: ${sqliteDecision.message}`);
|
|
456
|
+
if (sqliteDecision.terminal) subscriber.close(2, sqliteDecision.message);
|
|
457
|
+
else subscriber.close();
|
|
458
|
+
} else {
|
|
459
|
+
const { catchup, reason, coverage, logWarm } = sqliteDecision;
|
|
445
460
|
cleanupSubscriber = () => catchup.remove(subscriber);
|
|
446
461
|
const registration = await catchup.catchup(subscriber, () => this.#captureRequiredHead(), { logWarm });
|
|
447
462
|
switch (registration.kind) {
|
|
@@ -450,14 +465,27 @@ var ChangeStreamerImpl = class {
|
|
|
450
465
|
this.#recordCatchupRoute("sqlite", reason);
|
|
451
466
|
break;
|
|
452
467
|
case "uncovered":
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
468
|
+
if (this.#pgChangeLogEnabled) {
|
|
469
|
+
lc.info?.(`serving ${ctx.id} from PG catchup: subscriber watermark ${ctx.watermark} is below the SQLite change-log minimum ` + registration.minWatermark);
|
|
470
|
+
this.#recordCatchupRoute("pg", "watermark-uncovered");
|
|
471
|
+
catchupFromPG();
|
|
472
|
+
} else {
|
|
473
|
+
const message = `earliest supported watermark is ${registration.minWatermark} (requested ${ctx.watermark})`;
|
|
474
|
+
lc.warn?.(`rejecting subscriber at watermark ${ctx.watermark}: the SQLite change log starts at ${registration.minWatermark} and the PG change log is disabled`);
|
|
475
|
+
this.#recordCatchupRoute("none", "watermark-uncovered");
|
|
476
|
+
subscriber.close(2, message);
|
|
477
|
+
}
|
|
456
478
|
break;
|
|
457
479
|
case "declined":
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
480
|
+
if (this.#pgChangeLogEnabled) {
|
|
481
|
+
lc.error?.(`serving ${ctx.id} from PG catchup: SQLite catchup registration failed`, registration.error);
|
|
482
|
+
this.#recordCatchupRoute("pg", "registration-failed");
|
|
483
|
+
catchupFromPG();
|
|
484
|
+
} else {
|
|
485
|
+
lc.error?.(`ending subscription for ${ctx.id} to retry SQLite catchup: registration failed and the PG change log is disabled`, registration.error);
|
|
486
|
+
this.#recordCatchupRoute("none", "registration-failed");
|
|
487
|
+
subscriber.fail(registration.error);
|
|
488
|
+
}
|
|
461
489
|
break;
|
|
462
490
|
case "handled":
|
|
463
491
|
this.#recordCatchupRoute("sqlite", "registration-handled");
|
|
@@ -495,13 +523,22 @@ var ChangeStreamerImpl = class {
|
|
|
495
523
|
const backupWatermark = this.#backupWatermark;
|
|
496
524
|
const reservations = this.#reservations;
|
|
497
525
|
if (backupWatermark === void 0 || !reservations?.confirmationsRequired()) return;
|
|
498
|
-
const pgState = await this.#getChangeLogState();
|
|
526
|
+
const pgState = this.#pgChangeLogEnabled ? await this.#getChangeLogState() : void 0;
|
|
499
527
|
for (const taskID of reservations.unconfirmedTaskIDs()) {
|
|
500
528
|
let route = this.#readRouter?.peek(taskID);
|
|
501
529
|
if (this.#readRouter && route === void 0) continue;
|
|
530
|
+
if (!this.#pgChangeLogEnabled && route?.source === "pg") {
|
|
531
|
+
this.#readRouter?.release(taskID);
|
|
532
|
+
route = this.#readRouter?.pin(taskID);
|
|
533
|
+
if (route?.source === "pg") {
|
|
534
|
+
if (reservations.noteConfirmationDelayed(taskID)) this.#reservationConfirmDelays.add(1);
|
|
535
|
+
this.#lc.warn?.(`delaying snapshot reservation for ${taskID}: SQLite change log is unavailable and the PG change log is disabled`);
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
502
539
|
if (route?.source === "sqlite") {
|
|
503
540
|
const coverage = must(route.coverage, "a pinned SQLite route must carry its covered range");
|
|
504
|
-
if (coverage.minWatermark > backupWatermark) {
|
|
541
|
+
if (this.#pgChangeLogEnabled && coverage.minWatermark > backupWatermark) {
|
|
505
542
|
this.#lc.info?.(`demoting ${taskID} to PG catchup: SQLite change-log minimum ${coverage.minWatermark} is later than backupWatermark ` + backupWatermark);
|
|
506
543
|
this.#reservationDemotions.add(1);
|
|
507
544
|
route = must(this.#readRouter).demote(taskID);
|
|
@@ -510,17 +547,17 @@ var ChangeStreamerImpl = class {
|
|
|
510
547
|
const source = route?.source ?? "pg";
|
|
511
548
|
let minWatermark;
|
|
512
549
|
if (route?.source === "sqlite") minWatermark = must(route.coverage, "a pinned SQLite route must carry its covered range").minWatermark;
|
|
513
|
-
else
|
|
514
|
-
if (minWatermark <= backupWatermark) reservations.confirmFor(taskID,
|
|
550
|
+
else minWatermark = must(pgState, "a PG reservation route requires the PG change log").minWatermark;
|
|
551
|
+
if (minWatermark <= backupWatermark) reservations.confirmFor(taskID, this.#replicaVersion, backupWatermark, source);
|
|
515
552
|
else {
|
|
516
553
|
if (reservations.noteConfirmationDelayed(taskID)) this.#reservationConfirmDelays.add(1);
|
|
517
|
-
this.#lc.error?.(
|
|
554
|
+
this.#lc.error?.(`${source} change-log minWatermark ${minWatermark} is later than backupWatermark ${backupWatermark}. Delaying confirmation of snapshot reservation until next backup.`);
|
|
518
555
|
}
|
|
519
556
|
}
|
|
520
557
|
}
|
|
521
558
|
#maybeSchedulePGPurge() {
|
|
522
559
|
const backupWatermark = this.#backupWatermark;
|
|
523
|
-
if (this.#pgPurgeScheduled || this.#pgPurgeRunning || backupWatermark === void 0 || this.#pgPurgedWatermark >= backupWatermark) return;
|
|
560
|
+
if (!this.#pgChangeLogEnabled || this.#pgPurgeScheduled || this.#pgPurgeRunning || backupWatermark === void 0 || this.#pgPurgedWatermark >= backupWatermark) return;
|
|
524
561
|
this.#pgPurgeScheduled = true;
|
|
525
562
|
this.#state.setTimeout(() => {
|
|
526
563
|
this.#pgPurgeScheduled = false;
|
|
@@ -664,14 +701,10 @@ var ChangeStreamerImpl = class {
|
|
|
664
701
|
}
|
|
665
702
|
#selectSQLiteCatchup(lc, ctx) {
|
|
666
703
|
const opts = this.#sqliteCatchupOptions;
|
|
667
|
-
if (this.#lastForwardedCommitWatermark === void 0 || !opts)
|
|
668
|
-
|
|
669
|
-
return;
|
|
670
|
-
}
|
|
671
|
-
if (ctx.mode !== "serving") {
|
|
704
|
+
if (this.#lastForwardedCommitWatermark === void 0 || !opts) return this.#fallbackOrReject("not-ready", "SQLite catchup is not ready and the PG change log is disabled");
|
|
705
|
+
if (ctx.mode === "backup" && this.#pgChangeLogEnabled) {
|
|
672
706
|
lc.info?.(`not serving backup subscriber ${ctx.id} from SQLite catchup`);
|
|
673
|
-
this.#
|
|
674
|
-
return;
|
|
707
|
+
return this.#fallbackOrReject("ineligible-mode", "backup subscribers retain the PG change-log recovery policy");
|
|
675
708
|
}
|
|
676
709
|
let route;
|
|
677
710
|
if (this.#readRouter) {
|
|
@@ -680,33 +713,34 @@ var ChangeStreamerImpl = class {
|
|
|
680
713
|
if (route.reason === "cold-log") lc.info?.(`serving ${ctx.id} from PG catchup: SQLite change log is still warming`, { sqliteChangeLogCoverage: route.coverage });
|
|
681
714
|
else if (route.reason === "log-unavailable") this.#declineSQLiteCatchup(lc, ctx, opts, `${opts.changeLogFile} is unavailable or incompatible`);
|
|
682
715
|
else lc.debug?.(`serving ${ctx.id} from PG catchup: SQLite route ${route.reason}`, ...route.coverage ? [{ sqliteChangeLogCoverage: route.coverage }] : []);
|
|
683
|
-
this.#
|
|
684
|
-
return;
|
|
716
|
+
return this.#fallbackOrReject(route.reason, `SQLite catchup route ${route.reason} is unavailable and the PG change log is disabled`);
|
|
685
717
|
}
|
|
686
718
|
const coverage = route.coverage;
|
|
687
719
|
assert(coverage, "a SQLite route must carry its covered range");
|
|
688
720
|
if (ctx.watermark < coverage.minWatermark) {
|
|
689
721
|
lc.info?.(`serving ${ctx.id} from PG catchup: subscriber watermark ${ctx.watermark} is below the SQLite change-log minimum ` + coverage.minWatermark, { sqliteChangeLogCoverage: coverage });
|
|
690
|
-
this.#
|
|
691
|
-
return;
|
|
722
|
+
return this.#fallbackOrReject("watermark-uncovered", `earliest supported watermark is ${coverage.minWatermark} (requested ${ctx.watermark})`, true);
|
|
692
723
|
}
|
|
693
724
|
}
|
|
694
|
-
if (!this.#readRouter && !opts.shouldUse?.(ctx))
|
|
695
|
-
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
if (this.#readRouter && opts.shouldUse && !opts.shouldUse(ctx)) {
|
|
699
|
-
this.#recordCatchupRoute("pg", "selector");
|
|
700
|
-
return;
|
|
701
|
-
}
|
|
725
|
+
if (!this.#readRouter && !opts.shouldUse?.(ctx)) return this.#fallbackOrReject("selector", "SQLite catchup was not selected and the PG change log is disabled");
|
|
726
|
+
if (this.#readRouter && opts.shouldUse && !opts.shouldUse(ctx)) return this.#fallbackOrReject("selector", "SQLite catchup was not selected and the PG change log is disabled");
|
|
702
727
|
const catchup = this.#sqliteCatchup ?? this.#openSQLiteCatchup(lc, opts, ctx);
|
|
703
728
|
if (catchup) return {
|
|
729
|
+
kind: "selected",
|
|
704
730
|
catchup,
|
|
705
731
|
reason: route?.reason ?? "selector",
|
|
706
732
|
coverage: route?.coverage,
|
|
707
733
|
logWarm: route === void 0 ? void 0 : route.reason !== "selected-cold"
|
|
708
734
|
};
|
|
709
|
-
else this.#
|
|
735
|
+
else return this.#fallbackOrReject("log-unavailable", "SQLite change log is unavailable and the PG change log is disabled");
|
|
736
|
+
}
|
|
737
|
+
#fallbackOrReject(reason, message, terminal = false) {
|
|
738
|
+
this.#recordCatchupRoute(this.#pgChangeLogEnabled ? "pg" : "none", reason);
|
|
739
|
+
return this.#pgChangeLogEnabled ? void 0 : {
|
|
740
|
+
kind: "rejected",
|
|
741
|
+
message,
|
|
742
|
+
terminal
|
|
743
|
+
};
|
|
710
744
|
}
|
|
711
745
|
#recordCatchupRoute(source, reason) {
|
|
712
746
|
this.#catchupRoutes.add(1, {
|
|
@@ -722,10 +756,11 @@ var ChangeStreamerImpl = class {
|
|
|
722
756
|
* first reconcile, and deletes it when it fails soft -- or may exist without
|
|
723
757
|
* content, or may be unreadable. None of those can be allowed to fail a
|
|
724
758
|
* subscription:
|
|
725
|
-
* this is the last point at which PG catchup
|
|
726
|
-
* `Forwarder.add()` the subscriber is committed to SQLite --
|
|
727
|
-
* here instead.
|
|
728
|
-
* subscription retries
|
|
759
|
+
* this is the last point at which PG catchup can be selected when it is
|
|
760
|
+
* enabled -- past `Forwarder.add()` the subscriber is committed to SQLite --
|
|
761
|
+
* so each declines here instead. With PG disabled, the caller ends the
|
|
762
|
+
* subscription so that it retries. Neither the failure nor the reader is
|
|
763
|
+
* retained, so a later subscription retries from scratch.
|
|
729
764
|
*/
|
|
730
765
|
#openSQLiteCatchup(lc, opts, ctx) {
|
|
731
766
|
let reader;
|
|
@@ -763,7 +798,7 @@ var ChangeStreamerImpl = class {
|
|
|
763
798
|
const now = Date.now();
|
|
764
799
|
this.#changeLogUnavailableSince ??= now;
|
|
765
800
|
const unavailableMs = now - this.#changeLogUnavailableSince;
|
|
766
|
-
lc[unavailableMs >= (opts.notReadyWarnThresholdMs ?? DEFAULT_CHANGE_LOG_UNAVAILABLE_WARN_THRESHOLD_MS) ? "warn" : "debug"]?.(`serving ${ctx.id} from PG catchup: ${reason} (unavailable for ${unavailableMs} ms)`, ...error === void 0 ? [] : [error]);
|
|
801
|
+
lc[unavailableMs >= (opts.notReadyWarnThresholdMs ?? DEFAULT_CHANGE_LOG_UNAVAILABLE_WARN_THRESHOLD_MS) ? "warn" : "debug"]?.((this.#pgChangeLogEnabled ? `serving ${ctx.id} from PG catchup: ` : `cannot serve ${ctx.id} from SQLite catchup: `) + `${reason} (unavailable for ${unavailableMs} ms)`, ...error === void 0 ? [] : [error]);
|
|
767
802
|
}
|
|
768
803
|
};
|
|
769
804
|
var CLEANUP_DELAY_MS = DEFAULT_MAX_RETRY_DELAY_MS * 3;
|