@supalive/core 1.2.0 → 1.2.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.
Files changed (36) hide show
  1. package/README.md +2 -2
  2. package/dist/db-ClCicssQ.js.map +1 -1
  3. package/dist/{index-E1_1iRI1.d.ts → index-DJYvJYR4.d.ts} +6 -5
  4. package/dist/index-DJYvJYR4.d.ts.map +1 -0
  5. package/dist/{mysql-BmkLy5oY.d.ts → mysql-53W9lRh9.d.ts} +2 -2
  6. package/dist/{mysql-BmkLy5oY.d.ts.map → mysql-53W9lRh9.d.ts.map} +1 -1
  7. package/dist/{mysql-Ca1B_0k_.js → mysql-C0mysDQ_.js} +1 -2
  8. package/dist/mysql-C0mysDQ_.js.map +1 -0
  9. package/dist/{postgres-v2ctNE6o.d.ts → postgres-7d6R9P7w.d.ts} +2 -2
  10. package/dist/{postgres-v2ctNE6o.d.ts.map → postgres-7d6R9P7w.d.ts.map} +1 -1
  11. package/dist/{postgres-CHDY1HPf.js → postgres-SvdXfb0w.js} +2 -6
  12. package/dist/postgres-SvdXfb0w.js.map +1 -0
  13. package/dist/src/client/index.d.ts +1 -1
  14. package/dist/src/exports/mysql.d.ts +1 -1
  15. package/dist/src/exports/mysql.js +1 -1
  16. package/dist/src/exports/postgres.d.ts +1 -1
  17. package/dist/src/exports/postgres.js +1 -1
  18. package/dist/src/exports/procedure.d.ts +1 -1
  19. package/dist/src/exports/schema-sql.d.ts +16 -15
  20. package/dist/src/exports/schema-sql.d.ts.map +1 -1
  21. package/dist/src/exports/schema-sql.js +7 -2
  22. package/dist/src/exports/schema-sql.js.map +1 -1
  23. package/dist/src/exports/server.d.ts +17 -16
  24. package/dist/src/exports/server.d.ts.map +1 -1
  25. package/dist/src/exports/server.js +1 -1
  26. package/dist/src/exports/subscription-manager-worker-entry.js +1 -1
  27. package/dist/src/exports/types.d.ts +2 -2
  28. package/dist/{subscription-worker-CAf6MUta.js → subscription-worker-B2XtjFWY.js} +16 -15
  29. package/dist/subscription-worker-B2XtjFWY.js.map +1 -0
  30. package/dist/{types_server-CzAufcee.d.ts → types_server-wW3ZgE7l.d.ts} +2 -2
  31. package/dist/{types_server-CzAufcee.d.ts.map → types_server-wW3ZgE7l.d.ts.map} +1 -1
  32. package/package.json +1 -1
  33. package/dist/index-E1_1iRI1.d.ts.map +0 -1
  34. package/dist/mysql-Ca1B_0k_.js.map +0 -1
  35. package/dist/postgres-CHDY1HPf.js.map +0 -1
  36. package/dist/subscription-worker-CAf6MUta.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-E1_1iRI1.d.ts","names":[],"sources":["../src/db/types_db.ts","../src/server/subscription-manager-types.ts","../src/db/cache.ts","../src/db/db.ts","../src/db/schema.ts","../src/db/query.ts","../src/db/context.ts","../src/db/query_definition.ts","../src/db/realtime_db.ts","../src/router/procedure.ts","../src/router/router.ts","../src/client/ws_client_manager.ts","../src/db/types_client_rpc.ts","../src/client/client.ts","../src/client/caller_client.ts"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"mysql-Ca1B_0k_.js","names":[],"sources":["../src/db/mysql.ts"],"sourcesContent":["import mysql, { Pool, PoolConnection, PoolOptions } from \"mysql2/promise\";\nimport { Database, DbQueryResult, DbType, LazyCommitTsParam, PendingPointEntry, PooledClient, PreparedQueries, PreparedQuery, SqlBuilder, TxDatabase, CoreInitLockCtx, CORE_INIT_LOCK_NAME } from \"./db\";\nimport { CommitLogEntry, normalizeIdToBytes, normalizeToBytes, OccConflictError, PointRead, ReadEntry, WriteEntry } from \"./types_db\";\nimport { utf8Encode } from \"./bytes\";\n\n// mysql2 expects Buffer (not plain Uint8Array) for binary params.\nfunction toBufferView(bytes: Uint8Array): Buffer {\n if (Buffer.isBuffer(bytes)) return bytes;\n return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n}\nimport { checkLogsAffectReadSet, mapReadSetToRaw } from \"../server/overlap-checker\";\nimport { supaliveStringify } from \"../helper\";\nimport { CacheLayer } from \"./cache\";\nimport { Logger } from \"pino\";\n\n/**\n * mysql2 returns `ResultSetHeader` for non-SELECT queries (carrying\n * `affectedRows`) and `RowDataPacket[]` for SELECTs. The previous shim\n * blindly cast to T[] which made `rowCount` zero for UPDATE/DELETE, breaking\n * CAS detection. This helper picks the right shape.\n */\nfunction normalizeMysqlResult<T>(raw: unknown): DbQueryResult<T> {\n if (Array.isArray(raw)) {\n return { rows: raw as T[], rowCount: raw.length };\n }\n if (raw && typeof raw === \"object\" && \"affectedRows\" in raw) {\n return { rows: [], rowCount: Number((raw as { affectedRows: number }).affectedRows) || 0 };\n }\n return { rows: [], rowCount: 0 };\n}\n\ninterface QueryConnection {\n query(opts: { sql: string; timeout?: number; values?: unknown[] }): Promise<[any[], unknown]>;\n query(sql: string, params?: unknown[]): Promise<[any[], unknown]>;\n}\n\n/**\n * mysql2's PoolOptions does not have a per-statement timeout field; we\n * carry our own. Set 0 to disable.\n */\nexport type MySqlPoolOptions = PoolOptions & { queryTimeoutMs?: number };\n\nexport class MySqlDatabase implements Database {\n constructor(\n logger: Logger,\n config: MySqlPoolOptions,\n pool: Pool | undefined = undefined,\n ) {\n this.logger = logger;\n const { queryTimeoutMs, ...poolConfig } = config;\n this.queryTimeoutMs = queryTimeoutMs ?? 0;\n this.config = poolConfig;\n if (pool) {\n this.pool = pool;\n } else {\n this.pool = mysql.createPool(poolConfig);\n }\n }\n\n private logger: Logger;\n public config: PoolOptions;\n protected queryTimeoutMs: number;\n private pool: Pool;\n readonly dbType: DbType = \"mysql\";\n readonly sqlBuilder: SqlBuilder = mysqlSql;\n // Lazy per-table column-type cache. The apply path consults this for\n // unnest carriers/casts in batched writes; we never re-query pg_attribute\n // for a table we've already seen unless the cache is explicitly\n // invalidated (e.g. after a migration). Shared with tx clients via\n // adoptRegistries so a single startup load services all transactions.\n public columnTypes: Map<string, Map<string, string>> = new Map();\n // Compiled-SQL cache keyed by (op, table, sorted column signature).\n // Mirrors columnTypes — invalidated together when types change.\n protected sqlCache: Map<string, string> = new Map();\n\n /**\n * Fetches actual column types from MySQL for `table` and returns a\n * map of DB column name → MySQL type string (as produced by `COLUMN_TYPE`,\n * e.g. `bigint`, `integer`, `varchar(32)`, `text`, `json`).\n * No caching here — see {@link getColumnTypes} for the cached path.\n */\n async loadColumnTypesFromMySql(table: string): Promise<Map<string, string>> {\n const result = await this.query<{ column_name: string; mysql_type: string }>(\n `SELECT COLUMN_NAME AS column_name, COLUMN_TYPE AS mysql_type\n FROM INFORMATION_SCHEMA.COLUMNS\n WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?\n ORDER BY ORDINAL_POSITION`,\n [table],\n );\n // MySQL folds unquoted identifiers to lowercase on the server side, so\n // COLUMN_NAME comes back lowercase. JS-side column keys\n // (`entry.data`) often arrive in camelCase from the schema layer; we\n // lookup via lowercase to bridge the two cases without making callers\n // worry about it.\n const out = new Map<string, string>();\n for (const row of result.rows) out.set(row.column_name.toLowerCase(), row.mysql_type);\n return out;\n }\n\n /**\n * Synchronous column-type lookup. The apply path calls this on every\n * batched write, so it can't await — populate the cache via\n * {@link bootstrapColumnTypes} at server start. Throws if `table` is\n * missing (programmer error / bootstrap skipped).\n */\n getColumnTypes(table: string): Map<string, string> | null {\n const hit = this.columnTypes.get(table);\n if (!hit) {\n this.logger.warn({ table }, \"MySqlDatabase: no cached column types fallback to non-batched writes\");\n return null;\n }\n return hit;\n }\n\n /**\n * Eagerly load column types into the in-memory cache. With a Redis\n * client supplied, attempts the cache key first and falls through to\n * MySQL on miss (writing the result back to Redis). This is the\n * \"one server queries MySQL, the rest read from Redis\" pattern for cold\n * starts in a multi-instance deploy. Without Redis, always queries MySQL.\n *\n * Pass `tables` to limit the load to a specific list; otherwise every\n * user table in the connected database is loaded.\n *\n * The Redis cache key should encode whatever invalidates types in your\n * environment (typically a schema version / deploy version). The\n * subscriber in supalive-server.ts is expected to publish a reload\n * signal after migrations and invoke {@link invalidateColumnTypes}.\n */\n async bootstrapColumnTypes(opts: {\n redis?: CacheLayer;\n cacheKey: string;\n tables?: string[];\n }): Promise<void> {\n this.invalidateColumnTypes();\n\n const { redis, cacheKey, tables } = opts;\n\n // Redis hit path: deserialize the full table → column → mysqlType map\n // and populate in one shot, skipping any INFORMATION_SCHEMA round-trips.\n if (redis) {\n const cached = await redis.getCachedTableColumnTypes(cacheKey);\n if (cached) {\n for (const [table, cols] of Object.entries(cached)) {\n this.columnTypes.set(table, new Map(Object.entries(cols)));\n }\n return;\n }\n }\n\n // Cache miss (or no Redis): query MySQL for the listed tables\n // (or enumerate all user tables) and populate.\n const names = tables ?? await this.listUserTables();\n for (const t of names) {\n if (this.columnTypes.has(t)) continue;\n\n const fresh = await this.loadColumnTypesFromMySql(t);\n this.columnTypes.set(t, fresh);\n }\n\n // Write back to Redis so subsequent server instances skip the MySQL hop.\n if (redis) {\n const dump: Record<string, Record<string, string>> = {};\n for (const [table, cols] of this.columnTypes) {\n dump[table] = Object.fromEntries(Object.entries(cols).sort());\n }\n await redis.setCachedTableColumnsTypes(cacheKey, dump);\n }\n }\n\n /**\n * Invalidate cached types (and dependent SQL) for `table`, or the entire\n * cache if `table` is omitted. The Redis-pubsub reload signal in\n * supalive-server.ts is expected to call this on schema changes.\n */\n invalidateColumnTypes(table?: string): void {\n if (table) {\n this.columnTypes.delete(table);\n for (const k of [...this.sqlCache.keys()]) {\n if (k.includes(`:${table}:`) || k === `d:${table}`) this.sqlCache.delete(k);\n }\n } else {\n this.columnTypes.clear();\n this.sqlCache.clear();\n }\n }\n\n /** Replace this instance's caches with shared references from a parent.\n * Used by getTransactionClient so types loaded once at startup are\n * visible inside transactions. */\n adoptCaches(\n columnTypes: Map<string, Map<string, string>>,\n sqlCache: Map<string, string>,\n ): void {\n this.columnTypes = columnTypes;\n this.sqlCache = sqlCache;\n }\n\n /** Enumerate the user-defined tables in the connected database for mysql — used\n * by bootstrapColumnTypes() when no explicit list is provided. */\n private async listUserTables(): Promise<string[]> {\n const result = await this.query<{ table_name: string }>(\n `SELECT table_name FROM information_schema.tables\n WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'\n AND table_name NOT IN ('commit_logs', 'metadata', 'global_commit_ts')`\n );\n return result.rows.map(r => r.table_name);\n }\n\n async getCoreVersion(): Promise<bigint> {\n const result = await this.query<{ meta_value: string | number | bigint }>(\n \"SELECT meta_value FROM metadata WHERE meta_key = 'core_version'\",\n );\n return BigInt(result.rows[0]?.meta_value ?? 0);\n }\n\n // Non-table core bootstrap applied per version step. Tables live in the\n // generated schema (see coreTablesSql); this covers the MySQL timestamp\n // `global_commit_ts` counter table + seed and the metadata seed rows.\n coreMigrationStatements(toVersion: bigint): string[] {\n if (toVersion === 1n) {\n return [\n `CREATE TABLE IF NOT EXISTS global_commit_ts (id BIGINT NOT NULL)`,\n `INSERT IGNORE INTO global_commit_ts VALUES (0)`,\n `INSERT IGNORE INTO metadata (meta_key, meta_value) VALUES ('latest_committed_ts', 0)`,\n `INSERT IGNORE INTO metadata (meta_key, meta_value) VALUES ('min_retained_ts', 0)`,\n ];\n }\n return [];\n }\n\n async withCoreInitLock(fn: (ctx: CoreInitLockCtx) => Promise<void>): Promise<void> {\n const conn = await this.pool.getConnection();\n try {\n // Named session lock: serializes core init across processes. Held for\n // the duration of fn and explicitly released in finally.\n const [rows] = await conn.query(\"SELECT GET_LOCK(?, 30) AS locked\", [CORE_INIT_LOCK_NAME]);\n const locked = Array.isArray(rows) ? (rows[0] as { locked: number } | undefined)?.locked : undefined;\n if (locked !== 1) {\n throw new Error(`Failed to acquire core-init lock '${CORE_INIT_LOCK_NAME}'`);\n }\n\n const ctx: CoreInitLockCtx = {\n exec: async (sql, params = []) => {\n const [r] = await conn.query(sql, params);\n return normalizeMysqlResult(r);\n },\n getVersion: async () => {\n const [r] = await conn.query(\"SELECT meta_value FROM metadata WHERE meta_key = 'core_version'\");\n const row = Array.isArray(r) ? (r[0] as { meta_value: string | number | bigint } | undefined) : undefined;\n return BigInt(row?.meta_value ?? 0);\n },\n setVersion: async (version) => {\n await conn.query(\n `INSERT INTO metadata (meta_key, meta_value) VALUES ('core_version', ?)\n ON DUPLICATE KEY UPDATE meta_value = VALUES(meta_value)`,\n [version.toString()],\n );\n },\n };\n\n await fn(ctx);\n } finally {\n await conn.query(\"SELECT RELEASE_LOCK(?)\", [CORE_INIT_LOCK_NAME]).catch(() => { });\n conn.release();\n }\n }\n\n async query<T = any>(sql: string, params: unknown[] = []): Promise<DbQueryResult<T>> {\n const client = await this.pool.getConnection() as PoolConnection & QueryConnection;\n try {\n const [rows] = this.queryTimeoutMs > 0\n ? await client.query({ sql, values: params, timeout: this.queryTimeoutMs })\n : await client.query(sql, params);\n return normalizeMysqlResult<T>(rows);\n } catch (err) {\n throw translateMysqlError(err);\n } finally {\n client.release();\n }\n }\n\n async getClient(): Promise<PooledClient> {\n const client = await this.pool.getConnection();\n return client as unknown as PooledClient;\n }\n\n async getTransactionClient(): Promise<TxDatabase> {\n const client = await this.pool.getConnection();\n const tx = new MySqlTxDatabase(this.logger, { ...this.config, queryTimeoutMs: this.queryTimeoutMs }, this.pool, client as PoolConnection & QueryConnection);\n tx.adoptCaches(this.columnTypes, this.sqlCache);\n return tx;\n }\n\n async getLatestSnapshotTimestamp(): Promise<bigint> {\n const result = await this.query<{ meta_value: string | number }>(\"SELECT meta_value FROM metadata WHERE meta_key = 'latest_committed_ts'\");\n return BigInt(result.rows[0]?.meta_value ?? 0);\n }\n\n async updateLatestSnapshotTimestamp(commitTs: bigint): Promise<void> {\n await this.query(\n `UPDATE metadata SET meta_value = ? WHERE meta_key = 'latest_committed_ts' AND meta_value < ?`,\n [commitTs, commitTs]\n );\n }\n\n async getMinSnapshotTimestamp(): Promise<bigint> {\n const result = await this.query<{ meta_value: string | number }>(\"SELECT meta_value FROM metadata WHERE meta_key = 'min_retained_ts'\");\n return BigInt(result.rows[0]?.meta_value ?? 0);\n }\n\n async updateMinSnapshotTimestamp(ts: bigint): Promise<void> {\n await this.query(\n `UPDATE metadata SET meta_value = ? WHERE meta_key = 'min_retained_ts' AND meta_value < ?`,\n [ts, ts]\n );\n }\n\n async getNextTimestamp(): Promise<bigint> {\n const result = await this.query<{ id: string | number | bigint }>(\n \"UPDATE global_commit_ts SET id = LAST_INSERT_ID(id + 1); SELECT LAST_INSERT_ID() AS id\"\n );\n return BigInt(result.rows[0]?.id ?? 0);\n }\n\n // Runs on the pool, not the tx client — intentionally. This keeps the\n // transaction window short, but it means `prevData` is not snapshot-\n // consistent with the eventual commitTs (a peer may have moved the row\n // between beginTs and this SELECT). That's safe because:\n // 1. The per-row CAS in pgApplyWrites is the real snapshot fence. If a\n // peer committed in our staleness window, the CAS sees a moved\n // commit_ts and throws OccConflictError → retry.\n // 2. The only window where CAS passes with \"stale\" prevData is when\n // the current row at our SELECT moment matches `expectedCommitTs`;\n // by construction nobody committed between our captured ts and now,\n // so prevData IS consistent with the ts we're CAS-ing against.\n // 3. The downstream consumer (overlap-checker.checkRowWriteAffectsRange)\n // is conservative on missing/odd prevData — \"unknown\" verdicts still\n // invalidate, so the worst case here is a spurious invalidation,\n // never a missed one.\n // Locked in by mysql.attach-prev-data.test.ts.\n async attachPrevDataToWriteSet(writeSet: WriteEntry[], readSet: ReadEntry[]): Promise<void> {\n const readTsByKey = new Map<string, bigint | null>();\n for (let i = readSet.length - 1; i >= 0; i--) {\n const r = readSet[i]!;\n if (r.kind !== \"point\" || r.expectedCommitTs === undefined) continue;\n\n const key = `${r.table} ${r.id}`;\n if (!readTsByKey.has(key)) readTsByKey.set(key, r.expectedCommitTs);\n }\n\n const byTable = new Map<string, WriteEntry[]>();\n for (const entry of writeSet) {\n if (entry.op !== \"update\" && entry.op !== \"delete\") continue;\n\n const bucket = byTable.get(entry.table);\n if (bucket) bucket.push(entry);\n else byTable.set(entry.table, [entry]);\n }\n if (byTable.size === 0) return;\n\n for (const [table, entries] of byTable) {\n const ids = entries.map((e) => e.id);\n const placeholders = ids.map(() => \"?\").join(\", \");\n // No FOR UPDATE — the per-row CAS on the subsequent UPDATE/DELETE is\n // the fence. If a peer mutated the row since our read, the CAS will\n // see a stale expected commit_ts and throw OCC.\n const sql = `SELECT * FROM ${table} WHERE id IN (${placeholders})`;\n const result = await this.query<Record<string, unknown>>(sql, ids);\n\n const byId = new Map<string, Record<string, unknown>>();\n for (const row of result.rows) {\n byId.set(String(row.id), row);\n }\n for (const entry of entries) {\n const row = byId.get(String(entry.id));\n const key = `${entry.table} ${entry.id}`;\n const priorReadTs = readTsByKey.get(key);\n\n if (row) {\n entry.prevData = row;\n // Prefer the read-time ts so read-then-update patterns get\n // beginTs-level isolation; fall back to current row ts for\n // blind writes (no prior read).\n entry.expectedCommitTs = priorReadTs !== undefined\n ? priorReadTs\n : BigInt(row.commit_ts as string | number | bigint);\n } else if (priorReadTs !== undefined) {\n // Row gone now, but we had read it earlier: carry the read ts —\n // the CAS will then mismatch (row deleted) and throw OCC.\n entry.expectedCommitTs = priorReadTs;\n }\n // else: neither a prior read nor a current row → leave undefined\n // so CAS misses and surfaces OCC.\n }\n }\n }\n\n // Prepare BEFORE the conflict scan: each write is a CAS against the row's\n // commit_ts, so any concurrent peer that touched the row produces a\n // 0-row-affected UPDATE/DELETE → OccConflictError. Inserts surface as\n // PK violations, also translated to OCC.\n async prepareCommitWrites(\n readSet: ReadEntry[],\n writeSet: WriteEntry[],\n commitTs: LazyCommitTsParam,\n ): Promise<PreparedQueries> {\n const result: PreparedQuery[] = [];\n\n await this.mysqlPrepareBatchWrites(result, writeSet, commitTs);\n await this.mysqlPrepareCommitLogs(result, writeSet, commitTs);\n\n const hasRangeRead = readSet.some(r => r.kind === \"range\");\n if (!hasRangeRead) {\n const validateReads = this.mysqlPrepareValidatePointReadsByCommitTs(readSet, writeSet);\n return { commits: result, validateReadPoints: validateReads, hasRangeRead: false };\n }\n\n // has atleast one range read so use scan, prepare data\n const tableIds = [...new Set(readSet.map(r => r.tableId))];\n const rawReadSet = mapReadSetToRaw(readSet);\n\n return { commits: result, hasRangeRead: true, tableIds: tableIds, rawReadSet: rawReadSet };\n }\n\n private async mysqlPrepareBatchWrites(\n result: PreparedQuery[],\n writeSet: WriteEntry[],\n commitTs: LazyCommitTsParam,\n ) {\n let i = 0;\n let counter = 0;\n while (i < writeSet.length) {\n counter++;\n const { table, op } = writeSet[i];\n let j = i + 1;\n while (j < writeSet.length && writeSet[j].table === table && writeSet[j].op === op) j++;\n\n const batch = writeSet.slice(i, j);\n if (op === \"insert\") await this.mysqlPrepareInsertBatch(result, table, batch, commitTs);\n else if (op === \"update\") await this.mysqlPrepareUpdateSingle(result, table, batch, commitTs);\n else await this.mysqlPrepareDeleteBatch(result, table, batch);\n i = j;\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n }\n }\n\n private async mysqlPrepareInsertBatch(\n result: PreparedQuery[],\n table: string,\n entries: WriteEntry[],\n commitTs: LazyCommitTsParam,\n ) {\n if (entries.length === 0) return;\n\n const groups = new Map<string, { cols: string[]; rows: WriteEntry[] }>();\n for (const entry of entries) {\n const cols = [...Object.keys(entry.data ?? {}), 'commit_ts'].sort();\n const key = cols.join(\"|\");\n let g = groups.get(key);\n if (!g) { g = { cols, rows: [] }; groups.set(key, g); }\n g.rows.push(entry);\n }\n\n let counter = 0;\n for (const { cols, rows } of groups.values()) {\n counter++;\n\n const values: unknown[] = [];\n const tuples: string[] = [];\n for (const entry of rows) {\n const data = { ...(entry.data ?? {}), commit_ts: commitTs } as Record<string, unknown>;\n tuples.push(`(${cols.map(() => \"?\").join(\", \")})`);\n for (const col of cols) {\n values.push(data[col]);\n }\n }\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n\n result.push({\n sql: `INSERT INTO ${table} (${cols.join(\", \")}) VALUES ${tuples.join(\", \")}`,\n params: values,\n operation: \"insertBatch\",\n table: table,\n })\n }\n }\n\n private async mysqlPrepareUpdateSingle(\n result: PreparedQuery[],\n table: string,\n entries: WriteEntry[],\n commitTs: LazyCommitTsParam,\n ) {\n if (entries.length === 0) return;\n\n let counter = 0;\n for (const entry of entries) {\n counter++;\n\n const data = { ...(entry.data ?? {}), commit_ts: commitTs };\n const columns = Object.keys(data);\n const sets = columns.map((c) => `${c} = ?`);\n const values = Object.values(data);\n const expected = entry.expectedCommitTs ?? -1n;\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n\n result.push({\n sql: `UPDATE ${table} SET ${sets.join(\", \")} WHERE id = ? AND commit_ts = ?`,\n params: [...values, entry.id, expected],\n operation: 'updateSingle',\n table: table,\n entryId: entry.id,\n expectedTs: expected,\n })\n }\n }\n\n private async mysqlPrepareDeleteBatch(\n result: PreparedQuery[],\n table: string,\n entries: WriteEntry[],\n ) {\n if (entries.length === 0) return;\n\n let counter = 0;\n for (const entry of entries) {\n counter++;\n\n const expected = entry.expectedCommitTs ?? -1n;\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n\n result.push({\n sql: `DELETE FROM ${table} WHERE id = ? AND commit_ts = ?`,\n params: [entry.id, expected],\n table: table,\n operation: 'deleteSingle',\n entryId: entry.id,\n expectedTs: expected,\n });\n }\n }\n\n private async mysqlPrepareCommitLogs(\n result: PreparedQuery[],\n writeEntries: WriteEntry[],\n commitTs: LazyCommitTsParam,\n ) {\n if (writeEntries.length === 0) return;\n\n const values: unknown[] = [];\n const tuples: string[] = [];\n let counter = 0;\n\n for (const entry of writeEntries) {\n counter++;\n\n tuples.push(`(?, ?, ?, ?)`);\n values.push(\n toBufferView(normalizeIdToBytes(entry.id)),\n commitTs,\n toBufferView(entry.tableId),\n toBufferView(utf8Encode(supaliveStringify(entry))),\n );\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n }\n\n result.push({\n sql: `INSERT INTO commit_logs (id, ts, table_id, data) VALUES ${tuples.join(\", \")}`,\n params: values,\n table: 'commit_logs',\n operation: 'commit_logs',\n })\n }\n\n /**\n * Point-only OCC check. For each genuine point read, compare the row's\n * current commit_ts against the value captured at read time. A `null`\n * expectedCommitTs means \"row didn't exist when we read\"; any row found\n * now is a conflict. Reads whose row is being written in this same txn\n * are skipped — the CAS UPDATE/DELETE already validated those.\n */\n private mysqlPrepareValidatePointReadsByCommitTs(\n readSet: ReadEntry[],\n writeSet: WriteEntry[],\n ): PreparedQuery[] {\n const result: PreparedQuery[] = [];\n\n // Skip reads whose row is being mutated in this same tx — CAS already\n // fenced them. We dedupe per (table, id) so duplicate reads of the same\n // row don't cause extra fetches.\n const writeKeys = new Set<string>();\n for (const w of writeSet) writeKeys.add(`${w.table} ${w.id}`);\n\n const byTable = new Map<string, PendingPointEntry[]>();\n const seen = new Set<string>();\n\n for (const entry of readSet) {\n if (entry.kind !== \"point\") continue;\n\n const key = `${entry.table} ${entry.id}`;\n if (writeKeys.has(key) || seen.has(key)) continue;\n\n seen.add(key);\n // expectedCommitTs === undefined → no commit_ts captured at read time\n // (synthetic or pre-migration). Skip — we cannot CAS-validate it. This\n // path should only fire when callers construct PointReads externally.\n if (entry.expectedCommitTs === undefined) continue;\n\n const bucket = byTable.get(entry.table);\n if (bucket) bucket.push({ entry, key });\n else byTable.set(entry.table, [{ entry, key }]);\n }\n\n for (const [table, pendings] of byTable) {\n const ids = pendings.map((p) => p.entry.id);\n const placeholders = ids.map(() => \"?\").join(\", \");\n\n result.push({\n sql: `SELECT id, commit_ts FROM ${table} WHERE id IN (${placeholders})`,\n params: ids,\n table: table,\n operation: 'pointReadValidation',\n pendingsEntry: pendings,\n });\n }\n\n return result;\n }\n\n async commitWrites(\n beginTs: bigint,\n queries: PreparedQueries,\n commitTs: bigint,\n ): Promise<{ success: boolean }> {\n await this.mysqlApplyWrites(queries.commits);\n\n // Fast path: when the readSet has no range reads, we don't need a\n // commit-log scan at all — point reads validate via per-row commit_ts,\n // and writes already self-validated via CAS above. This is the dominant\n // shape (most mutations target known ids) and eliminates the heaviest\n // OCC cost in the previous design.\n if (!queries.hasRangeRead) {\n if ((queries.validateReadPoints?.length ?? 0) > 0) {\n await this.validatePointReadsByCommitTs(queries.validateReadPoints ?? []);\n }\n return { success: true };\n }\n\n // Slow path: at least one range read present. Fall back to the\n // commit-log scan so phantom inserts and predicate transitions-in are\n // still caught. Point reads in the same set are covered by the same\n // scan, so no separate validation is needed.\n const logs = await this.getCommitLogsSinceTs(beginTs, commitTs, queries.tableIds ?? []);\n const hasConflict = checkLogsAffectReadSet(logs, queries.rawReadSet ?? []);\n if (hasConflict) {\n throw new OccConflictError(\n `Conflict detected: overlapping commit logs since ${beginTs}`,\n { logs }\n );\n }\n\n return { success: true };\n }\n\n // Walks the writeSet in order and coalesces consecutive entries with the\n // same (table, op) into one batched statement. Order is preserved across\n // batch boundaries so replace-patterns (delete-then-insert of the same\n // id) behave identically to the per-row code path. Single-row batches\n // take a direct INSERT/UPDATE/DELETE fast-path to avoid the unnest+join\n // overhead, which matters under high contention.\n private async mysqlApplyWrites(result: PreparedQuery[]): Promise<void> {\n for (const q of result) {\n switch (q.operation) {\n case 'insertBatch': {\n try {\n await this.query(q.sql, q.params);\n } catch (err) {\n if (\n err && typeof err === \"object\" &&\n ((err as { errno?: number }).errno === 1062 ||\n (err as { code?: string }).code === \"ER_DUP_ENTRY\")\n ) {\n const msg = (err as { message?: string }).message ?? \"\";\n const idMatch = msg.match(/key '[^']+'.*?\\(.*?\\)=\\(?([^,\\)]+)/);\n const failedId = idMatch?.[1];\n throw new OccConflictError(\n failedId !== undefined\n ? `Conflict: insert into ${q.table}/${failedId} hit duplicate key`\n : `Conflict: batch insert into ${q.table} hit duplicate key`,\n err,\n );\n }\n throw err;\n }\n break;\n }\n case 'updateSingle': {\n const result = await this.query(q.sql, q.params);\n if ((result.rowCount ?? 0) === 0) {\n throw new OccConflictError(\n `Conflict: CAS update of ${q.table}/${q.entryId} (expected commit_ts=${q.expectedTs}) matched no rows`,\n { table: q.table, id: q.entryId, expected: q.expectedTs },\n );\n }\n break;\n }\n case 'deleteBatch': {\n const result = await this.query(q.sql, q.params);\n if ((result.rowCount ?? 0) === 0) {\n throw new OccConflictError(\n `Conflict: CAS delete of ${q.table}/${q.entryId} (expected commit_ts=${q.expectedTs}) matched no rows`,\n { table: q.table, id: q.entryId, expected: q.expectedTs },\n );\n }\n break;\n }\n case 'commit_logs': {\n await this.query(q.sql, q.params);\n break;\n }\n default:\n throw new Error(\"Unhandled MySQL Operation: \" + q.operation);\n\n }\n }\n }\n\n private async validatePointReadsByCommitTs(queries: PreparedQuery[]): Promise<void> {\n\n for (const q of queries) {\n const result = await this.query<{ id: string; commit_ts: string | number | bigint }>(q.sql, q.params);\n\n const currentById = new Map<string, bigint>();\n for (const row of result.rows) {\n currentById.set(String(row.id), BigInt(row.commit_ts));\n }\n\n for (const { entry } of q.pendingsEntry ?? []) {\n const current = currentById.get(String(entry.id));\n const expected = entry.expectedCommitTs;\n\n if (expected === null) {\n // We read \"no row\"; conflict if a row now exists.\n if (current !== undefined) {\n throw new OccConflictError(\n `Conflict: row ${entry.table}/${entry.id} was inserted concurrently`,\n { table: entry.table, id: entry.id }\n );\n }\n } else {\n if (current === undefined) {\n throw new OccConflictError(\n `Conflict: row ${entry.table}/${entry.id} was deleted concurrently`,\n { table: entry.table, id: entry.id, expected }\n );\n }\n if (current !== expected) {\n throw new OccConflictError(\n `Conflict: row ${entry.table}/${entry.id} changed from ts=${expected} to ts=${current}`,\n { table: entry.table, id: entry.id, expected, current }\n );\n }\n }\n }\n }\n }\n\n async pruneCommitLogsBefore(ts: bigint): Promise<bigint> {\n const result = await this.query(\n `DELETE FROM commit_logs WHERE ts < ?`,\n [ts]\n );\n return BigInt(result.rowCount ?? 0);\n }\n\n async getMinCommitLogTs(): Promise<bigint | null> {\n const result = await this.query<{ min: string | number | bigint | null }>(\n `SELECT min(ts) AS min FROM commit_logs`,\n );\n const min = result.rows[0]?.min;\n return min === null || min === undefined ? null : BigInt(min);\n }\n\n async getCommitLogsBetweenTs(beginTs: bigint, endTs: bigint, tableIds: Uint8Array[]): Promise<CommitLogEntry[]> {\n if (tableIds.length === 0) return [];\n\n const placeholders = tableIds.map(() => '?').join(\", \");\n const sql = `SELECT id, ts, table_id, data FROM commit_logs WHERE ts >= ? AND ts < ? AND table_id IN (${placeholders})`;\n\n const result = await this.query<{ id: unknown; ts: string | number | bigint; table_id: unknown; data: unknown }>(\n sql,\n [beginTs, endTs, ...tableIds.map(toBufferView)]\n );\n\n return result.rows.map((row) => ({\n id: normalizeToBytes(row.id),\n ts: BigInt(row.ts),\n tableId: normalizeToBytes(row.table_id),\n data: normalizeToBytes(row.data),\n }));\n }\n\n async getCommitLogsSinceTs(sinceTs: bigint, excludeTs: bigint, tableIds: Uint8Array[]): Promise<CommitLogEntry[]> {\n if (tableIds.length === 0) return [];\n\n const placeholders = tableIds.map(() => '?').join(\", \");\n const sql = `SELECT id, ts, table_id, data FROM commit_logs WHERE ts >= ? AND ts <> ? AND table_id IN (${placeholders})`;\n\n const result = await this.query<{ id: unknown; ts: string | number | bigint; table_id: unknown; data: unknown }>(\n sql,\n [sinceTs, excludeTs, ...tableIds.map(toBufferView)]\n );\n\n return result.rows.map((row) => ({\n id: normalizeToBytes(row.id),\n ts: BigInt(row.ts),\n tableId: normalizeToBytes(row.table_id),\n data: normalizeToBytes(row.data),\n }));\n }\n\n async close(): Promise<void> {\n await this.pool.end();\n }\n}\n\nexport class MySqlTxDatabase extends MySqlDatabase {\n constructor(logger: Logger, config: MySqlPoolOptions, pool: Pool, client: PoolConnection & QueryConnection) {\n super(logger, config, pool);\n this.client = client;\n }\n\n private client: PoolConnection & QueryConnection;\n\n async query<T = any>(sql: string, params: unknown[] = []): Promise<DbQueryResult<T>> {\n try {\n const [rows] = this.queryTimeoutMs > 0\n ? await this.client.query({ sql, values: params as any[], timeout: this.queryTimeoutMs })\n : await this.client.query(sql, params as any[]);\n return normalizeMysqlResult<T>(rows);\n } catch (err) {\n throw translateMysqlError(err);\n }\n }\n\n async begin(): Promise<void> {\n await this.client.beginTransaction();\n }\n\n async commit(): Promise<void> {\n await this.client.commit();\n }\n\n async rollback(): Promise<void> {\n await this.client.rollback();\n }\n\n release(): void {\n this.client.release();\n }\n}\n\n/**\n * MySQL InnoDB deadlock (errno 1213 / SQLSTATE 40001) is transient and\n * semantically equivalent to an OCC conflict from the mutation runner's\n * perspective: re-execute the handler with a fresh snapshot. Wrapping\n * here lets realtime_db.ts stay driver-agnostic — its retry loop already\n * handles OccConflictError.\n */\nfunction translateMysqlError(err: unknown): unknown {\n if (\n err && typeof err === \"object\" &&\n ((err as { errno?: number }).errno === 1213 ||\n (err as { code?: string }).code === \"ER_LOCK_DEADLOCK\")\n ) {\n return new OccConflictError(\"deadlock detected\", err);\n }\n return err;\n}\n\nconst mysqlSql: SqlBuilder = {\n placeholder: (i) => `?`,\n like: (col, i) => `${col} LIKE ?`,\n ilike: (col, i) => `${col} LIKE ?`, // MySQL doesn't have ILIKE\n icontains: (col, i) => `${col} LIKE ?`,\n // CAST(? AS JSON) lets the driver bind the param as a regular string\n // (JSON-serialized client-side) and MySQL re-parses it into a JSON value\n // for containment comparison. When a sub-path is set, JSON_CONTAINS takes\n // the path as its third argument.\n jsonContains: (col, _i, opts) => opts?.pathIndex !== undefined\n ? `JSON_CONTAINS(${col}, CAST(? AS JSON), ?)`\n : `JSON_CONTAINS(${col}, CAST(? AS JSON))`,\n jsonContainedBy: (col, _i, opts) => opts?.pathIndex !== undefined\n // For \"is the column contained in the candidate at this sub-path of the\n // column\" we still need to extract the sub-path from the column side.\n // JSON_CONTAINS's path arg is on the TARGET position, so we flip and use\n // JSON_EXTRACT for the column side instead.\n ? `JSON_CONTAINS(CAST(? AS JSON), JSON_EXTRACT(${col}, ?))`\n : `JSON_CONTAINS(CAST(? AS JSON), ${col})`,\n jsonHasKey: (col, _i, opts) => {\n if (opts?.pathCount && opts.pathCount > 0) {\n const mode = opts.mode === \"all\" ? \"'all'\" : \"'one'\";\n const places = new Array(opts.pathCount).fill(\"?\").join(\", \");\n return `JSON_CONTAINS_PATH(${col}, ${mode}, ${places})`;\n }\n return opts?.raw\n // Param is already a JSON path expression like `$.foo.bar` or `$.\"a\".\"b\"`.\n ? `JSON_CONTAINS_PATH(${col}, 'one', ?)`\n // Param is a literal top-level key. Wrap it in `$.\"<key>\"` server-side\n // and escape any embedded double-quotes so dotted keys behave as keys\n // and not nested paths.\n : `JSON_CONTAINS_PATH(${col}, 'one', CONCAT('$.\"', REPLACE(?, '\"', '\\\\\\\\\"'), '\"'))`;\n },\n jsonArrayContains: (col, _i, opts) => opts?.pathIndex !== undefined\n ? `JSON_CONTAINS(${col}, JSON_ARRAY(CAST(? AS JSON)), ?)`\n : `JSON_CONTAINS(${col}, JSON_ARRAY(CAST(? AS JSON)))`,\n};\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"postgres-CHDY1HPf.js","names":[],"sources":["../src/db/postgres.ts"],"sourcesContent":["import { Pool, PoolConfig, PoolClient } from \"pg\";\nimport { Database, PooledClient, DbQueryResult, DbType, SqlBuilder, TxDatabase, PreparedQuery, PendingPointEntry, PreparedQueries, LazyCommitTsParam, CoreInitLockCtx, CORE_INIT_LOCK_KEY } from \"./db\";\nimport type { CommitLogEntry, ReadEntry, WriteEntry } from \"./types_db\";\nimport { normalizeIdToBytes, OccConflictError, normalizeToBytes } from \"./types_db\";\nimport { utf8Encode } from \"./bytes\";\n\n// pg's bytea encoder checks `Buffer.isBuffer`; a plain Uint8Array falls through\n// to its scalar path and corrupts the bytes. Wrap as a zero-copy Buffer view.\nfunction toBufferView(bytes: Uint8Array): Buffer {\n if (Buffer.isBuffer(bytes)) return bytes;\n return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n}\nimport { checkLogsAffectReadSet, mapReadSetToRaw } from \"../server/overlap-checker\";\nimport { supaliveStringify } from \"../helper\";\nimport { CacheLayer } from \"./cache\";\nimport { Logger } from \"pino\";\n\nexport class PgDatabase implements Database {\n constructor(\n logger: Logger,\n config: PoolConfig,\n pool: Pool | undefined = undefined,\n ) {\n this.logger = logger;\n this.config = config;\n if (pool) {\n this.pool = pool;\n } else {\n this.pool = new Pool(config);\n }\n }\n\n private logger: Logger;\n public config: PoolConfig;\n private pool: Pool;\n readonly sqlBuilder: SqlBuilder = pgSql;\n readonly dbType: DbType = \"postgres\";\n // Lazy per-table column-type cache. The apply path consults this for\n // unnest carriers/casts in batched writes; we never re-query pg_attribute\n // for a table we've already seen unless the cache is explicitly\n // invalidated (e.g. after a migration). Shared with tx clients via\n // adoptRegistries so a single startup load services all transactions.\n public columnTypes: Map<string, Map<string, string>> = new Map();\n // Compiled-SQL cache keyed by (op, table, sorted column signature).\n // Mirrors columnTypes — invalidated together when types change.\n protected sqlCache: Map<string, string> = new Map();\n\n /**\n * Fetches actual column types from Postgres for `table` and returns a\n * map of DB column name → PG type string (as produced by `format_type`,\n * e.g. `bigint`, `integer`, `character varying(32)`, `text[]`, `jsonb`).\n * No caching here — see {@link getColumnTypes} for the cached path.\n */\n async loadColumnTypesFromPg(table: string): Promise<Map<string, string>> {\n const result = await this.query<{ column_name: string; pg_type: string }>(\n `SELECT a.attname AS column_name, format_type(a.atttypid, a.atttypmod) AS pg_type\n FROM pg_attribute a\n WHERE a.attrelid = $1::regclass AND a.attnum > 0 AND NOT a.attisdropped\n ORDER BY a.attnum`,\n [table],\n );\n // PG folds unquoted identifiers to lowercase on the server side, so\n // pg_attribute.attname comes back lowercase. JS-side column keys\n // (`entry.data`) often arrive in camelCase from the schema layer; we\n // lookup via lowercase to bridge the two cases without making callers\n // worry about it.\n const out = new Map<string, string>();\n for (const row of result.rows) out.set(row.column_name.toLowerCase(), row.pg_type);\n return out;\n }\n\n /**\n * Synchronous column-type lookup. The apply path calls this on every\n * batched write, so it can't await — populate the cache via\n * {@link bootstrapColumnTypes} at server start. Throws if `table` is\n * missing (programmer error / bootstrap skipped).\n */\n getColumnTypes(table: string): Map<string, string> | null {\n const hit = this.columnTypes.get(table);\n if (!hit) {\n this.logger.warn({ table }, \"PgDatabase: no cached column types fallback to non-batched writes\");\n return null;\n }\n return hit;\n }\n\n /**\n * Eagerly load column types into the in-memory cache. With a Redis\n * client supplied, attempts the cache key first and falls through to\n * Postgres on miss (writing the result back to Redis). This is the\n * \"one server queries PG, the rest read from Redis\" pattern for cold\n * starts in a multi-instance deploy. Without Redis, always queries PG.\n *\n * Pass `tables` to limit the load to a specific list; otherwise every\n * user table in the connected database is loaded.\n *\n * The Redis cache key should encode whatever invalidates types in your\n * environment (typically a schema version / deploy version). The\n * subscriber in supalive-server.ts is expected to publish a reload\n * signal after migrations and invoke {@link invalidateColumnTypes}.\n */\n async bootstrapColumnTypes(opts: {\n redis?: CacheLayer;\n cacheKey: string;\n tables?: string[];\n }): Promise<void> {\n this.invalidateColumnTypes();\n\n const { redis, cacheKey, tables } = opts;\n\n // Redis hit path: deserialize the full table → column → pgType map\n // and populate in one shot, skipping any pg_attribute round-trips.\n if (redis) {\n const cached = await redis.getCachedTableColumnTypes(cacheKey);\n if (cached) {\n for (const [table, cols] of Object.entries(cached)) {\n this.columnTypes.set(table, new Map(Object.entries(cols)));\n }\n return;\n }\n }\n\n // Cache miss (or no Redis): query Postgres for the listed tables\n // (or enumerate all user tables) and populate.\n const names = tables ?? await this.listUserTables();\n for (const t of names) {\n if (this.columnTypes.has(t)) continue;\n\n const fresh = await this.loadColumnTypesFromPg(t);\n this.columnTypes.set(t, fresh);\n }\n\n // Write back to Redis so subsequent server instances skip the PG hop.\n if (redis) {\n const dump: Record<string, Record<string, string>> = {};\n for (const [table, cols] of this.columnTypes) {\n dump[table] = Object.fromEntries([...cols.entries()].sort());\n }\n await redis.setCachedTableColumnsTypes(cacheKey, dump);\n }\n }\n\n /**\n * Invalidate cached types (and dependent SQL) for `table`, or the entire\n * cache if `table` is omitted. The Redis-pubsub reload signal in\n * supalive-server.ts is expected to call this on schema changes.\n */\n private invalidateColumnTypes(table?: string): void {\n if (table) {\n this.columnTypes.delete(table);\n for (const k of [...this.sqlCache.keys()]) {\n if (k.includes(`:${table}:`) || k === `d:${table}`) this.sqlCache.delete(k);\n }\n } else {\n this.columnTypes.clear();\n this.sqlCache.clear();\n }\n }\n\n /** Enumerate the user-defined tables in the connected database — used\n * by bootstrapColumnTypes() when no explicit list is provided. */\n private async listUserTables(): Promise<string[]> {\n const res = await this.query<{ relname: string }>(\n `SELECT c.relname FROM pg_class c\n JOIN pg_namespace n ON n.oid = c.relnamespace\n WHERE c.relkind = 'r' AND n.nspname = ANY (current_schemas(false))\n AND c.relname NOT IN ('commit_logs','metadata')`,\n );\n return res.rows.map((r) => r.relname);\n }\n\n async getCoreVersion(): Promise<bigint> {\n const result = await this.query<{ meta_value: string | number | bigint }>(\n \"SELECT meta_value FROM metadata WHERE meta_key = 'core_version'\",\n );\n return BigInt(result.rows[0]?.meta_value ?? 0);\n }\n\n // Non-table core bootstrap applied per version step. Tables live in the\n // generated schema (see coreTablesSql); this covers the OCC timestamp\n // sequence and the metadata seed rows.\n coreMigrationStatements(toVersion: bigint): string[] {\n if (toVersion === 1n) {\n return [\n `CREATE SEQUENCE IF NOT EXISTS global_commit_ts START 1 INCREMENT 1 NO CYCLE;`,\n `INSERT INTO metadata (meta_key, meta_value) VALUES ('latest_committed_ts', 0) ON CONFLICT (meta_key) DO NOTHING;`,\n `INSERT INTO metadata (meta_key, meta_value) VALUES ('min_retained_ts', 0) ON CONFLICT (meta_key) DO NOTHING;`,\n ];\n }\n return [];\n }\n\n async withCoreInitLock(fn: (ctx: CoreInitLockCtx) => Promise<void>): Promise<void> {\n const client = await this.pool.connect();\n try {\n await client.query(\"BEGIN\");\n // Transaction-level advisory lock: auto-released on COMMIT/ROLLBACK, so\n // no leak even if fn throws. Serializes core init across processes.\n await client.query(\"SELECT pg_advisory_xact_lock($1)\", [CORE_INIT_LOCK_KEY]);\n\n const ctx: CoreInitLockCtx = {\n exec: async (sql, params = []) => {\n const r = await client.query(sql, params);\n return { rows: r.rows, rowCount: r.rowCount };\n },\n getVersion: async () => {\n const r = await client.query<{ meta_value: string | number | bigint }>(\n \"SELECT meta_value FROM metadata WHERE meta_key = 'core_version'\",\n );\n return BigInt(r.rows[0]?.meta_value ?? 0);\n },\n setVersion: async (version) => {\n await client.query(\n `INSERT INTO metadata (meta_key, meta_value) VALUES ('core_version', $1)\n ON CONFLICT (meta_key) DO UPDATE SET meta_value = EXCLUDED.meta_value`,\n [version.toString()],\n );\n },\n };\n\n await fn(ctx);\n await client.query(\"COMMIT\");\n } catch (err) {\n await client.query(\"ROLLBACK\").catch(() => { });\n throw translatePgError(err);\n } finally {\n client.release();\n }\n }\n\n async query<T = any>(sql: string, params: unknown[] = []): Promise<DbQueryResult<T>> {\n const client = await this.pool.connect();\n try {\n const result = await client.query(sql, params);\n return {\n rows: result.rows as T[],\n rowCount: result.rowCount,\n };\n } catch (err) {\n throw translatePgError(err);\n } finally {\n client.release();\n }\n }\n\n async getClient(): Promise<PooledClient> {\n return await this.pool.connect() as PooledClient;\n }\n\n async getTransactionClient(): Promise<TxDatabase> {\n const client = await this.pool.connect();\n const tx = new PgTxDatabase(this.logger, this.config, this.pool, client);\n // Tx clients are short-lived. Share the parent's caches by reference so\n // (a) types loaded once at startup are visible inside transactions, and\n // (b) the SQL cache grows across the process rather than per-tx.\n tx.adoptCaches(this.columnTypes, this.sqlCache);\n return tx;\n }\n\n /** Internal: replace this instance's caches with shared references from\n * a parent. Used by PgDatabase.getTransactionClient. */\n adoptCaches(\n columnTypes: Map<string, Map<string, string>>,\n sqlCache: Map<string, string>,\n ): void {\n this.columnTypes = columnTypes;\n this.sqlCache = sqlCache;\n }\n\n async getLatestSnapshotTimestamp(): Promise<bigint> {\n const result = await this.query<{ meta_value: string | number | bigint }>(\"SELECT meta_value FROM metadata WHERE meta_key = 'latest_committed_ts'\");\n return BigInt(result.rows[0]?.meta_value ?? 0);\n }\n\n async updateLatestSnapshotTimestamp(commitTs: bigint): Promise<void> {\n await this.query(\n \"UPDATE metadata SET meta_value = $1 WHERE meta_key = 'latest_committed_ts' AND meta_value < $1\",\n [commitTs],\n );\n }\n\n async getMinSnapshotTimestamp(): Promise<bigint> {\n const result = await this.query<{ meta_value: string | number | bigint }>(\n \"SELECT meta_value FROM metadata WHERE meta_key = 'min_retained_ts'\",\n );\n return BigInt(result.rows[0]?.meta_value ?? 0);\n }\n\n async updateMinSnapshotTimestamp(ts: bigint): Promise<void> {\n await this.query(\n \"UPDATE metadata SET meta_value = $1 WHERE meta_key = 'min_retained_ts' AND meta_value < $1\",\n [ts],\n );\n }\n\n async getNextTimestamp(): Promise<bigint> {\n const result = await this.query<{ nextval: string | number | bigint }>(\n \"SELECT nextval('global_commit_ts') as nextval\"\n );\n return BigInt(result.rows[0]?.nextval ?? \"0\");\n }\n\n // Runs on the pool, not the tx client — intentionally. This keeps the\n // transaction window short, but it means `prevData` is not snapshot-\n // consistent with the eventual commitTs (a peer may have moved the row\n // between beginTs and this SELECT). That's safe because:\n // 1. The per-row CAS in pgApplyWrites is the real snapshot fence. If a\n // peer committed in our staleness window, the CAS sees a moved\n // commit_ts and throws OccConflictError → retry.\n // 2. The only window where CAS passes with \"stale\" prevData is when\n // the current row at our SELECT moment matches `expectedCommitTs`;\n // by construction nobody committed between our captured ts and now,\n // so prevData IS consistent with the ts we're CAS-ing against.\n // 3. The downstream consumer (overlap-checker.checkRowWriteAffectsRange)\n // is conservative on missing/odd prevData — \"unknown\" verdicts still\n // invalidate, so the worst case here is a spurious invalidation,\n // never a missed one.\n // Locked in by postgres.attach-prev-data.test.ts.\n async attachPrevDataToWriteSet(writeSet: WriteEntry[], readSet: ReadEntry[]): Promise<void> {\n // Index prior point reads by (table, id) so we can carry the\n // read-time commit_ts onto matching writes. Iterate in reverse so the\n // last read wins (handles handlers that read the same row twice).\n const readTsByKey = new Map<string, bigint | null>();\n for (let i = readSet.length - 1; i >= 0; i--) {\n const r = readSet[i];\n if (r.kind !== \"point\" || r.expectedCommitTs === undefined) continue;\n\n const key = `${r.table} ${r.id}`;\n if (!readTsByKey.has(key)) readTsByKey.set(key, r.expectedCommitTs);\n }\n\n const byTable = new Map<string, WriteEntry[]>();\n for (const entry of writeSet) {\n if (entry.op !== \"update\" && entry.op !== \"delete\") continue;\n\n const bucket = byTable.get(entry.table);\n if (bucket) bucket.push(entry);\n else byTable.set(entry.table, [entry]);\n }\n if (byTable.size === 0) return;\n\n for (const [table, entries] of byTable) {\n const ids = entries.map((e) => e.id);\n const placeholders = ids.map((_, i) => `$${i + 1}`).join(\", \");\n // No FOR UPDATE — the per-row CAS on the subsequent UPDATE/DELETE is\n // the fence. If a peer mutated the row since our read, the CAS will\n // see a stale expected commit_ts and throw OCC.\n const sql = `SELECT * FROM ${table} WHERE id IN (${placeholders})`;\n const result = await this.query<Record<string, unknown>>(sql, ids);\n\n const byId = new Map<string, Record<string, unknown>>();\n for (const row of result.rows) {\n byId.set(String(row.id), row);\n }\n for (const entry of entries) {\n const row = byId.get(entry.id);\n const key = `${entry.table} ${entry.id}`;\n const priorReadTs = readTsByKey.get(key);\n\n if (row) {\n entry.prevData = row;\n // Prefer the read-time ts so read-then-update patterns get\n // beginTs-level isolation; fall back to current row ts for\n // blind writes (no prior read).\n entry.expectedCommitTs = priorReadTs !== undefined\n ? priorReadTs\n : BigInt(row.commit_ts as string | number | bigint);\n } else if (priorReadTs !== undefined) {\n // Row gone now, but we had read it earlier: carry the read ts —\n // the CAS will then mismatch (row deleted) and throw OCC.\n entry.expectedCommitTs = priorReadTs;\n }\n // else: neither a prior read nor a current row → leave undefined\n // so CAS misses and surfaces OCC.\n }\n }\n }\n\n // Prepare BEFORE the conflict scan: each write is a CAS against the row's\n // commit_ts, so any concurrent peer that touched the row produces a\n // 0-row-affected UPDATE/DELETE → OccConflictError. Inserts surface as\n // PK violations, also translated to OCC.\n async prepareCommitWrites(\n readSet: ReadEntry[],\n writeSet: WriteEntry[],\n commitTs: LazyCommitTsParam,\n ): Promise<PreparedQueries> {\n\n const result: PreparedQuery[] = [];\n\n await this.pgPrepareBatchWrites(result, writeSet, commitTs);\n await this.pgPrepareCommitLogs(result, writeSet, commitTs);\n\n const hasRangeRead = readSet.some(r => r.kind === \"range\");\n if (!hasRangeRead) {\n const validateReads = this.pgPrepareValidatePointReadsByCommitTs(readSet, writeSet);\n return { commits: result, validateReadPoints: validateReads, hasRangeRead: false };\n }\n\n // has atleast one range read so use scan, prepare data\n const tableIds = [...new Set(readSet.map(r => r.tableId))];\n const rawReadSet = mapReadSetToRaw(readSet);\n\n return { commits: result, hasRangeRead: true, tableIds: tableIds, rawReadSet: rawReadSet };\n };\n\n private async pgPrepareBatchWrites(\n result: PreparedQuery[],\n writeSet: WriteEntry[],\n commitTs: LazyCommitTsParam,\n ) {\n let i = 0;\n let counter = 0;\n while (i < writeSet.length) {\n counter++;\n const { table, op } = writeSet[i];\n let j = i + 1;\n while (j < writeSet.length && writeSet[j].table === table && writeSet[j].op === op) j++;\n\n const batch = writeSet.slice(i, j);\n if (op === \"insert\") await this.pgPrepareInsertBatch(result, table, batch, commitTs);\n else if (op === \"update\") await this.pgPrepareUpdateBatch(result, table, batch, commitTs);\n else await this.pgPrepareDeleteBatch(result, table, batch);\n i = j;\n\n if (counter % 50 == 0)\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n }\n\n // N=1 INSERT fast-path: identical SQL shape to the original per-row\n // code, no unnest overhead. PG infers param types from the column\n // context directly, so we don't need pg_attribute either.\n private pgPrepareInsertSingle(\n result: PreparedQuery[],\n table: string,\n entry: WriteEntry,\n commitTs: LazyCommitTsParam,\n ) {\n const data = { ...(entry.data ?? {}), commit_ts: commitTs } as Record<string, unknown>;\n const cols = Object.keys(data);\n const placeholders = cols.map((_, i) => `$${i + 1}`);\n result.push({\n sql: `INSERT INTO ${table} (${cols.join(\", \")}) VALUES (${placeholders.join(\", \")})`,\n params: Object.values(data),\n operation: \"insertSingle\",\n table: table,\n entryId: entry.id,\n })\n }\n\n private async pgPrepareInsertBatch(\n result: PreparedQuery[],\n table: string,\n entries: WriteEntry[],\n commitTs: LazyCommitTsParam,\n ) {\n if (entries.length === 0) return;\n\n const types = this.getColumnTypes(table);\n if (!types) {\n this.logger.warn({ table }, \"No column types found, falling back to non-batched writes for insert\");\n let counter = 0;\n for (const entry of entries) {\n counter++;\n this.pgPrepareInsertSingle(result, table, entry, commitTs);\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n }\n return;\n }\n\n // Sub-bucket by sorted column signature: writes with different optional\n // columns can't share a statement.\n const groups = new Map<string, { cols: string[]; rows: WriteEntry[] }>();\n for (const entry of entries) {\n const cols = [...Object.keys(entry.data ?? {}), 'commit_ts'].sort();\n const key = cols.join(\"|\");\n let g = groups.get(key);\n if (!g) { g = { cols, rows: [] }; groups.set(key, g); }\n g.rows.push(entry);\n }\n\n let counter = 0;\n for (const { cols, rows } of groups.values()) {\n counter++;\n\n const sql = this.buildOrGetInsertSql(table, types, cols);\n // Params layout: one carrier array per column, each of length N.\n const params: unknown[][] = cols.map(() => new Array(rows.length));\n for (let r = 0; r < rows.length; r++) {\n const data = { ...(rows[r].data ?? {}), commit_ts: commitTs } as Record<string, unknown>;\n for (let c = 0; c < cols.length; c++) {\n const pgType = types.get(cols[c].toLowerCase()) ?? \"text\";\n params[c][r] = encodeForCarrier(data[cols[c]], pgType);\n }\n }\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n\n result.push({\n sql: sql,\n params: params,\n operation: \"insertBatch\",\n table: table,\n })\n }\n }\n\n // N=1 UPDATE fast-path: same shape as the original per-row CAS.\n private pgPrepareUpdateSingle(\n result: PreparedQuery[],\n table: string,\n entry: WriteEntry,\n commitTs: LazyCommitTsParam,\n ) {\n const data = { ...(entry.data ?? {}), commit_ts: commitTs } as Record<string, unknown>;\n const cols = Object.keys(data);\n const sets = cols.map((col, i) => `${col} = $${i + 1}`);\n const values = Object.values(data);\n const idP = `$${values.length + 1}`;\n const tsP = `$${values.length + 2}`;\n const expected = entry.expectedCommitTs ?? -1n;\n\n result.push({\n sql: `UPDATE ${table} SET ${sets.join(\", \")} WHERE id = ${idP} AND commit_ts = ${tsP}`,\n params: [...values, entry.id, expected],\n operation: \"updateSingle\",\n table: table,\n entryId: entry.id,\n expectedTs: expected,\n })\n }\n\n private async pgPrepareUpdateBatch(\n result: PreparedQuery[],\n table: string,\n entries: WriteEntry[],\n commitTs: LazyCommitTsParam,\n ) {\n if (entries.length === 0) return;\n\n const types = this.getColumnTypes(table);\n if (!types) {\n this.logger.warn({ table }, \"No column types found, falling back to non-batched writes for update\");\n\n let counter = 0;\n for (const entry of entries) {\n counter++;\n this.pgPrepareUpdateSingle(result, table, entry, commitTs);\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n }\n return;\n }\n\n const groups = new Map<string, { cols: string[]; rows: WriteEntry[] }>();\n for (const entry of entries) {\n const cols = [...Object.keys(entry.data ?? {}), 'commit_ts'].sort();\n const key = cols.join(\"|\");\n let g = groups.get(key);\n if (!g) { g = { cols, rows: [] }; groups.set(key, g); }\n g.rows.push(entry);\n }\n\n let counter = 0;\n for (const { cols, rows } of groups.values()) {\n counter++;\n\n const sql = this.buildOrGetUpdateSql(table, types, cols);\n const idType = types.get(\"id\") ?? \"text\";\n const idArr: unknown[] = new Array(rows.length);\n const expArr: unknown[] = new Array(rows.length);\n const colArrs: unknown[][] = cols.map(() => new Array(rows.length));\n for (let r = 0; r < rows.length; r++) {\n const entry = rows[r];\n const data = { ...(entry.data ?? {}), commit_ts: commitTs } as Record<string, unknown>;\n const expected = entry.expectedCommitTs ?? -1n;\n idArr[r] = encodeForCarrier(entry.id, idType);\n expArr[r] = encodeForCarrier(expected, \"bigint\");\n for (let c = 0; c < cols.length; c++) {\n const pgType = types.get(cols[c].toLowerCase()) ?? \"text\";\n colArrs[c][r] = encodeForCarrier(data[cols[c]], pgType);\n }\n }\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n\n const params: unknown[][] = [idArr, expArr, ...colArrs];\n result.push({\n sql: sql,\n params: params,\n operation: \"updateBatch\",\n table: table,\n entries: rows,\n })\n }\n }\n\n // N=1 DELETE fast-path: original per-row CAS shape.\n private pgPrepareDeleteSingle(\n result: PreparedQuery[],\n table: string,\n entry: WriteEntry,\n ) {\n const expected = entry.expectedCommitTs ?? -1n;\n result.push({\n sql: `DELETE FROM ${table} WHERE id = $1 AND commit_ts = $2`,\n params: [entry.id, expected],\n operation: \"deleteSingle\",\n table: table,\n entryId: entry.id,\n expectedTs: expected,\n });\n }\n\n private async pgPrepareDeleteBatch(\n result: PreparedQuery[],\n table: string,\n entries: WriteEntry[],\n ) {\n if (entries.length === 0) return;\n\n const types = this.getColumnTypes(table);\n if (!types) {\n this.logger.warn({ table }, \"No column types found, falling back to non-batched writes for delete\");\n\n let counter = 0;\n for (const entry of entries) {\n counter++;\n this.pgPrepareDeleteSingle(result, table, entry);\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n }\n return;\n }\n\n const sql = this.buildOrGetDeleteSql(table, types);\n const idType = types.get(\"id\") ?? \"text\";\n const idArr: unknown[] = new Array(entries.length);\n const expArr: unknown[] = new Array(entries.length);\n\n let counter = 0;\n for (let i = 0; i < entries.length; i++) {\n counter++;\n const entry = entries[i];\n const expected = entry.expectedCommitTs ?? -1n;\n idArr[i] = encodeForCarrier(entry.id, idType);\n expArr[i] = encodeForCarrier(expected, \"bigint\");\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n }\n result.push({\n sql: sql,\n params: [idArr, expArr],\n operation: \"deleteBatch\",\n table: table,\n entries: entries,\n });\n }\n\n private buildOrGetInsertSql(table: string, types: Map<string, string>, cols: string[]): string {\n const key = `i:${table}:${cols.join(\",\")}`;\n let sql = this.sqlCache.get(key);\n if (sql) return sql;\n\n const placeholders = cols.map((c, i) => {\n const pgType = types.get(c.toLowerCase()) ?? \"text\";\n return `$${i + 1}::${pgCarrierType(pgType)}`;\n });\n const aliases = cols.map((_, i) => `c${i}`);\n const selectExprs = cols.map((c, i) => {\n const pgType = types.get(c.toLowerCase()) ?? \"text\";\n return pgSelectExpr(aliases[i], pgType);\n });\n sql = `INSERT INTO ${table} (${cols.join(\", \")}) ` +\n `SELECT ${selectExprs.join(\", \")} ` +\n `FROM unnest(${placeholders.join(\", \")}) AS u(${aliases.join(\", \")})`;\n this.sqlCache.set(key, sql);\n return sql;\n }\n\n private buildOrGetUpdateSql(table: string, types: Map<string, string>, cols: string[]): string {\n const key = `u:${table}:${cols.join(\",\")}`;\n let sql = this.sqlCache.get(key);\n if (sql) return sql;\n\n const idType = types.get(\"id\") ?? \"text\";\n const idCarrier = `$1::${pgCarrierType(idType)}`;\n const expCarrier = `$2::bigint[]`;\n const dataCarriers = cols.map((c, i) => {\n const pgType = types.get(c.toLowerCase()) ?? \"text\";\n return `$${i + 3}::${pgCarrierType(pgType)}`;\n });\n const aliases = [\"id_c\", \"exp_c\", ...cols.map((_, i) => `c${i}`)];\n const setClause = cols\n .map((c, i) => {\n const pgType = types.get(c.toLowerCase()) ?? \"text\";\n return `${c} = ${pgSelectExpr(`u.${aliases[i + 2]}`, pgType)}`;\n })\n .join(\", \");\n sql =\n `UPDATE ${table} AS t SET ${setClause} ` +\n `FROM unnest(${idCarrier}, ${expCarrier}, ${dataCarriers.join(\", \")}) AS u(${aliases.join(\", \")}) ` +\n `WHERE t.id = u.id_c AND t.commit_ts = u.exp_c ` +\n `RETURNING t.id AS id`;\n this.sqlCache.set(key, sql);\n return sql;\n }\n\n private buildOrGetDeleteSql(table: string, types: Map<string, string>): string {\n const key = `d:${table}`;\n let sql = this.sqlCache.get(key);\n if (sql) return sql;\n const idType = types.get(\"id\") ?? \"text\";\n sql =\n `DELETE FROM ${table} AS t ` +\n `USING unnest($1::${pgCarrierType(idType)}, $2::bigint[]) AS u(id_c, exp_c) ` +\n `WHERE t.id = u.id_c AND t.commit_ts = u.exp_c ` +\n `RETURNING t.id AS id`;\n this.sqlCache.set(key, sql);\n return sql;\n }\n\n private async pgPrepareCommitLogs(\n result: PreparedQuery[],\n writeEntries: WriteEntry[],\n commitTs: LazyCommitTsParam,\n ) {\n if (writeEntries.length === 0) return;\n\n // unnest with column-typed arrays: 4 placeholders regardless of N\n // (vs 4N for multi-row VALUES). All four columns have fixed driver-side\n // types so no per-table metadata lookup is needed.\n const ids: Buffer[] = new Array(writeEntries.length);\n const tss: LazyCommitTsParam[] = new Array(writeEntries.length);\n const tableIds: Buffer[] = new Array(writeEntries.length);\n const datas: Buffer[] = new Array(writeEntries.length);\n\n let counter = 0;\n for (let i = 0; i < writeEntries.length; i++) {\n counter++;\n\n const entry = writeEntries[i];\n ids[i] = toBufferView(normalizeIdToBytes(entry.id));\n tss[i] = commitTs;\n tableIds[i] = toBufferView(entry.tableId);\n datas[i] = toBufferView(utf8Encode(supaliveStringify(entry)));\n\n if (counter % 50 == 0) {\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n }\n\n result.push({\n sql: `INSERT INTO commit_logs (id, ts, table_id, data) ` +\n `SELECT * FROM unnest($1::bytea[], $2::bigint[], $3::bytea[], $4::bytea[])`,\n params: [ids, tss, tableIds, datas],\n table: 'commit_logs',\n operation: 'commit_logs',\n })\n }\n\n /**\n * Point-only OCC check. For each genuine point read, compare the row's\n * current commit_ts against the value captured at read time. A `null`\n * expectedCommitTs means \"row didn't exist when we read\"; any row found\n * now is a conflict. Reads whose row is being written in this same txn\n * are skipped — the CAS UPDATE/DELETE already validated those.\n */\n private pgPrepareValidatePointReadsByCommitTs(\n readSet: ReadEntry[],\n writeSet: WriteEntry[],\n ): PreparedQuery[] {\n const result: PreparedQuery[] = [];\n\n // Skip reads whose row is being mutated in this same tx — CAS already\n // fenced them. We dedupe per (table, id) so duplicate reads of the same\n // row don't cause extra fetches.\n const writeKeys = new Set<string>();\n for (const w of writeSet) {\n writeKeys.add(`${w.table} ${w.id}`);\n }\n\n const byTable = new Map<string, PendingPointEntry[]>();\n const seen = new Set<string>();\n\n for (const entry of readSet) {\n if (entry.kind !== \"point\") continue;\n\n const key = `${entry.table} ${entry.id}`;\n if (writeKeys.has(key) || seen.has(key)) continue;\n\n seen.add(key);\n // expectedCommitTs === undefined → no commit_ts captured at read time\n // (synthetic or pre-migration). Skip — we cannot CAS-validate it. This\n // path should only fire when callers construct PointReads externally.\n if (entry.expectedCommitTs === undefined) continue;\n\n const bucket = byTable.get(entry.table);\n if (bucket) bucket.push({ entry, key });\n else byTable.set(entry.table, [{ entry, key }]);\n }\n\n for (const [table, pendings] of byTable) {\n const ids = pendings.map((p) => p.entry.id);\n const placeholders = ids.map((_, i) => `$${i + 1}`).join(\", \");\n\n result.push({\n sql: `SELECT id, commit_ts FROM ${table} WHERE id IN (${placeholders})`,\n params: ids,\n table: table,\n operation: \"pointReadValidation\",\n pendingsEntry: pendings,\n });\n }\n\n return result;\n }\n\n async commitWrites(\n beginTs: bigint,\n queries: PreparedQueries,\n commitTs: bigint,\n ): Promise<{ success: boolean }> {\n await this.pgApplyWrites(queries.commits);\n\n // Fast path: when the readSet has no range reads, we don't need a\n // commit-log scan at all — point reads validate via per-row commit_ts,\n // and writes already self-validated via CAS above. This is the dominant\n // shape (most mutations target known ids) and eliminates the heaviest\n // OCC cost in the previous design.\n if (!queries.hasRangeRead) {\n if ((queries.validateReadPoints?.length ?? 0) > 0) {\n await this.validatePointReadsByCommitTs(queries.validateReadPoints ?? []);\n }\n return { success: true };\n }\n\n // Slow path: at least one range read present. Fall back to the\n // commit-log scan so phantom inserts and predicate transitions-in are\n // still caught. Point reads in the same set are covered by the same\n // scan, so no separate validation is needed.\n const logs = await this.getCommitLogsSinceTs(beginTs, commitTs, queries.tableIds ?? []);\n const hasConflict = checkLogsAffectReadSet(logs, queries.rawReadSet ?? []);\n if (hasConflict) {\n throw new OccConflictError(\n `Conflict detected: overlapping commit logs since ${beginTs}`,\n { logs }\n );\n }\n\n return { success: true };\n };\n\n // Walks the writeSet in order and coalesces consecutive entries with the\n // same (table, op) into one batched statement. Order is preserved across\n // batch boundaries so replace-patterns (delete-then-insert of the same\n // id) behave identically to the per-row code path. Single-row batches\n // take a direct INSERT/UPDATE/DELETE fast-path to avoid the unnest+join\n // overhead, which matters under high contention.\n private async pgApplyWrites(result: PreparedQuery[]): Promise<void> {\n for (const q of result) {\n switch (q.operation) {\n case 'insertSingle': {\n try {\n await this.query(q.sql, q.params);\n } catch (err) {\n if (err && typeof err === \"object\" && (err as { code?: string }).code === \"23505\") {\n throw new OccConflictError(\n `Conflict: insert into ${q.table}/${q.entryId} hit duplicate key`,\n err,\n );\n }\n throw err;\n }\n break;\n }\n case 'insertBatch': {\n try {\n await this.query(q.sql, q.params);\n } catch (err) {\n if (err && typeof err === \"object\" && (err as { code?: string }).code === \"23505\") {\n const detail = (err as { detail?: string }).detail;\n const idMatch = detail?.match(/Key \\([^)]+\\)=\\(([^)]+)\\)/);\n const failedId = idMatch?.[1];\n throw new OccConflictError(\n failedId !== undefined\n ? `Conflict: insert into ${q.table}/${failedId} hit duplicate key`\n : `Conflict: batch insert into ${q.table} hit duplicate key`,\n err,\n );\n }\n throw err;\n }\n break;\n }\n case 'updateSingle': {\n const result = await this.query(q.sql, q.params);\n if ((result.rowCount ?? 0) === 0) {\n throw new OccConflictError(\n `Conflict: CAS update of ${q.table}/${q.entryId} (expected commit_ts=${q.expectedTs}) matched no rows`,\n { table: q.table, id: q.entryId, expectedTs: q.expectedTs },\n );\n }\n break;\n }\n case 'updateBatch': {\n const result = await this.query<{ id: string }>(q.sql, q.params);\n\n const returned = new Set<string>();\n for (const r of result.rows) {\n returned.add(r.id);\n }\n for (const entry of q.entries!) {\n if (!returned.has(entry.id)) {\n const expected = entry.expectedCommitTs ?? -1n;\n throw new OccConflictError(\n `Conflict: CAS update of ${q.table}/${entry.id} (expected commit_ts=${expected}) matched no rows`,\n { table: q.table, id: q.entryId, expectedTs: q.expectedTs },\n );\n }\n }\n break;\n }\n case 'deleteSingle': {\n const result = await this.query(q.sql, q.params);\n if ((result.rowCount ?? 0) === 0) {\n throw new OccConflictError(\n `Conflict: CAS delete of ${q.table}/${q.entryId} (expected commit_ts=${q.expectedTs}) matched no rows`,\n { table: q.table, id: q.entryId, expectedTs: q.expectedTs },\n );\n }\n break;\n }\n case 'deleteBatch': {\n const result = await this.query<{ id: string }>(q.sql, q.params);\n const returned = new Set<string>();\n for (const r of result.rows) returned.add(r.id);\n for (const entry of q.entries!) {\n if (!returned.has(entry.id)) {\n const expected = entry.expectedCommitTs ?? -1n;\n throw new OccConflictError(\n `Conflict: CAS delete of ${q.table}/${entry.id} (expected commit_ts=${expected}) matched no rows`,\n { table: q.table, id: entry.id, expected },\n );\n }\n }\n break;\n }\n case 'commit_logs': {\n await this.query(q.sql, q.params);\n break;\n }\n default:\n throw new Error(\"Unhandled Postgres Operation: \" + q.operation);\n\n }\n }\n }\n\n /**\n * Point-only OCC check. For each genuine point read, compare the row's\n * current commit_ts against the value captured at read time. A `null`\n * expectedCommitTs means \"row didn't exist when we read\"; any row found\n * now is a conflict. Reads whose row is being written in this same txn\n * are skipped — the CAS UPDATE/DELETE already validated those.\n */\n private async validatePointReadsByCommitTs(\n queries: PreparedQuery[],\n ): Promise<void> {\n\n for (const q of queries) {\n const result = await this.query<{ id: string; commit_ts: string | number | bigint }>(q.sql, q.params);\n\n const currentById = new Map<string, bigint>();\n for (const row of result.rows) {\n currentById.set(row.id, BigInt(row.commit_ts));\n }\n\n for (const { entry } of (q.pendingsEntry ?? [])) {\n const current = currentById.get(entry.id);\n const expected = entry.expectedCommitTs;\n\n if (expected === null) {\n // We read \"no row\"; conflict if a row now exists.\n if (current !== undefined) {\n throw new OccConflictError(\n `Conflict: row ${entry.table}/${entry.id} was inserted concurrently`,\n { table: entry.table, id: entry.id }\n );\n }\n } else {\n if (current === undefined) {\n throw new OccConflictError(\n `Conflict: row ${entry.table}/${entry.id} was deleted concurrently`,\n { table: entry.table, id: entry.id, expected }\n );\n }\n if (current !== expected) {\n throw new OccConflictError(\n `Conflict: row ${entry.table}/${entry.id} changed from ts=${expected} to ts=${current}`,\n { table: entry.table, id: entry.id, expected, current }\n );\n }\n }\n }\n }\n }\n\n async pruneCommitLogsBefore(ts: bigint): Promise<bigint> {\n const result = await this.query(\n `DELETE FROM commit_logs WHERE ts < $1`,\n [ts]\n );\n return BigInt(result.rowCount ?? 0);\n }\n\n async getMinCommitLogTs(): Promise<bigint | null> {\n const result = await this.query<{ min: string | number | bigint | null }>(\n `SELECT min(ts) AS min FROM commit_logs`,\n );\n const min = result.rows[0]?.min;\n return min === null || min === undefined ? null : BigInt(min);\n }\n\n async getCommitLogsBetweenTs(beginTs: bigint, endTs: bigint, tableIds: Uint8Array[]): Promise<CommitLogEntry[]> {\n if (tableIds.length === 0) return [];\n\n const placeholders = tableIds.map((_, i) => `$${i + 3}`).join(\", \");\n const sql = `SELECT id, ts, table_id, data FROM commit_logs WHERE ts >= $1 AND ts < $2 AND table_id IN (${placeholders})`;\n\n const result = await this.query<{ id: unknown; ts: string | number | bigint; table_id: unknown; data: unknown }>(\n sql,\n [beginTs, endTs, ...tableIds.map(toBufferView)]\n );\n\n return result.rows.map((row) => ({\n id: normalizeToBytes(row.id),\n ts: BigInt(row.ts),\n tableId: normalizeToBytes(row.table_id),\n data: normalizeToBytes(row.data),\n }));\n }\n\n async getCommitLogsSinceTs(sinceTs: bigint, excludeTs: bigint, tableIds: Uint8Array[]): Promise<CommitLogEntry[]> {\n if (tableIds.length === 0) return [];\n\n const placeholders = tableIds.map((_, i) => `$${i + 3}`).join(\", \");\n const sql = `SELECT id, ts, table_id, data FROM commit_logs WHERE ts >= $1 AND ts <> $2 AND table_id IN (${placeholders})`;\n\n const result = await this.query<{ id: unknown; ts: string | number | bigint; table_id: unknown; data: unknown }>(\n sql,\n [sinceTs, excludeTs, ...tableIds.map(toBufferView)]\n );\n\n return result.rows.map((row) => ({\n id: normalizeToBytes(row.id),\n ts: BigInt(row.ts),\n tableId: normalizeToBytes(row.table_id),\n data: normalizeToBytes(row.data),\n }));\n }\n\n async close(): Promise<void> {\n await this.pool.end();\n }\n}\n\nexport class PgTxDatabase extends PgDatabase {\n constructor(logger: Logger, config: PoolConfig, pool: Pool, client: PoolClient) {\n super(logger, config, pool);\n this.client = client;\n }\n\n private client: PoolClient;\n\n override async query<T = any>(sql: string, params: unknown[] = []): Promise<DbQueryResult<T>> {\n try {\n const result = await this.client.query(sql, params);\n return {\n rows: result.rows as T[],\n rowCount: result.rowCount,\n };\n } catch (err) {\n throw translatePgError(err);\n }\n }\n\n async begin(): Promise<void> {\n await this.client.query(\"BEGIN\");\n }\n\n async commit(): Promise<void> {\n await this.client.query(\"COMMIT\");\n }\n\n async rollback(): Promise<void> {\n await this.client.query(\"ROLLBACK\");\n }\n\n release(): void {\n this.client.release();\n }\n}\n\n/**\n * Returns the unnest carrier array type for a column of `pgType`.\n * Scalars ride as their own array type so PG infers cleanly without an\n * extra cast on the SELECT/SET side. Array and jsonb columns can't ride\n * as their own array type (ragged 2D arrays aren't permitted, and the\n * driver can't tag jsonb sub-elements correctly inside a typed array),\n * so they get the universal `text[]` carrier with an explicit cast in\n * the SELECT/SET clause. Bytea rides natively as `bytea[]`.\n */\nfunction pgCarrierType(pgType: string): string {\n const base = pgType.trim().toLowerCase();\n if (base === \"bytea\") return \"bytea[]\";\n if (base === \"jsonb\" || base === \"json\") return \"text[]\";\n if (base.endsWith(\"[]\")) return \"text[]\";\n return `${pgType}[]`;\n}\n\n/** SELECT/SET expression for an unnest alias of a column with `pgType`.\n * When the carrier matches the column type (scalar / bytea), no cast is\n * needed and the alias passes through. When the carrier is text[] (jsonb\n * or array column), we cast back to the declared type. */\nfunction pgSelectExpr(alias: string, pgType: string): string {\n const base = pgType.trim().toLowerCase();\n if (base === \"jsonb\" || base === \"json\" || base.endsWith(\"[]\")) {\n return `(${alias})::${pgType}`;\n }\n return alias;\n}\n\n/**\n * Encodes a JS runtime value for transport via the chosen unnest carrier.\n * For scalar columns the pg driver handles type coercion directly (bigint,\n * number, boolean, Date, etc. all serialize cleanly). For jsonb columns we\n * stringify; for array columns we build a PG array literal. For bytea\n * columns we forward the bytes.\n *\n * Codecs declared by the upstream schema layer run before this point, so\n * `value` is already in the driver-side shape for its declared column.\n */\nfunction encodeForCarrier(value: unknown, pgTypeBase: string): unknown {\n if (value === null || value === undefined) return null;\n if (pgTypeBase === \"bytea\") {\n return toBufferView(normalizeToBytes(value));\n }\n if (pgTypeBase === \"jsonb\" || pgTypeBase === \"json\") {\n return typeof value === \"string\" ? value : supaliveStringify(value);\n }\n if (pgTypeBase.endsWith(\"[]\")) {\n if (!Array.isArray(value)) {\n throw new Error(`Expected array for column of type ${pgTypeBase}, got ${typeof value}`);\n }\n return pgArrayLiteral(value);\n }\n return value;\n}\n\n/** Serializes a JS array to a Postgres array literal `{a,b,c}`. Strings\n * are double-quoted with backslash/quote escaping; primitives stringify\n * directly; null becomes the literal NULL. */\nfunction pgArrayLiteral(arr: unknown[]): string {\n const parts: string[] = new Array(arr.length);\n for (let i = 0; i < arr.length; i++) {\n const v = arr[i];\n if (v === null || v === undefined) {\n parts[i] = \"NULL\";\n } else if (typeof v === \"string\") {\n parts[i] = `\"${v.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n } else if (typeof v === \"number\" || typeof v === \"bigint\" || typeof v === \"boolean\") {\n parts[i] = String(v);\n } else {\n const s = supaliveStringify(v);\n parts[i] = `\"${s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n }\n }\n return `{${parts.join(\",\")}}`;\n}\n\n/**\n * Postgres deadlock_detected (40P01) is transient and semantically equivalent\n * to an OCC conflict from the mutation runner's perspective: re-execute the\n * handler with a fresh snapshot. Wrapping here lets realtime_db.ts stay\n * driver-agnostic — its retry loop already handles OccConflictError.\n */\nfunction translatePgError(err: unknown): unknown {\n if (err && typeof err === \"object\" && (err as { code?: string }).code === \"40P01\") {\n return new OccConflictError(\"deadlock detected\", err);\n }\n return err;\n}\n\n// PG: when a sub-path is set, scope the target via `jsonb_path_query_first`\n// (returns the value at the path, or NULL → falsy in WHERE) before the\n// containment / array-membership check. Cast bound text to jsonb so the\n// same code path works for both `json` and `jsonb` columns.\nfunction pgScopedTarget(col: string, pathIndex: number | undefined): string {\n return pathIndex === undefined\n ? col\n : `jsonb_path_query_first(${col}::jsonb, $${pathIndex}::jsonpath)`;\n}\n\nexport const pgSql: SqlBuilder = {\n placeholder: (i) => `$${i}`,\n like: (col, i) => `${col} LIKE $${i}`,\n ilike: (col, i) => `${col} ILIKE $${i}`,\n icontains: (col, i) => `${col} ILIKE $${i}`,\n jsonContains: (col, i, opts) =>\n `${pgScopedTarget(col, opts?.pathIndex)} @> $${i}::jsonb`,\n jsonContainedBy: (col, i, opts) =>\n `${pgScopedTarget(col, opts?.pathIndex)} <@ $${i}::jsonb`,\n jsonHasKey: (col, i, opts) => {\n if (opts?.pathCount && opts.pathCount > 0) {\n const joiner = opts.mode === \"all\" ? \" AND \" : \" OR \";\n const parts: string[] = [];\n for (let k = 0; k < opts.pathCount; k++) {\n parts.push(`jsonb_path_exists(${col}, $${i + k}::jsonpath)`);\n }\n return `(${parts.join(joiner)})`;\n }\n return opts?.raw\n ? `jsonb_path_exists(${col}, $${i}::jsonpath)`\n : `${col} ? $${i}`;\n },\n jsonArrayContains: (col, i, opts) =>\n `${pgScopedTarget(col, opts?.pathIndex)} @> jsonb_build_array($${i}::jsonb)`,\n};\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"subscription-worker-CAf6MUta.js","names":["uuidv4","logger","baseLogger","logger","Redis","baseLogger"],"sources":["../src/logger.ts","../src/server/retention-watermark.ts","../src/server/subscription-manager-types.ts","../src/db/cache.ts","../src/db/init_db.ts","../src/server/subscription-worker.ts"],"sourcesContent":["import pino, { Level } from \"pino\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport pinoPretty from \"pino-pretty\";\nconst _ = pinoPretty; // Prevents tree shaking of pino-pretty\n\nexport const appInstanceId = `instance-${uuidv4().slice(0, 8)}`;\nexport const isProduction = process.env.ENV === \"prod\";\nexport const logger = pino({\n level: process.env.LOG_LEVEL || \"info\",\n timestamp: pino.stdTimeFunctions.isoTime,\n redact: { paths: [\"user.password\"] },\n transport: isProduction ? undefined : {\n target: 'pino-pretty',\n options: {\n colorize: true\n },\n },\n serializers: {\n \"columnsTypes\": (map) => {\n if (map instanceof Map) return serializeMapValue(map);\n return map;\n },\n },\n base: {\n \"srv\": appInstanceId,\n },\n});\n\nexport function logLevelOf(name: string): Level {\n const defaultLogLevel = process.env.DEFAULT_LOG_LEVEL || \"info\";\n return (process.env[name]?.toLowerCase() || defaultLogLevel) as Level;\n}\n\nexport function serializeMapValue<K extends string | number | symbol, V>(map: Map<K, V>): Record<K, V> {\n const obj: Record<K, any> = {} as Record<K, any>;\n for (const [k, v] of map.entries()) {\n obj[k] = {} as V;\n if (v instanceof Map) {\n for (const [innerK, innerV] of v.entries()) {\n obj[k][innerK] = innerV;\n }\n } else {\n obj[k] = v;\n }\n }\n\n return obj as Record<K, V>;\n}","import type { Database } from \"../db/db\";\n\n/** Redis pub/sub channel the sub-manager publishes the retention watermark on\n * after each prune (and at startup). App-server instances subscribe and update\n * their in-memory {@link RetentionWatermark}. Payload is the watermark `ts` as a\n * string. */\nexport const RETENTION_WATERMARK_CHANNEL = \"supalive:retention_watermark\";\n\n/**\n * In-memory holder for the commit-log retention watermark: the oldest commit-log\n * ts still retained after prune (see {@link Database.getMinSnapshotTimestamp}).\n * Read on the hot path by the query-cache freshness check — a plain variable, no\n * per-check Redis/DB round trip. Loaded once at startup from the `metadata`\n * table and kept fresh out-of-band: the sub-manager broadcasts the new watermark\n * (in-process to its workers, over Redis pub/sub to app servers) each time it\n * prunes.\n *\n * `set` is monotonic — the watermark only ever moves forward (pruning never\n * un-deletes rows), so an out-of-order or stale update can never lower it, which\n * keeps the freshness guard on the safe side (an over-estimate only costs an\n * extra recompute; an under-estimate could serve stale data).\n *\n * Initial value is the -1n genesis (not 0), matching `getMinSnapshotTimestamp`\n * and the empty-DB snapshot ts — so before anything is pruned the guard never\n * rejects a genesis-era entry (whose snapshot is -1).\n */\nexport class RetentionWatermark {\n private ts: bigint = -1n;\n\n get(): bigint {\n return this.ts;\n }\n\n set(ts: bigint): void {\n if (ts > this.ts) this.ts = ts;\n }\n\n /** Seed from the persisted watermark (metadata table). Returns the current value. */\n async loadFrom(db: Pick<Database, \"getMinSnapshotTimestamp\">): Promise<bigint> {\n this.set(await db.getMinSnapshotTimestamp());\n return this.ts;\n }\n}\n","import z from \"zod\";\nimport { BigIntSchema, RawReadEntry, ReadEntry, ReadEntrySchema, WriteEntrySchema } from \"../db/types_db\";\n\n// ─── RPC Schemas ──────────────────────────────────────────────────────────────\n//\n// The wire protocol intentionally has NO `_clientVersion` / `_resync` /\n// `serverVersion` fields. Ordering of concurrent `updateSubscriptionReadSet`\n// calls is enforced by `lastSnapshotTs` (which is monotonic — it comes from\n// `Database.getLatestSnapshotTimestamp()`). Recovery after a sub-manager\n// restart is driven by the app server iterating its own\n// `serverSubscriptions` map and re-registering each one using params\n// persisted in Redis under `sl:reg:<subId>`.\n\nexport const RegisterSubscriptionParamsSchema = z.object({\n /**\n * Caller-computed FNV-1a routing key + identity for this subscription.\n * The sub-manager trusts these values rather than re-deriving them from\n * (queryName, args, queryIdentity); this avoids one stringify+SHA1 per\n * register RPC. Trust is fine: the sub-manager RPC channel is fully\n * internal.\n */\n subId: z.string(),\n cacheKey: z.string(),\n queryName: z.string(),\n args: z.unknown(),\n /**\n * Segmentation key used in the subId/cacheKey hash. Defaults to the\n * authenticated user's id (\"anonymous\" when none), unless the\n * procedure overrides it via `QueryConfig.queryIdentity`.\n */\n queryIdentity: z.string(),\n instanceName: z.string(),\n lastSnapshotTs: BigIntSchema,\n});\nexport type RegisterSubscriptionParams = z.infer<typeof RegisterSubscriptionParamsSchema>;\n\nexport const RegisterSubscriptionResultSchema = z.object({\n cacheKey: z.string(),\n recompute: z.boolean(),\n readSet: z.array(ReadEntrySchema),\n // Version of the cached data the freshness check validated. The app server\n // serves the cached data blob only when its version matches this (guards a\n // data/metadata divergence). Absent when the worker had no metadata to\n // validate against (e.g. a plain recompute), in which case the server does\n // not serve from cache anyway.\n version: z.string().optional(),\n});\nexport type RegisterSubscriptionResult = z.infer<typeof RegisterSubscriptionResultSchema>;\n\nexport const RegisterSubscriptionBatchParamsSchema = z.array(RegisterSubscriptionParamsSchema);\nexport type RegisterSubscriptionBatchParams = z.infer<typeof RegisterSubscriptionBatchParamsSchema>;\n\nexport const RegisterSubscriptionBatchResultSchema = z.array(RegisterSubscriptionResultSchema);\nexport type RegisterSubscriptionBatchResult = z.infer<typeof RegisterSubscriptionBatchResultSchema>;\n\nexport const UpdateSubscriptionReadSetParamsSchema = z.object({\n cacheKey: z.string(),\n subId: z.string(),\n instanceName: z.string(),\n lastSnapshotTs: BigIntSchema,\n readSet: z.array(ReadEntrySchema),\n});\nexport type UpdateSubscriptionReadSetParams = z.infer<typeof UpdateSubscriptionReadSetParamsSchema>;\n\n/**\n * `tracked: false` means the sub-manager has no record of this subId (e.g.\n * a restart wiped state and the caller hasn't re-registered yet). The app\n * server should treat this as a signal to register the sub before retrying.\n */\nexport const UpdateSubscriptionReadSetResultSchema = z.object({\n tracked: z.boolean(),\n});\nexport type UpdateSubscriptionReadSetResult = z.infer<typeof UpdateSubscriptionReadSetResultSchema>;\n\nexport const UnregisterSubscriptionParamsSchema = z.object({\n subId: z.string(),\n instanceName: z.string(),\n});\nexport type UnregisterSubscriptionParams = z.infer<typeof UnregisterSubscriptionParamsSchema>;\n\nexport const UnregisterSubscriptionsParamsSchema = z.array(UnregisterSubscriptionParamsSchema);\nexport type UnregisterSubscriptionsParams = z.infer<typeof UnregisterSubscriptionsParamsSchema>;\n\nexport const UnregisterSubscriptionResultSchema = z.object({ ok: z.boolean() });\nexport type UnregisterSubscriptionResult = z.infer<typeof UnregisterSubscriptionResultSchema>;\n\nexport const UnregisterSubscriptionsResultSchema = z.array(z.object({ ok: z.boolean() }));\nexport type UnregisterSubscriptionsResult = z.infer<typeof UnregisterSubscriptionsResultSchema>;\n\nexport const InvalidateWritesetParamsSchema = z.object({\n writeSet: z.array(WriteEntrySchema),\n});\nexport type InvalidateWritesetParams = z.infer<typeof InvalidateWritesetParamsSchema>;\n\nexport const AffectedSubscriptionSchema = z.object({\n subId: z.string(),\n queryName: z.string(),\n args: z.unknown(),\n cacheKey: z.string(),\n /**\n * Every live instance that currently holds this subId. Routing rules:\n * • If the writer is in this list, it recomputes locally and publishes\n * an `update` to the rest (its own id is filtered by the publisher).\n * • Otherwise the writer broadcasts a `recompute-race` to every entry;\n * receivers race for a Redis lock and the winner recomputes.\n */\n notifyInstances: z.array(z.string()),\n});\nexport type AffectedSubscription = z.infer<typeof AffectedSubscriptionSchema>;\n\nexport const InvalidateWritesetResultSchema = z.object({\n affected: z.array(AffectedSubscriptionSchema),\n});\nexport type InvalidateWritesetResult = z.infer<typeof InvalidateWritesetResultSchema>;\n\n// ─── Registration record persisted to Redis ──────────────────────────────────\n//\n// Stored at `sl:reg:<subId>` by the sub-manager when a brand-new subscription\n// is created, and deleted by the sub-manager when the last instance leaves.\n// The app server reads this on reconnect to know how to re-register its\n// known subIds.\n\nexport const RegistrationRecordSchema = z.object({\n queryName: z.string(),\n args: z.unknown(),\n queryIdentity: z.string(),\n cacheKey: z.string(),\n});\nexport type RegistrationRecord = z.infer<typeof RegistrationRecordSchema>;\n\nexport interface TrackedSubscription {\n subId: string;\n queryName: string;\n args: unknown;\n cacheKey: string;\n lastSnapshotTs: bigint;\n readSet: ReadEntry[];\n rawReadSet: RawReadEntry[];\n /** All app server instances that currently hold this subscription. */\n instances: Set<string>;\n timeout: NodeJS.Timeout | null;\n}","import type { Redis as UpstashRedis } from \"@upstash/redis\";\nimport {\n CachedPgMetadata,\n CachedPgMetadataSchema,\n QueryCacheEntry, QueryCacheEntrySchema,\n QueryCacheMetadata, QueryCacheMetadataSchema\n} from \"./types_db\";\nimport { retry, handleAll, ExponentialBackoff } from \"cockatiel\";\nimport { RegistrationRecord, RegistrationRecordSchema } from \"../server/subscription-manager-types\";\nimport Redis from \"ioredis\";\nimport { createHash } from \"node:crypto\";\nimport { logger as baseLogger, logLevelOf } from \"../logger\";\nimport { supaliveStringify } from \"../helper\";\n\nconst logger = baseLogger.child({\n \"name\": \"CACHE_LAYER\",\n},\n { level: logLevelOf(\"SERVER_LOG_LEVEL\") },\n);\n\nexport const redisRetryPolicy = retry(handleAll, {\n maxAttempts: 3,\n backoff: new ExponentialBackoff({\n initialDelay: 5,\n maxDelay: 2300,\n exponent: 2,\n }),\n});\n\n// ─── Query-cache Lua scripts ────────────────────────────────────────────────\n//\n// The query cache is two string keys per query — data (`sl:cache:*`) and\n// metadata (`sl:meta:*`). They are written by several code paths across two\n// processes (app server + sub-worker), so a plain pipeline can't keep them\n// consistent (and on a non-atomic client a pipeline isn't even atomic). These\n// scripts make each write ATOMIC and MONOTONIC:\n// • atomic — data + metadata are set in one server-side script.\n// • monotonic (CAS) — a write is applied only when it is NOT older than what\n// is stored, so a slow/older writer can never clobber a newer entry.\n// \"Newer\" is compared on `version` (the data's compute-ts, a decimal string;\n// `tonumber` is exact for the real ts range and handles the -1 genesis value).\n// cjson is used ONLY to READ the stored comparand; the value written is always\n// the caller-serialized ARGV string, so we never hit cjson's empty-array\n// re-encode pitfall.\n\n/** Atomic one-shot recompute write: set data + metadata iff incoming version\n * (ARGV[3]) is not older than the stored one. KEYS: data, meta. */\nconst WRITE_DATA_AND_META = `\nlocal cur = redis.call('GET', KEYS[2])\nif cur then\n local ok, m = pcall(cjson.decode, cur)\n if ok and type(m) == 'table' and m.version and tonumber(ARGV[3]) < tonumber(m.version) then\n return 0\n end\nend\nredis.call('SET', KEYS[1], ARGV[1], 'EX', tonumber(ARGV[4]))\nredis.call('SET', KEYS[2], ARGV[2], 'EX', tonumber(ARGV[4]))\nreturn 1`;\n\n/** Data-only write (subscribe path): set data iff incoming version (ARGV[2]) is\n * not older than the stored metadata's version. KEYS: data, meta. */\nconst WRITE_DATA_ONLY = `\nlocal cur = redis.call('GET', KEYS[2])\nif cur then\n local ok, m = pcall(cjson.decode, cur)\n if ok and type(m) == 'table' and m.version and tonumber(ARGV[2]) < tonumber(m.version) then\n return 0\n end\nend\nredis.call('SET', KEYS[1], ARGV[1], 'EX', tonumber(ARGV[3]))\nreturn 1`;\n\n/** Metadata-only replace (subscription recompute): set meta iff incoming version\n * (ARGV[2]) is not older than the stored one. KEYS: meta. */\nconst REPLACE_META = `\nlocal cur = redis.call('GET', KEYS[1])\nif cur then\n local ok, m = pcall(cjson.decode, cur)\n if ok and type(m) == 'table' and m.version and tonumber(ARGV[2]) < tonumber(m.version) then\n return 0\n end\nend\nredis.call('SET', KEYS[1], ARGV[1], 'EX', tonumber(ARGV[3]))\nreturn 1`;\n\n/** Metadata-only horizon advance (still-fresh subscription): bump lastSnapshotTs\n * ONLY, without recomputing. Applies ARGV[1] iff the new horizon (ARGV[2]) is\n * strictly ahead of the stored one AND no newer computation (stored.version >\n * ARGV[3], the version the caller based its advance on) has landed meanwhile —\n * so an advance never reverts a fresh recompute. KEYS: meta. */\nconst ADVANCE_META = `\nlocal cur = redis.call('GET', KEYS[1])\nif not cur then return 0 end\nlocal ok, m = pcall(cjson.decode, cur)\nif not ok or type(m) ~= 'table' then return 0 end\nif tonumber(ARGV[2]) <= tonumber(m.lastSnapshotTs) then return 0 end\nif m.version and tonumber(m.version) > tonumber(ARGV[3]) then return 0 end\nredis.call('SET', KEYS[1], ARGV[1], 'EX', tonumber(ARGV[4]))\nreturn 1`;\n\nexport class CacheLayer {\n public redis: Redis | UpstashRedis;\n private readonly ttlSeconds: number;\n /** Cached EVALSHA digests keyed by Lua source (see evalScript). */\n private readonly scriptShaCache = new Map<string, string>();\n\n constructor(upstash: Redis | UpstashRedis, ttlSeconds: number = 3600) {\n this.redis = upstash;\n this.ttlSeconds = ttlSeconds;\n }\n\n /**\n * Run a Lua script via EVALSHA using the script's SHA1 (computed locally — the\n * same digest Redis keys scripts by, so no SCRIPT LOAD round-trip is needed on\n * the hot path). On NOSCRIPT (the script isn't in Redis's cache yet, e.g. first\n * use or after a Redis restart/failover) load it explicitly via SCRIPT LOAD and\n * re-run via EVALSHA — so the script ends up cached server-side and subsequent\n * EVALSHA calls hit. The runtime client is always ioredis (see initCacheLayer).\n */\n private async evalScript(src: string, keys: string[], args: (string | number)[]): Promise<unknown> {\n const redis = this.redis as Redis;\n let sha = this.scriptShaCache.get(src);\n if (!sha) {\n sha = createHash(\"sha1\").update(src).digest(\"hex\");\n this.scriptShaCache.set(src, sha);\n }\n return redisRetryPolicy.execute(async () => {\n try {\n return await redis.evalsha(sha!, keys.length, ...keys, ...args);\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"NOSCRIPT\")) {\n // Not in Redis's script cache yet — load it, then execute by digest.\n const loadedSha = (await redis.call(\"SCRIPT\", \"LOAD\", src)) as string;\n this.scriptShaCache.set(src, loadedSha);\n return await redis.evalsha(loadedSha, keys.length, ...keys, ...args);\n }\n throw err;\n }\n });\n }\n\n /** One-shot recompute: atomically write data + metadata (CAS on version). */\n async setQueryCacheAndMetadataFor(\n cacheKey: string, data: unknown,\n metaData: QueryCacheMetadata,\n ttlSeconds?: number,\n ): Promise<void> {\n const ttl = ttlSeconds ?? this.ttlSeconds;\n const dataJson = supaliveStringify({ data, version: metaData.version });\n const metaJson = supaliveStringify(metaData);\n await this.evalScript(\n WRITE_DATA_AND_META,\n [this.getQueryCacheDataKey(cacheKey), this.getQeruyCacheMetaKey(cacheKey)],\n [dataJson, metaJson, metaData.version, String(ttl)],\n );\n }\n\n /** Subscribe path: write the data blob only (CAS against the metadata's\n * version). The metadata is written separately by the sub-worker; the\n * `version` links the two so a divergent pair is detected on read. */\n async setQueryCacheFor(cacheKey: string, data: unknown, version: string, ttlSeconds?: number): Promise<void> {\n const ttl = ttlSeconds ?? this.ttlSeconds;\n const dataJson = supaliveStringify({ data, version });\n await this.evalScript(\n WRITE_DATA_ONLY,\n [this.getQueryCacheDataKey(cacheKey), this.getQeruyCacheMetaKey(cacheKey)],\n [dataJson, version, String(ttl)],\n );\n }\n\n async getQueryCacheFor(cacheKey: string): Promise<QueryCacheEntry | null> {\n const dataRaw = await redisRetryPolicy.execute(() => this.redis.get(this.getQueryCacheDataKey(cacheKey)));\n\n if (!dataRaw) return null;\n\n try {\n const parsed = typeof dataRaw === \"string\" ? JSON.parse(dataRaw) : dataRaw;\n return QueryCacheEntrySchema.parse(parsed);\n } catch {\n return null;\n }\n }\n\n /** Subscription recompute: replace the whole metadata (CAS on version). */\n async replaceQueryCacheMetadata(cacheKey: string, metaData: QueryCacheMetadata, ttlSeconds?: number): Promise<void> {\n const ttl = ttlSeconds ?? this.ttlSeconds;\n const metaJson = supaliveStringify(metaData);\n await this.evalScript(\n REPLACE_META,\n [this.getQeruyCacheMetaKey(cacheKey)],\n [metaJson, metaData.version, String(ttl)],\n );\n }\n\n /** Still-fresh subscription: advance `lastSnapshotTs` only, preserving the\n * data's `version` + `readSet` (no recompute). Monotonic and non-clobbering\n * — see ADVANCE_META. `metaData` carries the new horizon plus the version +\n * readSet the caller read, which the script keeps unless a newer computation\n * has since landed. */\n async advanceQueryCacheMetadata(cacheKey: string, metaData: QueryCacheMetadata, ttlSeconds?: number): Promise<void> {\n const ttl = ttlSeconds ?? this.ttlSeconds;\n const metaJson = supaliveStringify(metaData);\n await this.evalScript(\n ADVANCE_META,\n [this.getQeruyCacheMetaKey(cacheKey)],\n [metaJson, String(metaData.lastSnapshotTs), metaData.version, String(ttl)],\n );\n }\n\n async getQueryCacheMetaData(cacheKey: string): Promise<QueryCacheMetadata | null> {\n const dataRaw = await redisRetryPolicy.execute(() => this.redis.get(this.getQeruyCacheMetaKey(cacheKey)));\n\n if (!dataRaw) return null;\n\n try {\n const parsed = typeof dataRaw === \"string\" ? JSON.parse(dataRaw) : dataRaw;\n return QueryCacheMetadataSchema.parse(parsed);\n } catch {\n return null;\n }\n }\n\n async persistRegistrationRecord(subId: string, record: RegistrationRecord): Promise<void> {\n const data = supaliveStringify(record);\n await redisRetryPolicy.execute(() => this.redis.set(this.getRegistrationKey(subId), data));\n }\n\n async deleteRegistrationRecord(subId: string): Promise<void> {\n await redisRetryPolicy.execute(() => this.redis.del(this.getRegistrationKey(subId)));\n }\n\n async deleteRegistrationsRecord(subIds: string[]): Promise<void> {\n if (subIds.length === 0) return;\n\n await redisRetryPolicy.execute(() =>\n this.redis.del(...subIds.map((subId) => this.getRegistrationKey(subId))),\n );\n }\n\n async fetchRegistrationRecordsBatch(\n subIds: string[],\n ): Promise<Map<string, RegistrationRecord | null>> {\n const result = new Map<string, RegistrationRecord | null>();\n const CHUNK_SIZE = 100;\n\n for (let i = 0; i < subIds.length; i += CHUNK_SIZE) {\n const chunk = subIds.slice(i, i + CHUNK_SIZE);\n const keys = chunk.map((id) => `sl:reg:${id}`);\n try {\n if (keys.length === 0) continue;\n\n const rawValues = await redisRetryPolicy.execute(() =>\n this.redis.mget(...keys),\n );\n\n for (let j = 0; j < chunk.length; j++) {\n const subId = chunk[j]!;\n const raw = rawValues[j];\n const rawJson = typeof raw === \"string\" ? JSON.parse(raw) : raw;\n\n if (!raw) {\n result.set(subId, null);\n } else {\n try {\n const parsed = RegistrationRecordSchema.parse(rawJson);\n result.set(subId, parsed);\n } catch {\n logger.error(`Failed to parse sl:reg:${subId} during batch recovery`);\n result.set(subId, null);\n }\n }\n }\n } catch (err) {\n logger.error(err, \"Failed to fetch registration records batch\");\n for (const subId of chunk) {\n result.set(subId, null);\n }\n }\n }\n return result;\n }\n\n async getCachedTableColumnTypes(key: string): Promise<CachedPgMetadata | null> {\n const dataRaw = await redisRetryPolicy.execute(() => this.redis.get(key));\n if (!dataRaw) return null;\n\n try {\n const parsed = typeof dataRaw === \"string\" ? JSON.parse(dataRaw) : dataRaw;\n return CachedPgMetadataSchema.parse(parsed);\n } catch {\n return null;\n }\n }\n\n async setCachedTableColumnsTypes(key: string, value: CachedPgMetadata): Promise<void> {\n await redisRetryPolicy.execute(() =>\n this.redis.set(key, supaliveStringify(value)),\n );\n }\n\n /**\n * Race participant: try to claim `lock:recompute:<subId>:<commitTs>`\n * with `SET NX EX`. The single Redis round-trip both arbitrates and\n * sets a TTL fallback in case the winner crashes mid-recompute.\n */\n async tryAcquireRecomputeLock(instanceId: string, subId: string, commitTs: string, ttl: number): Promise<boolean> {\n const key = `lock:recompute:${subId}:${commitTs}`;\n return redisRetryPolicy.execute(async () => {\n try {\n const res = await this.redis.set(key, instanceId, \"EX\", ttl, \"NX\");\n return res === \"OK\";\n } catch (err) {\n logger.error(err, `Failed to acquire recompute lock ${key}`);\n // Fail-closed: if Redis is misbehaving, don't run a recompute that\n // we can't coordinate. The next mutation will trigger another race.\n return false;\n }\n });\n }\n\n\n private getRegistrationKey(subId: string): string {\n return `sl:reg:${subId}`;\n }\n\n private getQueryCacheDataKey(cacheKey: string): string {\n return `sl:cache:${cacheKey}`;\n }\n\n private getQeruyCacheMetaKey(cacheKey: string): string {\n return `sl:meta:${cacheKey}`;\n }\n}","import { DatabaseConfig, SupaliveServerConfig, UpstashConfig } from \"../config\";\nimport { logger } from \"../logger\";\nimport { CacheLayer } from \"./cache\";\nimport { Database } from \"./db\";\nimport { MySqlDatabase } from \"./mysql\";\nimport { PgDatabase } from \"./postgres\";\nimport { SupaliveDb } from \"./realtime_db\";\nimport Redis from \"ioredis\";\n\n/**\n * Current core schema version. Bump this whenever core needs a new non-table\n * database operation (a sequence, a seed row, a backfill). Each increment adds\n * a case to `Database.coreMigrationStatements` for that version step.\n *\n * The core *tables* (commit_logs, metadata) are NOT versioned here — they come\n * from the generated schema (`coreTablesSql` / `generateSchemaSql`) which must\n * be applied to the database BEFORE `initCore` runs.\n */\nexport const CORE_VERSION = 1n;\n\n/**\n * Bring the core, non-table database state up to {@link CORE_VERSION}. Idempotent\n * and safe to call from every process at startup: a lock-free version read\n * short-circuits the common \"already current\" case, and the actual migration\n * runs under a cross-process lock with a re-check so only one process applies\n * it.\n *\n * Assumes the core tables already exist (apply the generated schema first);\n * the `metadata` table is where the version and seed rows live.\n */\nexport async function initCore(db: Database): Promise<void> {\n // Fast path: no lock, no transaction.\n const current = await db.getCoreVersion();\n if (current >= CORE_VERSION) return;\n\n await db.withCoreInitLock(async (ctx) => {\n // Re-check under the lock — another process may have migrated while we\n // were waiting to acquire it.\n const from = await ctx.getVersion();\n if (from >= CORE_VERSION) return;\n\n for (let v = from + 1n; v <= CORE_VERSION; v++) {\n const statements = db.coreMigrationStatements(v);\n logger.info(`Migrating core schema ${v - 1n} -> ${v} (${statements.length} statements)`);\n for (const sql of statements) {\n await ctx.exec(sql);\n }\n }\n\n await ctx.setVersion(CORE_VERSION);\n logger.info(`Core schema now at version ${CORE_VERSION}`);\n });\n}\n\n/**\n * Default and env override for the per-statement DB timeout. PG enforces\n * this via `statement_timeout` (server cancels), MySQL via the per-query\n * `timeout` option (driver issues KILL QUERY). Set 0 to disable.\n */\nexport const DB_QUERY_TIMEOUT_MS = Number(\n process.env.SUPALIVE_DB_QUERY_TIMEOUT_MS ?? 30_000,\n);\n\nexport type InitDbOptions = {\n DbConfig: DatabaseConfig;\n CacheLayer: CacheLayer;\n forceBootstrapReload?: boolean;\n workerId?: number;\n};\n\nexport async function initDatabase(options: InitDbOptions): Promise<SupaliveDb> {\n const impl = createDatabase(options.DbConfig, options.workerId);\n const supaliveDb = SupaliveDb.create({ db: impl });\n // Bring core non-table state (sequences, seed rows) up to date. Core tables\n // are expected to already exist from the applied schema.\n await initCore(impl);\n await bootstrapDbTypes(supaliveDb, options.CacheLayer, options.forceBootstrapReload ?? false);\n return supaliveDb;\n}\n\nexport function createDatabase(config: DatabaseConfig, workerId?: number): PgDatabase | MySqlDatabase {\n const bindings: Record<string, any> = {\n \"db\": config.type,\n };\n if (workerId) {\n bindings[\"worker\"] = workerId;\n }\n\n if (config.type === \"postgres\") {\n return new PgDatabase(\n logger.child(bindings), {\n ...config,\n connectionString: config.connectionString,\n min: config.minConnections ?? 0,\n max: config.maxConnections ?? 20,\n connectionTimeoutMillis: config.connectionTimeoutMillis ?? 15_000,\n idleTimeoutMillis: config.idleTimeoutMillis ?? 30_000,\n // server-enforced per-statement timeout; pg cancels the running\n // query when it fires. 0 disables it.\n statement_timeout: DB_QUERY_TIMEOUT_MS > 0 ? DB_QUERY_TIMEOUT_MS : undefined,\n });\n } else {\n return new MySqlDatabase(\n logger.child(bindings), {\n ...config,\n connectionLimit: config.maxConnections ?? 20,\n connectTimeout: config.connectionTimeoutMillis ?? 15_000,\n // mysql2 pool: 0 = wait forever for a free conn (default). queueLimit\n // bounds the wait queue length so backpressure surfaces as an error\n // rather than unbounded growth.\n queueLimit: config.queueLimit ?? 0,\n // driver-side per-statement timeout applied uniformly in\n // MySqlDatabase.query.\n queryTimeoutMs: DB_QUERY_TIMEOUT_MS,\n });\n }\n}\n\n/**\n * Eagerly load column types into the apply-path cache at server start.\n * In production, the result is cached in Redis under\n * `supalive:schema:types:${SUPALIVE_SCHEMA_VERSION ?? \"v1\"}` so other\n * instances starting cold can skip the pg_attribute round-trip. In any\n * other env we go straight to PG every time so local schema iteration\n * is never blocked by stale Redis state. Migrations should publish a\n * `schema:reload` message (see {@link publishSchemaReload}) after\n * applying DDL — every instance picks that up and re-bootstraps.\n */\nexport async function bootstrapDbTypes(db: SupaliveDb, cache: CacheLayer, forceReload = false): Promise<void> {\n // TODO: remove this check if we needs mysql column types\n if (db.impl.dbType === \"mysql\") {\n // currently we don't use mysql column type\n return;\n }\n\n const inProd = process.env.NODE_ENV === \"production\";\n const version = process.env.SUPALIVE_SCHEMA_VERSION ?? \"v1\";\n const key = `supalive:schema:types:${version}`;\n try {\n await db.impl.bootstrapColumnTypes({\n cacheKey: key,\n redis: inProd && !forceReload ? cache : undefined,\n });\n logger.info({ columnsTypes: db.impl.columnTypes }, `Bootstrapped db column types (redis=${inProd}, key=${key})`);\n } catch (err) {\n logger.error(err, \"Failed to bootstrap db column types\");\n throw err;\n }\n}\n\nexport type InitCacheLayerOptions = {\n upstash: UpstashConfig;\n /* Default 3600 */\n cacheTtlSeconds?: number;\n /* Default 15_000 */\n connectionTimeout?: number;\n /* Default 1 */\n commandMaxRetries?: number;\n /* Default 5 */\n commandSubMaxRetries?: number;\n /* Default true */\n createSubClient?: boolean;\n};\n\nexport function initCacheLayer(config: InitCacheLayerOptions): { cacheLayer: CacheLayer, redisSubClient?: Redis } {\n const redis = new Redis(config.upstash.redisUrl, {\n connectTimeout: config.connectionTimeout ?? 15_000,\n maxRetriesPerRequest: config.commandMaxRetries ?? 1,\n keepAlive: 3000,\n });\n \n const redisSub = config.createSubClient ? new Redis(config.upstash.redisUrl, {\n connectTimeout: config.connectionTimeout ?? 15_000,\n maxRetriesPerRequest: config.commandSubMaxRetries ?? 5,\n disableClientInfo: true,\n retryStrategy: (times) => {\n if (times > 5) return null;\n return Math.min(times * 200, 2000);\n }\n }) : undefined;\n\n return {\n cacheLayer: new CacheLayer(redis, config.cacheTtlSeconds ?? 3600),\n redisSubClient: redisSub\n };\n}\n\n","import type { Database } from \"../db/db\";\nimport type { RawReadEntry, ReadEntry } from \"../db/types_db\";\nimport type { CacheLayer } from \"../db/cache\";\nimport {\n checkWriteSetAffectsReadSet,\n evaluateCacheFreshness,\n mapReadSetToRaw,\n type RawWriteEntry,\n} from \"./overlap-checker\";\nimport {\n AffectedSubscription,\n RegisterSubscriptionParams,\n RegisterSubscriptionResult,\n RegistrationRecord,\n TrackedSubscription,\n UnregisterSubscriptionParams,\n UnregisterSubscriptionResult,\n UnregisterSubscriptionsParams,\n UnregisterSubscriptionsResult,\n UpdateSubscriptionReadSetParams,\n UpdateSubscriptionReadSetResult,\n} from \"./subscription-manager-types\";\nimport { logger as baseLogger, logLevelOf } from \"../logger\";\nimport { RetentionWatermark, RETENTION_WATERMARK_CHANNEL } from \"./retention-watermark\";\n\n// A logical worker that owns a disjoint slice of subscriptions. The dispatcher\n// routes each operation here by FNV-1a(subId) % numWorkers. Each worker is\n// independent: no shared state, no locks, no cross-worker coordination.\n// invalidate() is a pure function of the worker's own state + the writeSet.\n\nexport class SubscriptionWorker {\n readonly id: number;\n private subscriptions = new Map<string, TrackedSubscription>();\n private cache: CacheLayer;\n private db: Database;\n // In-memory retained commit-log watermark. Seeded at startup and moved forward on\n // prune; read on the register hot path instead of a per-check Redis GET.\n private retentionWatermark = new RetentionWatermark();\n public logger: ReturnType<typeof baseLogger.child>;\n\n constructor(id: number, cache: CacheLayer, db: Database) {\n this.id = id;\n this.cache = cache;\n this.db = db;\n this.logger = baseLogger.child(\n { name: \"SUBS_WRK\", wid: id },\n { level: logLevelOf(\"SUBS_MANAGER_SERVER_LOG_LEVEL\") },\n );\n }\n\n size(): number {\n return this.subscriptions.size;\n }\n\n has(subId: string): boolean {\n return this.subscriptions.has(subId);\n }\n\n /**\n * Lowest `lastSnapshotTs` across this worker's subscriptions, or `null`\n * when there are none. Used by the dispatcher to derive a safe prune watermark.\n */\n minSubscriptionTs(): bigint | null {\n let min: bigint | null = null;\n for (const sub of this.subscriptions.values()) {\n if (min === null || sub.lastSnapshotTs < min) min = sub.lastSnapshotTs;\n }\n return min;\n }\n\n /**\n * Seed/repair the persisted retained watermark from the actual oldest retained\n * commit log (`min(ts)`), then load it into memory and broadcast it. Called\n * once at sub-manager startup — the `min(ts)` scan is off the hot path, and\n * it corrects `metadata.min_retained_ts` even for a DB that was pruned before\n * this feature existed. Returns the resulting watermark so the manager can\n * broadcast it to the other workers.\n */\n async refreshRetentionWatermark(): Promise<bigint> {\n const real = (await this.db.getMinCommitLogTs()) ?? 0n;\n await this.db.updateMinSnapshotTimestamp(real);\n // Read back so our in-memory copy matches the persisted (monotonic) value.\n const persisted = await this.db.getMinSnapshotTimestamp();\n this.retentionWatermark.set(persisted);\n await this.publishRetentionWatermark(persisted);\n return this.retentionWatermark.get();\n }\n\n /** Adopt a watermark broadcast by the manager (in-process from the pruning\n * worker). Monotonic, so an out-of-order message can't lower it. */\n setRetentionWatermark(ts: bigint): void {\n this.retentionWatermark.set(ts);\n }\n\n /**\n * Prune commit logs older than `minRetainedTs`. Advertises the new watermark FIRST —\n * persist it, bump our in-memory copy, and broadcast it over Redis — and only\n * then deletes, so no reader ever trusts a cache entry whose freshness scan\n * would include rows we're about to remove. Returns rows deleted.\n */\n async prune(minRetainedTs: bigint): Promise<bigint> {\n await this.db.updateMinSnapshotTimestamp(minRetainedTs);\n this.retentionWatermark.set(minRetainedTs);\n await this.publishRetentionWatermark(minRetainedTs);\n const deleted = await this.db.pruneCommitLogsBefore(minRetainedTs);\n return deleted;\n }\n\n /** Broadcast the watermark to app-server instances over Redis pub/sub. Workers in\n * this process get it in-process via {@link setRetentionWatermark}. */\n private async publishRetentionWatermark(ts: bigint): Promise<void> {\n try {\n await this.cache.redis.publish(RETENTION_WATERMARK_CHANNEL, ts.toString());\n } catch (err) {\n this.logger.error(err, \"failed to publish commit-log watermark\");\n }\n }\n\n async register(\n params: RegisterSubscriptionParams,\n ): Promise<RegisterSubscriptionResult> {\n const { subId, cacheKey, queryName, args, queryIdentity, instanceName, lastSnapshotTs } = params;\n this.logger.info(`registering subscription: ${subId} from ${instanceName}`);\n\n const existing = this.subscriptions.get(subId);\n\n if (existing && !existing.timeout) {\n existing.instances.add(instanceName);\n return {\n cacheKey,\n recompute: false,\n readSet: existing.readSet,\n };\n }\n\n if (existing?.timeout) {\n this.logger.info(`reactivating subscription: ${subId} from: ${instanceName}`);\n clearTimeout(existing.timeout);\n existing.timeout = null;\n }\n\n const metadata = await this.cache.getQueryCacheMetaData(cacheKey);\n const freshness = await evaluateCacheFreshness(this.db, metadata, lastSnapshotTs, this.retentionWatermark.get());\n let needsRecompute = !freshness.fresh;\n const readSet: ReadEntry[] = freshness.readSet;\n const rawReadSet: RawReadEntry[] = freshness.rawReadSet;\n\n if (!needsRecompute && metadata && lastSnapshotTs > metadata.lastSnapshotTs) {\n // Cache is still valid at a newer snapshot — advance the stored horizon\n // so the next freshness scan starts from here (and stays above the\n // watermark). Preserve the data's version + readSet; the CAS in\n // advanceQueryCacheMetadata won't revert a fresher recompute.\n this.cache\n .advanceQueryCacheMetadata(cacheKey, { lastSnapshotTs, version: metadata.version, readSet })\n .catch((err) => this.logger.error(err, `Failed to advance cache metadata for ${cacheKey}`));\n }\n\n let newSubscription: TrackedSubscription = {\n subId,\n queryName,\n args,\n cacheKey,\n lastSnapshotTs: lastSnapshotTs,\n readSet,\n rawReadSet,\n instances: new Set([instanceName]),\n timeout: null,\n };\n\n const createdWhileChecking = this.subscriptions.get(subId);\n if (createdWhileChecking) {\n if (createdWhileChecking.timeout) {\n clearTimeout(createdWhileChecking.timeout);\n createdWhileChecking.timeout = null;\n }\n\n if (createdWhileChecking.lastSnapshotTs > lastSnapshotTs) {\n newSubscription = {\n ...newSubscription,\n ...createdWhileChecking,\n instances: new Set([...createdWhileChecking.instances, instanceName]),\n };\n needsRecompute = false;\n }\n }\n\n this.subscriptions.set(subId, newSubscription);\n\n this.persistRegistration(subId, { queryName, args, queryIdentity, cacheKey });\n\n // `version` lets the app server verify the cached data blob it serves\n // matches the metadata we validated (undefined when there was no metadata,\n // i.e. a plain recompute — the server won't serve from cache then anyway).\n return { cacheKey, recompute: needsRecompute, readSet, version: metadata?.version };\n }\n\n async updateReadSet(\n params: UpdateSubscriptionReadSetParams,\n ): Promise<UpdateSubscriptionReadSetResult> {\n const { cacheKey, subId, instanceName, lastSnapshotTs, readSet } = params;\n this.logger.info(`updating subscription readSet: ${subId} from ${instanceName}`);\n\n const existing = this.subscriptions.get(subId);\n if (!existing) {\n return { tracked: false };\n }\n\n if (lastSnapshotTs < existing.lastSnapshotTs) {\n return { tracked: true };\n }\n\n const rawReadSet = mapReadSetToRaw(readSet);\n this.subscriptions.set(subId, { ...existing, readSet, rawReadSet, lastSnapshotTs });\n // Fresh recompute: version == the compute ts (== lastSnapshotTs here). The\n // server writes the matching data blob with this same version.\n await this.cache.replaceQueryCacheMetadata(cacheKey, { lastSnapshotTs, version: String(lastSnapshotTs), readSet });\n\n return { tracked: true };\n }\n\n async unregister(\n params: UnregisterSubscriptionParams,\n jitter: number = 0,\n ): Promise<UnregisterSubscriptionResult> {\n const { subId, instanceName } = params;\n this.logger.info(`unregistering subscription: ${subId} from: ${instanceName}`);\n\n const sub = this.subscriptions.get(subId);\n if (!sub) return { ok: true };\n\n if (sub.timeout) {\n clearTimeout(sub.timeout);\n }\n\n if (sub.instances.size > 1) {\n sub.instances.delete(instanceName);\n return { ok: true };\n }\n\n this.logger.debug(`scheduling unregister subscription: ${subId} from: ${instanceName} in 15s`);\n sub.timeout = setTimeout(async () => {\n sub.instances.delete(instanceName);\n\n if (sub.instances.size === 0) {\n this.logger.info(`unregistered subscription: ${subId} from: ${instanceName}`);\n this.subscriptions.delete(subId);\n await this.deleteRegistration(subId);\n }\n }, 15_000 + jitter);\n\n return { ok: true };\n }\n\n async unregisters(\n params: UnregisterSubscriptionsParams,\n ): Promise<UnregisterSubscriptionsResult> {\n this.logger.info({ subIds: params }, `scheduling unregistering subscriptions`);\n for (const param of params) {\n this.unregister(param, Math.floor(Math.random() * 100));\n }\n\n return params.map(() => ({ ok: true }));\n }\n\n /**\n * Synchronous, CPU-bound. Scans this worker's slice of subscriptions and\n * returns the ones affected by the writeSet.\n */\n invalidate(rawWriteSet: RawWriteEntry[]): AffectedSubscription[] {\n const affected: AffectedSubscription[] = [];\n\n for (const [, sub] of this.subscriptions) {\n if (sub.instances.size === 0) continue;\n if (!checkWriteSetAffectsReadSet(rawWriteSet, sub.rawReadSet)) continue;\n\n affected.push({\n subId: sub.subId,\n queryName: sub.queryName,\n args: sub.args,\n cacheKey: sub.cacheKey,\n notifyInstances: Array.from(sub.instances),\n });\n }\n\n return affected;\n }\n\n private async persistRegistration(subId: string, record: RegistrationRecord): Promise<void> {\n try {\n await this.cache.persistRegistrationRecord(subId, record);\n } catch (err) {\n this.logger.error(err, `[worker ${this.id}] Failed to persist registration for ${subId}`);\n }\n }\n\n private async deleteRegistration(subId: string): Promise<void> {\n try {\n await this.cache.deleteRegistrationRecord(subId);\n } catch (err) {\n this.logger.error(err, `[worker ${this.id}] Failed to delete registration for ${subId}`);\n }\n }\n}\n"],"mappings":"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"}