@rocicorp/zero 0.12.2025012901 → 0.12.2025013000

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.
Files changed (113) hide show
  1. package/out/advanced.js +1 -1
  2. package/out/{chunk-VYAI3OU4.js → chunk-UEPZPKPV.js} +125 -171
  3. package/out/{chunk-VYAI3OU4.js.map → chunk-UEPZPKPV.js.map} +4 -4
  4. package/out/{chunk-QAAJZ32T.js → chunk-ZVLXEWWB.js} +71 -11
  5. package/out/chunk-ZVLXEWWB.js.map +7 -0
  6. package/out/otel/src/log-options.d.ts +23 -0
  7. package/out/otel/src/log-options.d.ts.map +1 -0
  8. package/out/otel/src/log-options.js +34 -0
  9. package/out/otel/src/log-options.js.map +1 -0
  10. package/out/otel/src/maybe-time.d.ts +3 -0
  11. package/out/otel/src/maybe-time.d.ts.map +1 -0
  12. package/out/otel/src/maybe-time.js +13 -0
  13. package/out/otel/src/maybe-time.js.map +1 -0
  14. package/out/solid.js +2 -2
  15. package/out/zero-cache/src/auth/write-authorizer.d.ts +1 -1
  16. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  17. package/out/zero-cache/src/auth/write-authorizer.js +3 -1
  18. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  19. package/out/zero-cache/src/config/zero-config.d.ts +17 -13
  20. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  21. package/out/zero-cache/src/config/zero-config.js +1 -19
  22. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  23. package/out/zero-cache/src/server/multi/config.d.ts +8 -0
  24. package/out/zero-cache/src/server/multi/config.d.ts.map +1 -1
  25. package/out/zero-cache/src/server/multi/main.d.ts +2 -2
  26. package/out/zero-cache/src/server/multi/main.d.ts.map +1 -1
  27. package/out/zero-cache/src/server/multi/main.js +4 -89
  28. package/out/zero-cache/src/server/multi/main.js.map +1 -1
  29. package/out/zero-cache/src/server/multi/run-worker.d.ts +4 -0
  30. package/out/zero-cache/src/server/multi/run-worker.d.ts.map +1 -0
  31. package/out/zero-cache/src/server/multi/run-worker.js +91 -0
  32. package/out/zero-cache/src/server/multi/run-worker.js.map +1 -0
  33. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  34. package/out/zero-cache/src/server/syncer.js +1 -1
  35. package/out/zero-cache/src/server/syncer.js.map +1 -1
  36. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  37. package/out/zero-cache/src/services/change-source/pg/change-source.js +93 -120
  38. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  39. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +18 -18
  40. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  41. package/out/zero-cache/src/services/change-source/protocol/current/data.js +5 -2
  42. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  43. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +24 -24
  44. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +8 -8
  45. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  46. package/out/zero-cache/src/services/change-streamer/storer.js +3 -2
  47. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  48. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  49. package/out/zero-cache/src/services/life-cycle.js +4 -2
  50. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  51. package/out/zero-cache/src/services/replicator/change-processor.js +7 -3
  52. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  53. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +2 -1
  54. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  55. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +5 -3
  56. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  57. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  58. package/out/zero-cache/src/services/view-syncer/view-syncer.js +26 -2
  59. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  60. package/out/zero-cache/src/types/processes.d.ts +1 -0
  61. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  62. package/out/zero-cache/src/types/processes.js +5 -1
  63. package/out/zero-cache/src/types/processes.js.map +1 -1
  64. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  65. package/out/zero-cache/src/workers/replicator.js +9 -7
  66. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  67. package/out/zero-client/src/client/custom.d.ts +78 -0
  68. package/out/zero-client/src/client/custom.d.ts.map +1 -0
  69. package/out/zero-client/src/client/options.d.ts +4 -2
  70. package/out/zero-client/src/client/options.d.ts.map +1 -1
  71. package/out/zero-client/src/types/client-state.d.ts +8 -0
  72. package/out/zero-client/src/types/client-state.d.ts.map +1 -0
  73. package/out/zero.js +2 -2
  74. package/out/zql/src/ivm/change.d.ts +4 -4
  75. package/out/zql/src/ivm/change.d.ts.map +1 -1
  76. package/out/zql/src/ivm/change.js +1 -4
  77. package/out/zql/src/ivm/change.js.map +1 -1
  78. package/out/zql/src/ivm/data.d.ts +2 -1
  79. package/out/zql/src/ivm/data.d.ts.map +1 -1
  80. package/out/zql/src/ivm/data.js +7 -0
  81. package/out/zql/src/ivm/data.js.map +1 -1
  82. package/out/zql/src/ivm/exists.d.ts +3 -2
  83. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  84. package/out/zql/src/ivm/exists.js +55 -64
  85. package/out/zql/src/ivm/exists.js.map +1 -1
  86. package/out/zql/src/ivm/filter-push.js +1 -1
  87. package/out/zql/src/ivm/filter-push.js.map +1 -1
  88. package/out/zql/src/ivm/filter.d.ts +2 -3
  89. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  90. package/out/zql/src/ivm/filter.js +12 -7
  91. package/out/zql/src/ivm/filter.js.map +1 -1
  92. package/out/zql/src/ivm/join.d.ts +4 -1
  93. package/out/zql/src/ivm/join.d.ts.map +1 -1
  94. package/out/zql/src/ivm/join.js +32 -25
  95. package/out/zql/src/ivm/join.js.map +1 -1
  96. package/out/zql/src/ivm/skip.d.ts.map +1 -1
  97. package/out/zql/src/ivm/skip.js +1 -2
  98. package/out/zql/src/ivm/skip.js.map +1 -1
  99. package/out/zql/src/ivm/take.d.ts.map +1 -1
  100. package/out/zql/src/ivm/take.js +4 -3
  101. package/out/zql/src/ivm/take.js.map +1 -1
  102. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  103. package/out/zql/src/ivm/view-apply-change.js +4 -10
  104. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  105. package/out/zqlite/src/db.d.ts.map +1 -1
  106. package/out/zqlite/src/db.js +11 -1
  107. package/out/zqlite/src/db.js.map +1 -1
  108. package/out/zqlite/src/table-source.d.ts +3 -1
  109. package/out/zqlite/src/table-source.d.ts.map +1 -1
  110. package/out/zqlite/src/table-source.js +22 -6
  111. package/out/zqlite/src/table-source.js.map +1 -1
  112. package/package.json +2 -1
  113. package/out/chunk-QAAJZ32T.js.map +0 -7
@@ -1,94 +1,9 @@
1
1
  import 'dotenv/config'; // Imports ENV variables from .env
2
- import { assert } from "../../../../shared/src/asserts.js";
3
- import { exitAfter, ProcessManager, runUntilKilled, } from "../../services/life-cycle.js";
4
- import { childWorker, parentWorker, singleProcessMode, } from "../../types/processes.js";
5
- import { orTimeout } from "../../types/timeout.js";
6
- import { createLogContext } from "../logging.js";
7
- import { getMultiZeroConfig } from "./config.js";
8
- import { getTaskID } from "./runtime.js";
9
- import { TenantDispatcher } from "./tenant-dispatcher.js";
10
- export default async function runWorker(parent, env) {
11
- const startMs = Date.now();
12
- const { config, env: baseEnv } = getMultiZeroConfig(env);
13
- const lc = createLogContext(config, { worker: 'main' });
14
- const processes = new ProcessManager(lc, parent ?? process);
15
- const { port, changeStreamerPort = port + 1 } = config;
16
- let { taskID } = config;
17
- if (!taskID) {
18
- taskID = await getTaskID(lc);
19
- baseEnv['ZERO_TASK_ID'] = taskID;
20
- }
21
- lc.info?.(`starting task ${taskID}`);
22
- const multiMode = config.tenants.length;
23
- if (!multiMode) {
24
- // Run a single tenant on main `port`, and skip the TenantDispatcher.
25
- config.tenants.push({
26
- id: '',
27
- env: {
28
- ['ZERO_PORT']: String(port),
29
- ['ZERO_CVR_DB']: config.cvr.db,
30
- ['ZERO_CHANGE_DB']: config.change.db,
31
- ['ZERO_REPLICA_FILE']: config.replicaFile,
32
- },
33
- });
34
- }
35
- // In the multi-node configuration, determine if this process
36
- // should be dispatching sync requests (i.e. by `host` / `port`),
37
- // or change-streamer requests (i.e. by tenant `id`).
38
- const runAsReplicationManager = config.numSyncWorkers === 0;
39
- // Start the first tenant at (port + 2) unless explicitly
40
- // overridden by its own ZERO_PORT ...
41
- let tenantPort = port;
42
- const tenants = config.tenants.map(tenant => {
43
- const mergedEnv = {
44
- ...process.env, // propagate all ENV variables from this process
45
- ...baseEnv, // defaults
46
- ['ZERO_TENANT_ID']: tenant.id,
47
- ['ZERO_PORT']: String((tenantPort += 2)), // and bump the port by 2 thereafter.
48
- ...tenant.env, // overrides
49
- };
50
- if (runAsReplicationManager) {
51
- // Sanity-check. It doesn't make sense to run sync workers in the
52
- // replication-manager.
53
- assert(mergedEnv['ZERO_NUM_SYNC_WORKERS'] === '0', `Tenant ${tenant.id} cannot run sync workers in the replication-manager`);
54
- }
55
- const changeStreamerURI = mergedEnv['ZERO_CHANGE_STREAMER_URI'];
56
- if (changeStreamerURI && multiMode) {
57
- // Requests from the view-syncer to the replication-manager are
58
- // delineated/dispatched by the tenant ID as the first path component.
59
- mergedEnv['ZERO_CHANGE_STREAMER_URI'] += changeStreamerURI.endsWith('/')
60
- ? tenant.id
61
- : `/${tenant.id}`;
62
- }
63
- return { ...tenant, worker: childWorker('./server/main.ts', mergedEnv) };
64
- });
65
- for (const tenant of tenants) {
66
- processes.addWorker(tenant.worker, 'user-facing', tenant.id);
67
- }
68
- const s = tenants.length > 1 ? 's' : '';
69
- lc.info?.(`waiting for zero-cache${s} to be ready ...`);
70
- if ((await orTimeout(processes.allWorkersReady(), 60_000)) === 'timed-out') {
71
- lc.info?.(`timed out waiting for readiness (${Date.now() - startMs} ms)`);
72
- }
73
- else {
74
- lc.info?.(`zero-cache${s} ready (${Date.now() - startMs} ms)`);
75
- }
76
- const mainServices = [];
77
- if (multiMode) {
78
- mainServices.push(new TenantDispatcher(lc, runAsReplicationManager, tenants, {
79
- port: runAsReplicationManager ? changeStreamerPort : port,
80
- }));
81
- }
82
- parent?.send(['ready', { ready: true }]);
83
- try {
84
- await runUntilKilled(lc, parent ?? process, ...mainServices);
85
- }
86
- catch (err) {
87
- processes.logErrorAndExit(err, 'main');
88
- }
89
- await processes.done();
90
- }
2
+ import { exitAfter } from "../../services/life-cycle.js";
3
+ import { parentWorker, singleProcessMode } from "../../types/processes.js";
4
+ import { runWorker } from "./run-worker.js";
91
5
  if (!singleProcessMode()) {
92
6
  void exitAfter(() => runWorker(parentWorker, process.env));
93
7
  }
8
+ export default runWorker;
94
9
  //# sourceMappingURL=main.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../../../../../../zero-cache/src/server/multi/main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../../../../../zero-cache/src/server/multi/main.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC,CAAC,kCAAkC;AAC1D,OAAO,EAAC,SAAS,EAAC,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAC,YAAY,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAE1C,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;IACzB,KAAK,SAAS,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,eAAe,SAAS,CAAC"}
@@ -0,0 +1,4 @@
1
+ import 'dotenv/config';
2
+ import { type Worker } from '../../types/processes.ts';
3
+ export declare function runWorker(parent: Worker | null, env: NodeJS.ProcessEnv): Promise<void>;
4
+ //# sourceMappingURL=run-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-worker.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/server/multi/run-worker.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAIvB,OAAO,EAAc,KAAK,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAOlE,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,IAAI,CAAC,CA+Ff"}
@@ -0,0 +1,91 @@
1
+ import 'dotenv/config'; // Imports ENV variables from .env
2
+ import { assert } from "../../../../shared/src/asserts.js";
3
+ import { ProcessManager, runUntilKilled } from "../../services/life-cycle.js";
4
+ import { childWorker } from "../../types/processes.js";
5
+ import { orTimeout } from "../../types/timeout.js";
6
+ import { createLogContext } from "../logging.js";
7
+ import { getMultiZeroConfig } from "./config.js";
8
+ import { getTaskID } from "./runtime.js";
9
+ import { TenantDispatcher } from "./tenant-dispatcher.js";
10
+ export async function runWorker(parent, env) {
11
+ const startMs = Date.now();
12
+ const { config, env: baseEnv } = getMultiZeroConfig(env);
13
+ const lc = createLogContext(config, { worker: 'main' });
14
+ const processes = new ProcessManager(lc, parent ?? process);
15
+ const { port, changeStreamerPort = port + 1 } = config;
16
+ let { taskID } = config;
17
+ if (!taskID) {
18
+ taskID = await getTaskID(lc);
19
+ baseEnv['ZERO_TASK_ID'] = taskID;
20
+ }
21
+ lc.info?.(`starting task ${taskID}`);
22
+ const multiMode = config.tenants.length;
23
+ if (!multiMode) {
24
+ // Run a single tenant on main `port`, and skip the TenantDispatcher.
25
+ config.tenants.push({
26
+ id: '',
27
+ env: {
28
+ ['ZERO_PORT']: String(port),
29
+ ['ZERO_CVR_DB']: config.cvr.db,
30
+ ['ZERO_CHANGE_DB']: config.change.db,
31
+ ['ZERO_REPLICA_FILE']: config.replicaFile,
32
+ },
33
+ });
34
+ }
35
+ // In the multi-node configuration, determine if this process
36
+ // should be dispatching sync requests (i.e. by `host` / `port`),
37
+ // or change-streamer requests (i.e. by tenant `id`).
38
+ const runAsReplicationManager = config.numSyncWorkers === 0;
39
+ // Start the first tenant at (port + 2) unless explicitly
40
+ // overridden by its own ZERO_PORT ...
41
+ let tenantPort = port;
42
+ const tenants = config.tenants.map(tenant => {
43
+ const mergedEnv = {
44
+ ...process.env, // propagate all ENV variables from this process
45
+ ...baseEnv, // defaults
46
+ ['ZERO_TENANT_ID']: tenant.id,
47
+ ['ZERO_PORT']: String((tenantPort += 2)), // and bump the port by 2 thereafter.
48
+ ...tenant.env, // overrides
49
+ };
50
+ if (runAsReplicationManager) {
51
+ // Sanity-check. It doesn't make sense to run sync workers in the
52
+ // replication-manager.
53
+ assert(mergedEnv['ZERO_NUM_SYNC_WORKERS'] === '0', `Tenant ${tenant.id} cannot run sync workers in the replication-manager`);
54
+ }
55
+ const changeStreamerURI = mergedEnv['ZERO_CHANGE_STREAMER_URI'];
56
+ if (changeStreamerURI && multiMode) {
57
+ // Requests from the view-syncer to the replication-manager are
58
+ // delineated/dispatched by the tenant ID as the first path component.
59
+ mergedEnv['ZERO_CHANGE_STREAMER_URI'] += changeStreamerURI.endsWith('/')
60
+ ? tenant.id
61
+ : `/${tenant.id}`;
62
+ }
63
+ return { ...tenant, worker: childWorker('./server/main.ts', mergedEnv) };
64
+ });
65
+ for (const tenant of tenants) {
66
+ processes.addWorker(tenant.worker, 'user-facing', tenant.id);
67
+ }
68
+ const s = tenants.length > 1 ? 's' : '';
69
+ lc.info?.(`waiting for zero-cache${s} to be ready ...`);
70
+ if ((await orTimeout(processes.allWorkersReady(), 60_000)) === 'timed-out') {
71
+ lc.info?.(`timed out waiting for readiness (${Date.now() - startMs} ms)`);
72
+ }
73
+ else {
74
+ lc.info?.(`zero-cache${s} ready (${Date.now() - startMs} ms)`);
75
+ }
76
+ const mainServices = [];
77
+ if (multiMode) {
78
+ mainServices.push(new TenantDispatcher(lc, runAsReplicationManager, tenants, {
79
+ port: runAsReplicationManager ? changeStreamerPort : port,
80
+ }));
81
+ }
82
+ parent?.send(['ready', { ready: true }]);
83
+ try {
84
+ await runUntilKilled(lc, parent ?? process, ...mainServices);
85
+ }
86
+ catch (err) {
87
+ processes.logErrorAndExit(err, 'main');
88
+ }
89
+ await processes.done();
90
+ }
91
+ //# sourceMappingURL=run-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-worker.js","sourceRoot":"","sources":["../../../../../../zero-cache/src/server/multi/run-worker.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"syncer.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/server/syncer.ts"],"names":[],"mappings":"AA2BA,OAAO,EAGL,KAAK,MAAM,EACZ,MAAM,uBAAuB,CAAC;AAU/B,wBAA8B,SAAS,CACrC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,GAAG,IAAI,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,IAAI,CAAC,CA6Gf"}
1
+ {"version":3,"file":"syncer.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/server/syncer.ts"],"names":[],"mappings":"AA2BA,OAAO,EAGL,KAAK,MAAM,EACZ,MAAM,uBAAuB,CAAC;AAU/B,wBAA8B,SAAS,CACrC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,GAAG,IAAI,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,IAAI,CAAC,CA8Gf"}
@@ -77,7 +77,7 @@ export default async function runWorker(parent, env, ...args) {
77
77
  .withContext('component', 'view-syncer')
78
78
  .withContext('clientGroupID', id)
79
79
  .withContext('instance', randomID());
80
- return new ViewSyncerService(logger, must(config.taskID, 'main must set --task-id'), id, config.shard.id, cvrDB, new PipelineDriver(logger, new Snapshotter(logger, replicaFile), operatorStorage.createClientGroupStorage(id), id), sub, drainCoordinator, permissions);
80
+ return new ViewSyncerService(logger, must(config.taskID, 'main must set --task-id'), id, config.shard.id, cvrDB, new PipelineDriver(logger, config.log, new Snapshotter(logger, replicaFile), operatorStorage.createClientGroupStorage(id), id), sub, drainCoordinator, permissions);
81
81
  };
82
82
  const mutagenFactory = (id) => new MutagenService(lc.withContext('component', 'mutagen').withContext('clientGroupID', id), config.shard.id, id, upstreamDB, config, schema, permissions);
83
83
  const syncer = new Syncer(lc, config, viewSyncerFactory, mutagenFactory, parent);
@@ -1 +1 @@
1
- {"version":3,"file":"syncer.js","sourceRoot":"","sources":["../../../../../zero-cache/src/server/syncer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"syncer.js","sourceRoot":"","sources":["../../../../../zero-cache/src/server/syncer.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/pg/change-source.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EACL,yBAAyB,EAG1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAEV,eAAe,EAChB,MAAM,uEAAuE,CAAC;AAc/E,OAAO,KAAK,EAEV,kBAAkB,EAEnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAW,KAAK,WAAW,EAAC,MAAM,gCAAgC,CAAC;AAO1E,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,kDAAkD,CAAC;AAC1D,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,wCAAwC,CAAC;AAYhD,OAAO,EAAkB,KAAK,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AAI3E,OAAO,EAAqB,KAAK,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAQ/E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAMnD;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,kBAAkB,GAC9B,OAAO,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAC,CAAC,CA4C7E;AA+ND,qBAAa,KAAK;;gBAIJ,OAAO,EAAE,yBAAyB;IAI9C,SAAS;IAiBT,GAAG,CAAC,SAAS,EAAE,WAAW;CAa3B;AAoZD,wBAAgB,gBAAgB,CAC9B,CAAC,EAAE,eAAe,EAClB,CAAC,EAAE,eAAe,EAClB,EAAE,CAAC,EAAE,UAAU,WAchB;AAMD,wBAAgB,eAAe,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,kBAAkB,WAsB3E;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,eAAe,WAkB1E;AAwBD,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,IAAI,kCAAkC;;CAOhD"}
1
+ {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/pg/change-source.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EACL,yBAAyB,EAG1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAEV,eAAe,EAChB,MAAM,uEAAuE,CAAC;AAc/E,OAAO,KAAK,EAEV,kBAAkB,EAEnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAW,KAAK,WAAW,EAAC,MAAM,gCAAgC,CAAC;AAO1E,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,kDAAkD,CAAC;AAC1D,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,wCAAwC,CAAC;AAYhD,OAAO,EAAkB,KAAK,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AAI3E,OAAO,EAAqB,KAAK,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAQ/E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAMnD;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,kBAAkB,GAC9B,OAAO,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAC,CAAC,CA4C7E;AAmOD,qBAAa,KAAK;;gBAIJ,OAAO,EAAE,yBAAyB;IAI9C,SAAS;IAiBT,GAAG,CAAC,SAAS,EAAE,WAAW;CAa3B;AAkWD,wBAAgB,gBAAgB,CAC9B,CAAC,EAAE,eAAe,EAClB,CAAC,EAAE,eAAe,EAClB,EAAE,CAAC,EAAE,UAAU,WAchB;AAMD,wBAAgB,eAAe,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,kBAAkB,WAuB3E;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,eAAe,WAkB1E;AAoCD,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,IAAI,kCAAkC;;CAOhD"}
@@ -98,11 +98,10 @@ class PostgresChangeSource {
98
98
  async startStream(clientWatermark) {
99
99
  const db = pgClient(this.#lc, this.#upstreamUri);
100
100
  const slot = replicationSlot(this.#shardID);
101
- const clientStart = oneAfter(clientWatermark);
102
101
  try {
103
102
  await this.#stopExistingReplicationSlotSubscriber(db, slot);
104
103
  const config = await getInternalShardConfig(db, this.#shardID);
105
- this.#lc.info?.(`starting replication stream @${slot}`);
104
+ this.#lc.info?.(`starting replication stream@${slot}`);
106
105
  // Enabling ssl according to the logic in:
107
106
  // https://github.com/brianc/node-postgres/blob/95d7e620ef8b51743b4cbca05dd3c3ce858ecea7/packages/pg-connection-string/index.js#L90
108
107
  const url = new URL(this.#upstreamUri);
@@ -114,7 +113,7 @@ class PostgresChangeSource {
114
113
  // Unlike the postgres.js client, the pg client does not have an option to
115
114
  // only use SSL if the server supports it. We achieve it manually by
116
115
  // trying SSL first, and then falling back to connecting without SSL.
117
- return await this.#startStream(slot, clientStart, config, useSSL);
116
+ return await this.#startStream(slot, clientWatermark, config, useSSL);
118
117
  }
119
118
  catch (e) {
120
119
  if (e instanceof SSLUnsupportedError) {
@@ -144,7 +143,7 @@ class PostgresChangeSource {
144
143
  await db.end();
145
144
  }
146
145
  }
147
- async #startStream(slot, clientStart, shardConfig, useSSL) {
146
+ async #startStream(slot, clientWatermark, shardConfig, useSSL) {
148
147
  const changes = Subscription.create({
149
148
  cleanup: () => service.stop(),
150
149
  });
@@ -200,6 +199,7 @@ class PostgresChangeSource {
200
199
  }))
201
200
  .on('error', handleError);
202
201
  acker = new Acker(service);
202
+ const clientStart = oneAfter(clientWatermark);
203
203
  service
204
204
  .subscribe(new PgoutputPlugin({
205
205
  protoVersion: 1,
@@ -208,7 +208,8 @@ class PostgresChangeSource {
208
208
  }), slot, fromLexiVersion(clientStart))
209
209
  .then(() => changes.cancel(), handleError);
210
210
  await started;
211
- this.#lc.info?.(`started replication stream@${slot}`);
211
+ const { replicaVersion } = this.#replicationConfig;
212
+ this.#lc.info?.(`started replication stream@${slot} from ${clientWatermark} (replicaVersion: ${replicaVersion})`);
212
213
  return {
213
214
  changes,
214
215
  acks: { push: status => acker.ack(status[2].watermark) },
@@ -320,9 +321,13 @@ class ChangeMaker {
320
321
  return [
321
322
  ['begin', msg, { commitWatermark: toLexiVersion(must(msg.commitLsn)) }],
322
323
  ];
323
- case 'delete':
324
- assert(msg.key);
325
- return [['data', msg]];
324
+ case 'delete': {
325
+ const key = msg.key ?? msg.old;
326
+ if (!key) {
327
+ throw new Error(`Invalid DELETE msg (missing key): ${stringify(msg)}`);
328
+ }
329
+ return [['data', msg.key ? msg : { ...msg, key }]];
330
+ }
326
331
  case 'insert':
327
332
  case 'update':
328
333
  case 'truncate':
@@ -386,10 +391,18 @@ class ChangeMaker {
386
391
  * but SQLite will error instead (https://sqlite.org/forum/forumpost/2e62dba69f?t=c&hist).
387
392
  * The current workaround is to drop indexes first.
388
393
  *
389
- * More generally, the order of replicating DDL updates is:
394
+ * Also note that although it should not be possible to both rename and
395
+ * add/drop tables/columns in a single statement, the operations are
396
+ * ordered to handle that possibility, by always dropping old entities,
397
+ * then modifying kept entities, and then adding new entities.
398
+ *
399
+ * Thus, the order of replicating DDL updates is:
390
400
  * - drop indexes
391
- * - alter tables
392
401
  * - drop tables
402
+ * - alter tables
403
+ * - drop columns
404
+ * - alter columns
405
+ * - add columns
393
406
  * - create tables
394
407
  * - create indexes
395
408
  *
@@ -399,137 +412,87 @@ class ChangeMaker {
399
412
  * the type of a column that's indexed.
400
413
  */
401
414
  #makeSchemaChanges(preSchema, update) {
402
- const [prevTables, prevIndexes] = specsByName(preSchema);
403
- const [nextTables, nextIndexes] = specsByName(update.schema);
404
- const { tag } = update.event;
415
+ const [prevTbl, prevIdx] = specsByID(preSchema);
416
+ const [nextTbl, nextIdx] = specsByID(update.schema);
405
417
  const changes = [];
406
418
  // Validate the new table schemas
407
- for (const table of nextTables.values()) {
419
+ for (const table of nextTbl.values()) {
408
420
  validate(this.#lc, this.#shardID, table);
409
421
  }
410
- const [dropped, created] = symmetricDifferences(prevIndexes, nextIndexes);
411
- // Drop indexes first so that allow dropping dependent objects.
412
- for (const id of dropped) {
413
- const { schema, name } = must(prevIndexes.get(id));
422
+ const [droppedIdx, createdIdx] = symmetricDifferences(prevIdx, nextIdx);
423
+ for (const id of droppedIdx) {
424
+ const { schema, name } = must(prevIdx.get(id));
414
425
  changes.push({ tag: 'drop-index', id: { schema, name } });
415
426
  }
416
- if (tag === 'ALTER PUBLICATION') {
417
- const tables = intersection(prevTables, nextTables);
418
- for (const id of tables) {
419
- changes.push(...this.#getAddedOrDroppedColumnChanges(must(prevTables.get(id)), must(nextTables.get(id))));
420
- }
427
+ // DROP
428
+ const [droppedTbl, createdTbl] = symmetricDifferences(prevTbl, nextTbl);
429
+ for (const id of droppedTbl) {
430
+ const { schema, name } = must(prevTbl.get(id));
431
+ changes.push({ tag: 'drop-table', id: { schema, name } });
421
432
  }
422
- else if (tag === 'ALTER TABLE') {
423
- const altered = idString(update.event.table);
424
- const table = must(nextTables.get(altered));
425
- const prevTable = prevTables.get(altered);
426
- if (!prevTable) {
427
- // table rename. Find the old name.
428
- let old;
429
- for (const [id, { schema, name }] of prevTables.entries()) {
430
- if (!nextTables.has(id)) {
431
- old = { schema, name };
432
- break;
433
- }
434
- }
435
- if (!old) {
436
- throw new Error(`can't find previous table: ${stringify(update)}`);
437
- }
438
- changes.push({ tag: 'rename-table', old, new: table });
439
- }
440
- else {
441
- changes.push(...this.#getSingleColumnChange(prevTable, table));
442
- }
433
+ // ALTER
434
+ const tables = intersection(prevTbl, nextTbl);
435
+ for (const id of tables) {
436
+ changes.push(...this.#getTableChanges(must(prevTbl.get(id)), must(nextTbl.get(id))));
443
437
  }
444
- // Added/dropped tables are handled in the same way for most DDL updates, with
445
- // the exception being `ALTER TABLE`, for which a table rename should not be
446
- // confused as a drop + add.
447
- if (tag !== 'ALTER TABLE') {
448
- const [dropped, created] = symmetricDifferences(prevTables, nextTables);
449
- for (const id of dropped) {
450
- const { schema, name } = must(prevTables.get(id));
451
- changes.push({ tag: 'drop-table', id: { schema, name } });
452
- }
453
- for (const id of created) {
454
- const spec = must(nextTables.get(id));
455
- changes.push({ tag: 'create-table', spec });
456
- }
438
+ // CREATE
439
+ for (const id of createdTbl) {
440
+ const spec = must(nextTbl.get(id));
441
+ changes.push({ tag: 'create-table', spec });
457
442
  }
458
443
  // Add indexes last since they may reference tables / columns that need
459
444
  // to be created first.
460
- for (const id of created) {
461
- const spec = must(nextIndexes.get(id));
445
+ for (const id of createdIdx) {
446
+ const spec = must(nextIdx.get(id));
462
447
  changes.push({ tag: 'create-index', spec });
463
448
  }
464
449
  return changes;
465
450
  }
466
- // ALTER PUBLICATION can only add and drop columns, but never change them.
467
- #getAddedOrDroppedColumnChanges(oldTable, newTable) {
468
- const table = { schema: newTable.schema, name: newTable.name };
469
- const [dropped, added] = symmetricDifferences(new Set(Object.keys(oldTable.columns)), new Set(Object.keys(newTable.columns)));
451
+ #getTableChanges(oldTable, newTable) {
470
452
  const changes = [];
471
- for (const column of dropped) {
472
- changes.push({ tag: 'drop-column', table, column });
473
- }
474
- for (const name of added) {
453
+ if (oldTable.schema !== newTable.schema ||
454
+ oldTable.name !== newTable.name) {
475
455
  changes.push({
476
- tag: 'add-column',
477
- table,
478
- column: { name, spec: newTable.columns[name] },
456
+ tag: 'rename-table',
457
+ old: { schema: oldTable.schema, name: oldTable.name },
458
+ new: { schema: newTable.schema, name: newTable.name },
479
459
  });
480
460
  }
481
- return changes;
482
- }
483
- // ALTER TABLE can add, drop, or change/rename a single column.
484
- #getSingleColumnChange(oldTable, newTable) {
485
461
  const table = { schema: newTable.schema, name: newTable.name };
486
- const [d, a] = symmetricDifferences(new Set(Object.keys(oldTable.columns)), new Set(Object.keys(newTable.columns)));
487
- const dropped = [...d];
488
- const added = [...a];
489
- assert(dropped.length <= 1 && added.length <= 1, `too many dropped [${[dropped]}] or added [${[added]}] columns`);
490
- if (dropped.length === 1 && added.length === 1) {
491
- const oldName = dropped[0];
492
- const newName = added[0];
493
- return [
494
- {
495
- tag: 'update-column',
496
- table,
497
- old: { name: oldName, spec: oldTable.columns[oldName] },
498
- new: { name: newName, spec: newTable.columns[newName] },
499
- },
500
- ];
501
- }
502
- else if (added.length) {
503
- const name = added[0];
504
- return [
505
- {
506
- tag: 'add-column',
507
- table,
508
- column: { name, spec: newTable.columns[name] },
509
- },
510
- ];
511
- }
512
- else if (dropped.length) {
513
- return [{ tag: 'drop-column', table, column: dropped[0] }];
462
+ const oldColumns = columnsByID(oldTable.columns);
463
+ const newColumns = columnsByID(newTable.columns);
464
+ // DROP
465
+ const [dropped, added] = symmetricDifferences(oldColumns, newColumns);
466
+ for (const id of dropped) {
467
+ const { name: column } = must(oldColumns.get(id));
468
+ changes.push({ tag: 'drop-column', table, column });
514
469
  }
515
- // Not a rename, add, or drop. Find the column with a relevant update.
516
- for (const [name, oldSpec] of Object.entries(oldTable.columns)) {
517
- const newSpec = newTable.columns[name];
518
- // Besides the name, we only care about the data type and not null.
519
- // Default values and other constraints are not relevant.
520
- if (oldSpec.dataType !== newSpec.dataType ||
470
+ // ALTER
471
+ const both = intersection(oldColumns, newColumns);
472
+ for (const id of both) {
473
+ const { name: oldName, ...oldSpec } = must(oldColumns.get(id));
474
+ const { name: newName, ...newSpec } = must(newColumns.get(id));
475
+ // The three things that we care about are:
476
+ // 1. name
477
+ // 2. type
478
+ // 3. not-null
479
+ if (oldName !== newName ||
480
+ oldSpec.dataType !== newSpec.dataType ||
521
481
  oldSpec.notNull !== newSpec.notNull) {
522
- return [
523
- {
524
- tag: 'update-column',
525
- table,
526
- old: { name, spec: oldSpec },
527
- new: { name, spec: newSpec },
528
- },
529
- ];
482
+ changes.push({
483
+ tag: 'update-column',
484
+ table,
485
+ old: { name: oldName, spec: oldSpec },
486
+ new: { name: newName, spec: newSpec },
487
+ });
530
488
  }
531
489
  }
532
- return [];
490
+ // ADD
491
+ for (const id of added) {
492
+ const { name, ...spec } = must(newColumns.get(id));
493
+ changes.push({ tag: 'add-column', table, column: { name, spec } });
494
+ }
495
+ return changes;
533
496
  }
534
497
  #parseReplicationEvent(content) {
535
498
  const str = content instanceof Buffer
@@ -611,7 +574,8 @@ export function tablesDifferent(a, b) {
611
574
  const [bname, bcol] = bcols[i];
612
575
  return (aname !== bname ||
613
576
  acol.pos !== bcol.pos ||
614
- acol.typeOID !== bcol.typeOID);
577
+ acol.typeOID !== bcol.typeOID ||
578
+ acol.notNull !== bcol.notNull);
615
579
  }));
616
580
  }
617
581
  export function relationDifferent(a, b) {
@@ -639,14 +603,23 @@ function translateError(e) {
639
603
  return e;
640
604
  }
641
605
  const idString = (id) => `${id.schema}.${id.name}`;
642
- function specsByName(published) {
606
+ function specsByID(published) {
643
607
  return [
644
608
  // It would have been nice to use a CustomKeyMap here, but we rely on set-utils
645
609
  // operations which use plain Sets.
646
- new Map(published.tables.map(t => [idString(t), t])),
610
+ new Map(published.tables.map(t => [t.oid, t])),
647
611
  new Map(published.indexes.map(i => [idString(i), i])),
648
612
  ];
649
613
  }
614
+ function columnsByID(columns) {
615
+ const colsByID = new Map();
616
+ for (const [name, spec] of Object.entries(columns)) {
617
+ // The `pos` field is the `attnum` in `pg_attribute`, which is a stable
618
+ // identifier for the column in this table (i.e. never reused).
619
+ colsByID.set(spec.pos, { ...spec, name });
620
+ }
621
+ return colsByID;
622
+ }
650
623
  class SSLUnsupportedError extends Error {
651
624
  }
652
625
  export class UnsupportedSchemaChangeError extends Error {