@rocicorp/zero 0.25.9 → 0.25.10-canary.1

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.
@@ -1,4 +1,4 @@
1
- const version = "0.25.9";
1
+ const version = "0.25.10-canary.1";
2
2
  const packageJson = {
3
3
  version
4
4
  };
@@ -17,6 +17,7 @@ export type ChangeLogEntry = {
17
17
  export type ReplicationState = {
18
18
  lastWatermark: string;
19
19
  owner: string | null;
20
+ ownerAddress: string | null;
20
21
  };
21
22
  export declare function createReplicationStateTable(shard: ShardID): string;
22
23
  export declare function discoverChangeStreamerAddress(shard: ShardID, sql: PostgresDB): Promise<string | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-streamer/schema/tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAErC,OAAO,EAAC,UAAU,EAAC,MAAM,0CAA0C,CAAC;AAEpE,OAAO,EAA0B,KAAK,UAAU,EAAC,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAY,KAAK,OAAO,EAAC,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,8CAA8C,CAAC;AACzE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,8CAA8C,CAAC;AAOpF,eAAO,MAAM,SAAS,QAAQ,CAAC;AAM/B,MAAM,MAAM,cAAc,GAAG;IAG3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAiBF;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,UASzD;AAED,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB;AAED;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC,CAAC;AAsBF,wBAAsB,cAAc,CAClC,EAAE,EAAE,UAAU,EACd,EAAE,EAAE,QAAQ,CAAC,cAAc,EAC3B,KAAK,EAAE,OAAO,iBAIf;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,iBAKtE;AAED,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,UAAU,EACd,EAAE,EAAE,UAAU,EACd,iBAAiB,EAAE,iBAAiB,EACpC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,OAAO,iBAyEnB;AAED,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,QAAQ,CAAC,IAAI,qBAAqB;CACnC"}
1
+ {"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-streamer/schema/tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAErC,OAAO,EAAC,UAAU,EAAC,MAAM,0CAA0C,CAAC;AAEpE,OAAO,EAA0B,KAAK,UAAU,EAAC,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAY,KAAK,OAAO,EAAC,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,8CAA8C,CAAC;AACzE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,8CAA8C,CAAC;AAOpF,eAAO,MAAM,SAAS,QAAQ,CAAC;AAM/B,MAAM,MAAM,cAAc,GAAG;IAG3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAiBF;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,UASzD;AAED,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB;AAED;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC,CAAC;AAsBF,wBAAsB,cAAc,CAClC,EAAE,EAAE,UAAU,EACd,EAAE,EAAE,QAAQ,CAAC,cAAc,EAC3B,KAAK,EAAE,OAAO,iBAIf;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,iBAKtE;AAED,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,UAAU,EACd,EAAE,EAAE,UAAU,EACd,iBAAiB,EAAE,iBAAiB,EACpC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,OAAO,iBAiFnB;AAED,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,QAAQ,CAAC,IAAI,qBAAqB;CACnC"}
@@ -75,7 +75,9 @@ async function ensureReplicationConfig(lc, db, subscriptionState, shard, autoRes
75
75
  const { publications, replicaVersion, watermark } = subscriptionState;
76
76
  const replicaConfig = { publications, replicaVersion };
77
77
  const replicationState = {
78
- lastWatermark: replicaVersion
78
+ lastWatermark: replicaVersion,
79
+ owner: null,
80
+ ownerAddress: null
79
81
  };
80
82
  const schema2 = cdcSchema(shard);
81
83
  await db.begin(async (sql) => {
@@ -97,16 +99,15 @@ async function ensureReplicationConfig(lc, db, subscriptionState, shard, autoRes
97
99
  );
98
100
  stmts.push(
99
101
  sql`TRUNCATE TABLE ${sql(schema2)}."changeLog"`,
100
- sql`TRUNCATE TABLE ${sql(schema2)}."replicationConfig"`,
101
- sql`TRUNCATE TABLE ${sql(schema2)}."replicationState"`
102
+ sql`TRUNCATE TABLE ${sql(schema2)}."replicationConfig"`
102
103
  );
103
104
  }
104
105
  }
105
106
  if (results.length === 0 || stmts.length > 0) {
106
107
  stmts.push(
107
108
  sql`INSERT INTO ${sql(schema2)}."replicationConfig" ${sql(replicaConfig)}`,
108
- sql`INSERT INTO ${sql(schema2)}."replicationState"
109
- ${sql(replicationState)}`
109
+ sql`INSERT INTO ${sql(schema2)}."replicationState" ${sql(replicationState)}
110
+ ON CONFLICT (lock) DO UPDATE SET ${sql(replicationState)}`
110
111
  );
111
112
  return Promise.all(stmts);
112
113
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tables.js","sources":["../../../../../../../zero-cache/src/services/change-streamer/schema/tables.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {ident} from 'pg-format';\nimport type postgres from 'postgres';\nimport {type PendingQuery, type Row} from 'postgres';\nimport {AbortError} from '../../../../../shared/src/abort-error.ts';\nimport {equals} from '../../../../../shared/src/set-utils.ts';\nimport {disableStatementTimeout, type PostgresDB} from '../../../types/pg.ts';\nimport {cdcSchema, type ShardID} from '../../../types/shards.ts';\nimport type {Change} from '../../change-source/protocol/current/data.ts';\nimport type {SubscriptionState} from '../../replicator/schema/replication-state.ts';\n\n// For readability in the sql statements.\nfunction schema(shard: ShardID) {\n return ident(cdcSchema(shard));\n}\n\nexport const PG_SCHEMA = 'cdc';\n\nfunction createSchema(shard: ShardID) {\n return /*sql*/ `CREATE SCHEMA IF NOT EXISTS ${schema(shard)};`;\n}\n\nexport type ChangeLogEntry = {\n // A strictly monotonically increasing, lexicographically sortable\n // value that uniquely identifies a position in the change stream.\n watermark: string;\n change: Change;\n};\n\nfunction createChangeLogTable(shard: ShardID) {\n // Note: The \"change\" column used to be JSONB, but that was problematic in that\n // it does not handle the NULL unicode character.\n // https://vladimir.varank.in/notes/2021/01/you-dont-insert-unicode-null-character-as-postgres-jsonb/\n return /*sql*/ `\n CREATE TABLE ${schema(shard)}.\"changeLog\" (\n watermark TEXT,\n pos INT8,\n change JSON NOT NULL,\n precommit TEXT, -- Only exists on commit entries. Purely for debugging.\n PRIMARY KEY (watermark, pos)\n );\n`;\n}\n\n/**\n * Tracks the watermark from which to resume the change stream and the\n * current owner (task ID) acting as the single writer to the changeLog.\n */\nexport type ReplicationState = {\n lastWatermark: string;\n owner: string | null;\n};\n\nexport function createReplicationStateTable(shard: ShardID) {\n return /*sql*/ `\n CREATE TABLE ${schema(shard)}.\"replicationState\" (\n \"lastWatermark\" TEXT NOT NULL,\n \"owner\" TEXT,\n \"ownerAddress\" TEXT,\n \"lock\" INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n`;\n}\n\nexport async function discoverChangeStreamerAddress(\n shard: ShardID,\n sql: PostgresDB,\n): Promise<string | null> {\n const result = await sql<{ownerAddress: string | null}[]> /*sql*/ `\n SELECT \"ownerAddress\" FROM ${sql(cdcSchema(shard))}.\"replicationState\"`;\n return result[0].ownerAddress;\n}\n\n/**\n * This mirrors the analogously named table in the SQLite replica\n * (`services/replicator/schema/replication-state.ts`), and is used\n * to detect when the replica has been reset and is no longer compatible\n * with the current ChangeLog.\n */\nexport type ReplicationConfig = {\n replicaVersion: string;\n publications: readonly string[];\n};\n\nfunction createReplicationConfigTable(shard: ShardID) {\n return /*sql*/ `\n CREATE TABLE ${schema(shard)}.\"replicationConfig\" (\n \"replicaVersion\" TEXT NOT NULL,\n \"publications\" TEXT[] NOT NULL,\n \"resetRequired\" BOOL,\n \"lock\" INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n`;\n}\n\nfunction createTables(shard: ShardID) {\n return (\n createSchema(shard) +\n createChangeLogTable(shard) +\n createReplicationStateTable(shard) +\n createReplicationConfigTable(shard)\n );\n}\n\nexport async function setupCDCTables(\n lc: LogContext,\n db: postgres.TransactionSql,\n shard: ShardID,\n) {\n lc.info?.(`Setting up CDC tables`);\n await db.unsafe(createTables(shard));\n}\n\nexport async function markResetRequired(sql: PostgresDB, shard: ShardID) {\n const schema = cdcSchema(shard);\n await sql`\n UPDATE ${sql(schema)}.\"replicationConfig\"\n SET \"resetRequired\" = true`;\n}\n\nexport async function ensureReplicationConfig(\n lc: LogContext,\n db: PostgresDB,\n subscriptionState: SubscriptionState,\n shard: ShardID,\n autoReset: boolean,\n) {\n const {publications, replicaVersion, watermark} = subscriptionState;\n const replicaConfig = {publications, replicaVersion};\n const replicationState: Partial<ReplicationState> = {\n lastWatermark: replicaVersion,\n };\n const schema = cdcSchema(shard);\n\n await db.begin(async sql => {\n disableStatementTimeout(sql);\n\n const stmts: PendingQuery<Row[]>[] = [];\n const results = await sql<\n {\n replicaVersion: string;\n publications: string[];\n resetRequired: boolean | null;\n }[]\n > /*sql*/ `\n SELECT \"replicaVersion\", \"publications\", \"resetRequired\" \n FROM ${sql(schema)}.\"replicationConfig\"`;\n\n if (results.length) {\n const {replicaVersion, publications} = results[0];\n if (\n replicaVersion !== replicaConfig.replicaVersion ||\n !equals(new Set(publications), new Set(replicaConfig.publications))\n ) {\n if (replicaConfig.replicaVersion !== watermark) {\n throw new AutoResetSignal(\n `Cannot reset change db@${replicaVersion} to ` +\n `service replica@${replicaConfig.replicaVersion} ` +\n `from watermark ${watermark}`,\n );\n }\n lc.info?.(\n `Data in cdc tables @${replicaVersion} is incompatible ` +\n `with replica @${replicaConfig.replicaVersion}. Clearing tables.`,\n );\n stmts.push(\n sql`TRUNCATE TABLE ${sql(schema)}.\"changeLog\"`,\n sql`TRUNCATE TABLE ${sql(schema)}.\"replicationConfig\"`,\n sql`TRUNCATE TABLE ${sql(schema)}.\"replicationState\"`,\n );\n }\n }\n // Initialize (or re-initialize TRUNCATED) tables\n if (results.length === 0 || stmts.length > 0) {\n stmts.push(\n sql`INSERT INTO ${sql(schema)}.\"replicationConfig\" ${sql(replicaConfig)}`,\n sql`INSERT INTO ${sql(schema)}.\"replicationState\" \n ${sql(replicationState)}`,\n );\n return Promise.all(stmts);\n }\n\n const {resetRequired} = results[0];\n if (resetRequired) {\n if (autoReset) {\n throw new AutoResetSignal('reset required by replication stream');\n }\n lc.error?.(\n '\\n\\n\\n' +\n 'Reset required but --auto-reset is not enabled.\\n' +\n 'This can happen for upstream databases that do not support event triggers.\\n' +\n 'To correct this, see https://zero.rocicorp.dev/docs/connecting-to-postgres#schema-changes' +\n '\\n\\n\\n',\n );\n }\n\n return [];\n });\n}\n\nexport class AutoResetSignal extends AbortError {\n readonly name = 'AutoResetSignal';\n}\n"],"names":["schema","replicaVersion","publications"],"mappings":"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"}
1
+ {"version":3,"file":"tables.js","sources":["../../../../../../../zero-cache/src/services/change-streamer/schema/tables.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {ident} from 'pg-format';\nimport type postgres from 'postgres';\nimport {type PendingQuery, type Row} from 'postgres';\nimport {AbortError} from '../../../../../shared/src/abort-error.ts';\nimport {equals} from '../../../../../shared/src/set-utils.ts';\nimport {disableStatementTimeout, type PostgresDB} from '../../../types/pg.ts';\nimport {cdcSchema, type ShardID} from '../../../types/shards.ts';\nimport type {Change} from '../../change-source/protocol/current/data.ts';\nimport type {SubscriptionState} from '../../replicator/schema/replication-state.ts';\n\n// For readability in the sql statements.\nfunction schema(shard: ShardID) {\n return ident(cdcSchema(shard));\n}\n\nexport const PG_SCHEMA = 'cdc';\n\nfunction createSchema(shard: ShardID) {\n return /*sql*/ `CREATE SCHEMA IF NOT EXISTS ${schema(shard)};`;\n}\n\nexport type ChangeLogEntry = {\n // A strictly monotonically increasing, lexicographically sortable\n // value that uniquely identifies a position in the change stream.\n watermark: string;\n change: Change;\n};\n\nfunction createChangeLogTable(shard: ShardID) {\n // Note: The \"change\" column used to be JSONB, but that was problematic in that\n // it does not handle the NULL unicode character.\n // https://vladimir.varank.in/notes/2021/01/you-dont-insert-unicode-null-character-as-postgres-jsonb/\n return /*sql*/ `\n CREATE TABLE ${schema(shard)}.\"changeLog\" (\n watermark TEXT,\n pos INT8,\n change JSON NOT NULL,\n precommit TEXT, -- Only exists on commit entries. Purely for debugging.\n PRIMARY KEY (watermark, pos)\n );\n`;\n}\n\n/**\n * Tracks the watermark from which to resume the change stream and the\n * current owner (task ID) acting as the single writer to the changeLog.\n */\nexport type ReplicationState = {\n lastWatermark: string;\n owner: string | null;\n ownerAddress: string | null;\n};\n\nexport function createReplicationStateTable(shard: ShardID) {\n return /*sql*/ `\n CREATE TABLE ${schema(shard)}.\"replicationState\" (\n \"lastWatermark\" TEXT NOT NULL,\n \"owner\" TEXT,\n \"ownerAddress\" TEXT,\n \"lock\" INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n`;\n}\n\nexport async function discoverChangeStreamerAddress(\n shard: ShardID,\n sql: PostgresDB,\n): Promise<string | null> {\n const result = await sql<{ownerAddress: string | null}[]> /*sql*/ `\n SELECT \"ownerAddress\" FROM ${sql(cdcSchema(shard))}.\"replicationState\"`;\n return result[0].ownerAddress;\n}\n\n/**\n * This mirrors the analogously named table in the SQLite replica\n * (`services/replicator/schema/replication-state.ts`), and is used\n * to detect when the replica has been reset and is no longer compatible\n * with the current ChangeLog.\n */\nexport type ReplicationConfig = {\n replicaVersion: string;\n publications: readonly string[];\n};\n\nfunction createReplicationConfigTable(shard: ShardID) {\n return /*sql*/ `\n CREATE TABLE ${schema(shard)}.\"replicationConfig\" (\n \"replicaVersion\" TEXT NOT NULL,\n \"publications\" TEXT[] NOT NULL,\n \"resetRequired\" BOOL,\n \"lock\" INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n`;\n}\n\nfunction createTables(shard: ShardID) {\n return (\n createSchema(shard) +\n createChangeLogTable(shard) +\n createReplicationStateTable(shard) +\n createReplicationConfigTable(shard)\n );\n}\n\nexport async function setupCDCTables(\n lc: LogContext,\n db: postgres.TransactionSql,\n shard: ShardID,\n) {\n lc.info?.(`Setting up CDC tables`);\n await db.unsafe(createTables(shard));\n}\n\nexport async function markResetRequired(sql: PostgresDB, shard: ShardID) {\n const schema = cdcSchema(shard);\n await sql`\n UPDATE ${sql(schema)}.\"replicationConfig\"\n SET \"resetRequired\" = true`;\n}\n\nexport async function ensureReplicationConfig(\n lc: LogContext,\n db: PostgresDB,\n subscriptionState: SubscriptionState,\n shard: ShardID,\n autoReset: boolean,\n) {\n const {publications, replicaVersion, watermark} = subscriptionState;\n const replicaConfig = {publications, replicaVersion};\n const replicationState: ReplicationState = {\n lastWatermark: replicaVersion,\n owner: null,\n ownerAddress: null,\n };\n const schema = cdcSchema(shard);\n\n await db.begin(async sql => {\n disableStatementTimeout(sql);\n\n const stmts: PendingQuery<Row[]>[] = [];\n const results = await sql<\n {\n replicaVersion: string;\n publications: string[];\n resetRequired: boolean | null;\n }[]\n > /*sql*/ `\n SELECT \"replicaVersion\", \"publications\", \"resetRequired\" \n FROM ${sql(schema)}.\"replicationConfig\"`;\n\n if (results.length) {\n const {replicaVersion, publications} = results[0];\n if (\n replicaVersion !== replicaConfig.replicaVersion ||\n !equals(new Set(publications), new Set(replicaConfig.publications))\n ) {\n if (replicaConfig.replicaVersion !== watermark) {\n throw new AutoResetSignal(\n `Cannot reset change db@${replicaVersion} to ` +\n `service replica@${replicaConfig.replicaVersion} ` +\n `from watermark ${watermark}`,\n );\n }\n lc.info?.(\n `Data in cdc tables @${replicaVersion} is incompatible ` +\n `with replica @${replicaConfig.replicaVersion}. Clearing tables.`,\n );\n // Note: The replicationState table is explicitly not TRUNCATE'd.\n // Any existing row must be overwritten by an UPDATE or\n // INSERT ... ON CONFLICT clause in order to correctly abort\n // any pending transaction by a concurrently running\n // change-streamer. Deleting the existing row and creating\n // a new one, on the other hand, may not properly trigger the\n // SERIALIZATION failure necessary to abort the pending tx.\n stmts.push(\n sql`TRUNCATE TABLE ${sql(schema)}.\"changeLog\"`,\n sql`TRUNCATE TABLE ${sql(schema)}.\"replicationConfig\"`,\n );\n }\n }\n // Initialize (or re-initialize TRUNCATED) tables\n if (results.length === 0 || stmts.length > 0) {\n stmts.push(\n sql`INSERT INTO ${sql(schema)}.\"replicationConfig\" ${sql(replicaConfig)}`,\n sql`INSERT INTO ${sql(schema)}.\"replicationState\" ${sql(replicationState)} \n ON CONFLICT (lock) DO UPDATE SET ${sql(replicationState)}`,\n );\n return Promise.all(stmts);\n }\n\n const {resetRequired} = results[0];\n if (resetRequired) {\n if (autoReset) {\n throw new AutoResetSignal('reset required by replication stream');\n }\n lc.error?.(\n '\\n\\n\\n' +\n 'Reset required but --auto-reset is not enabled.\\n' +\n 'This can happen for upstream databases that do not support event triggers.\\n' +\n 'To correct this, see https://zero.rocicorp.dev/docs/connecting-to-postgres#schema-changes' +\n '\\n\\n\\n',\n );\n }\n\n return [];\n });\n}\n\nexport class AutoResetSignal extends AbortError {\n readonly name = 'AutoResetSignal';\n}\n"],"names":["schema","replicaVersion","publications"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- const version = "0.25.9";
1
+ const version = "0.25.10-canary.1";
2
2
  export {
3
3
  version
4
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rocicorp/zero",
3
- "version": "0.25.9",
3
+ "version": "0.25.10-canary.1",
4
4
  "description": "Zero is a web framework for serverless web development.",
5
5
  "author": "Rocicorp, Inc.",
6
6
  "repository": {