orez 0.2.27 → 0.2.30

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 (157) hide show
  1. package/dist/cf-do/worker.d.ts +3 -0
  2. package/dist/cf-do/worker.d.ts.map +1 -1
  3. package/dist/cf-do/worker.js +37 -15
  4. package/dist/cf-do/worker.js.map +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +8 -0
  7. package/dist/index.js.map +1 -1
  8. package/package.json +3 -4
  9. package/src/admin/admin-data.test.ts +0 -348
  10. package/src/admin/http-proxy.ts +0 -252
  11. package/src/admin/log-store.ts +0 -192
  12. package/src/admin/server.ts +0 -471
  13. package/src/admin/ui.ts +0 -1322
  14. package/src/bench/proxy-throughput.bench.ts +0 -343
  15. package/src/bench/serial-mutations.bench.ts +0 -270
  16. package/src/browser.ts +0 -203
  17. package/src/cf-do/.wrangler/cache/cf.json +0 -1
  18. package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite +0 -0
  19. package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite-shm +0 -0
  20. package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite-wal +0 -0
  21. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/0ffaabee41a60e04dd0eb7db3073f0a40139e6a97ccd26823967acb652b89a7b.sqlite +0 -0
  22. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite +0 -0
  23. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite-shm +0 -0
  24. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite-wal +0 -0
  25. package/src/cf-do/.wrangler/tmp/bundle-0z4CpE/middleware-insertion-facade.js +0 -11
  26. package/src/cf-do/.wrangler/tmp/bundle-0z4CpE/middleware-loader.entry.ts +0 -134
  27. package/src/cf-do/.wrangler/tmp/bundle-vYmw0E/middleware-insertion-facade.js +0 -11
  28. package/src/cf-do/.wrangler/tmp/bundle-vYmw0E/middleware-loader.entry.ts +0 -134
  29. package/src/cf-do/.wrangler/tmp/dev-cbILNo/worker.js +0 -1059
  30. package/src/cf-do/.wrangler/tmp/dev-cbILNo/worker.js.map +0 -8
  31. package/src/cf-do/.wrangler/tmp/dev-qbho19/worker.js +0 -1059
  32. package/src/cf-do/.wrangler/tmp/dev-qbho19/worker.js.map +0 -8
  33. package/src/cf-do/ARCHITECTURE.md +0 -93
  34. package/src/cf-do/CHAT_E2E.md +0 -213
  35. package/src/cf-do/watermark.test.ts +0 -103
  36. package/src/cf-do/watermark.ts +0 -118
  37. package/src/cf-do/worker.ts +0 -1041
  38. package/src/cf-do/wrangler.toml +0 -11
  39. package/src/cf-pglite/README.md +0 -19
  40. package/src/change-tracking.ts +0 -25
  41. package/src/child-process.test.ts +0 -147
  42. package/src/child-process.ts +0 -90
  43. package/src/cli-entry.ts +0 -72
  44. package/src/cli.test.ts +0 -40
  45. package/src/cli.ts +0 -1214
  46. package/src/config.ts +0 -150
  47. package/src/do-sql-tracking.test.ts +0 -19
  48. package/src/do-sql-tracking.ts +0 -19
  49. package/src/index.ts +0 -1215
  50. package/src/integration/integration.test.ts +0 -517
  51. package/src/integration/native-binary.guard.test.ts +0 -13
  52. package/src/integration/native-startup.test.ts +0 -44
  53. package/src/integration/replication-latency.test.ts +0 -428
  54. package/src/integration/restore-live-stress.test.ts +0 -433
  55. package/src/integration/restore-reset.test.ts +0 -400
  56. package/src/integration/restore.test.ts +0 -274
  57. package/src/integration/test-permissions.ts +0 -147
  58. package/src/load-config.ts +0 -46
  59. package/src/log.ts +0 -96
  60. package/src/mutex.ts +0 -47
  61. package/src/pg-proxy-browser.singledb.test.ts +0 -233
  62. package/src/pg-proxy-browser.ts +0 -2022
  63. package/src/pg-proxy-do-backend.test.ts +0 -3890
  64. package/src/pg-proxy-do-backend.ts +0 -7191
  65. package/src/pg-proxy.ts +0 -1087
  66. package/src/pg-sqlite-compiler/README.md +0 -53
  67. package/src/pg-sqlite-compiler/catalog/seed.ts +0 -524
  68. package/src/pg-sqlite-compiler/fixtures/pgsqlite/arithmetic.json +0 -307
  69. package/src/pg-sqlite-compiler/fixtures/pgsqlite/array.json +0 -377
  70. package/src/pg-sqlite-compiler/fixtures/pgsqlite/cast.json +0 -12
  71. package/src/pg-sqlite-compiler/fixtures/pgsqlite/catalog.json +0 -447
  72. package/src/pg-sqlite-compiler/fixtures/pgsqlite/create-table.json +0 -32
  73. package/src/pg-sqlite-compiler/fixtures/pgsqlite/datetime.json +0 -397
  74. package/src/pg-sqlite-compiler/fixtures/pgsqlite/enum.json +0 -337
  75. package/src/pg-sqlite-compiler/fixtures/pgsqlite/insert.json +0 -337
  76. package/src/pg-sqlite-compiler/fixtures/pgsqlite/json.json +0 -537
  77. package/src/pg-sqlite-compiler/fixtures/pgsqlite/misc.json +0 -1837
  78. package/src/pg-sqlite-compiler/index.ts +0 -73
  79. package/src/pg-sqlite-compiler/integration.test.ts +0 -136
  80. package/src/pg-sqlite-compiler/passes/ast-utils.ts +0 -113
  81. package/src/pg-sqlite-compiler/passes/catalog.ts +0 -65
  82. package/src/pg-sqlite-compiler/passes/datetime.ts +0 -74
  83. package/src/pg-sqlite-compiler/passes/index.ts +0 -49
  84. package/src/pg-sqlite-compiler/passes/types.ts +0 -156
  85. package/src/pg-sqlite-compiler/smoke.test.ts +0 -69
  86. package/src/pg-sqlite-compiler/test/catalog.test.ts +0 -171
  87. package/src/pg-sqlite-compiler/test/corpus.test.ts +0 -161
  88. package/src/pg-sqlite-compiler/test/datetime.oracle.test.ts +0 -102
  89. package/src/pg-sqlite-compiler/test/oracle.ts +0 -237
  90. package/src/pg-sqlite-compiler/test/types.test.ts +0 -109
  91. package/src/pg-sqlite-compiler/types.ts +0 -63
  92. package/src/pglite-ipc.test.ts +0 -116
  93. package/src/pglite-ipc.ts +0 -266
  94. package/src/pglite-manager.ts +0 -557
  95. package/src/pglite-web-proxy.test.ts +0 -57
  96. package/src/pglite-web-proxy.ts +0 -221
  97. package/src/pglite-web-worker.ts +0 -152
  98. package/src/pglite-worker-thread.ts +0 -253
  99. package/src/port.ts +0 -25
  100. package/src/process-title.ts +0 -9
  101. package/src/recovery.ts +0 -155
  102. package/src/replication/change-tracker.test.ts +0 -357
  103. package/src/replication/change-tracker.ts +0 -279
  104. package/src/replication/handler.test.ts +0 -511
  105. package/src/replication/handler.ts +0 -1190
  106. package/src/replication/pgoutput-encoder.test.ts +0 -697
  107. package/src/replication/pgoutput-encoder.ts +0 -373
  108. package/src/replication/tcp-replication.test.ts +0 -876
  109. package/src/replication/zero-compat.test.ts +0 -1150
  110. package/src/restore-stress.test.ts +0 -188
  111. package/src/s3-local.ts +0 -203
  112. package/src/shim/hooks.mjs +0 -120
  113. package/src/shim/register.mjs +0 -4
  114. package/src/sqlite-mode/apply-mode.ts +0 -224
  115. package/src/sqlite-mode/index.ts +0 -15
  116. package/src/sqlite-mode/native-binary.ts +0 -89
  117. package/src/sqlite-mode/package-resolve.ts +0 -17
  118. package/src/sqlite-mode/resolve-mode.ts +0 -80
  119. package/src/sqlite-mode/shim-template.ts +0 -159
  120. package/src/sqlite-mode/sqlite-mode.test.ts +0 -427
  121. package/src/sqlite-mode/types.ts +0 -30
  122. package/src/vite-plugin.ts +0 -67
  123. package/src/wasm-sqlite.test.ts +0 -537
  124. package/src/worker/browser-admin.ts +0 -52
  125. package/src/worker/browser-build-config.test.ts +0 -71
  126. package/src/worker/browser-build-config.ts +0 -109
  127. package/src/worker/browser-embed-admin.test.ts +0 -75
  128. package/src/worker/browser-embed.ts +0 -345
  129. package/src/worker/cf-patches.ts +0 -384
  130. package/src/worker/embed-integration.test.ts +0 -321
  131. package/src/worker/index.ts +0 -138
  132. package/src/worker/shims/fastify.test.ts +0 -255
  133. package/src/worker/shims/fastify.ts +0 -306
  134. package/src/worker/shims/http-service.test.ts +0 -355
  135. package/src/worker/shims/http-service.ts +0 -293
  136. package/src/worker/shims/node-stub.ts +0 -290
  137. package/src/worker/shims/oxfmt.ts +0 -3
  138. package/src/worker/shims/postgres-browser.ts +0 -59
  139. package/src/worker/shims/postgres-socket.test.ts +0 -576
  140. package/src/worker/shims/postgres-socket.ts +0 -310
  141. package/src/worker/shims/postgres.test.ts +0 -364
  142. package/src/worker/shims/postgres.ts +0 -1454
  143. package/src/worker/shims/sqlite-browser.test.ts +0 -233
  144. package/src/worker/shims/sqlite-browser.ts +0 -175
  145. package/src/worker/shims/sqlite.test.ts +0 -786
  146. package/src/worker/shims/sqlite.ts +0 -978
  147. package/src/worker/shims/stream-browser.ts +0 -15
  148. package/src/worker/shims/ws-browser.test.ts +0 -205
  149. package/src/worker/shims/ws-browser.ts +0 -248
  150. package/src/worker/shims/ws.test.ts +0 -288
  151. package/src/worker/shims/ws.ts +0 -467
  152. package/src/worker/shims/zero-process-env.ts +0 -11
  153. package/src/worker/types.ts +0 -75
  154. package/src/worker/worker-integration.test.ts +0 -223
  155. package/src/worker/worker.test.ts +0 -136
  156. package/src/worker/zero-cache-embed-cf.ts +0 -463
  157. package/src/worker/zero-cache-embed.ts +0 -277
@@ -1,8 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../worker.ts", "../../../../do-sql-tracking.ts", "../../../watermark.ts", "../../../../../../soot/node_modules/wrangler/templates/middleware/middleware-ensure-req-body-drained.ts", "../../../../../../soot/node_modules/wrangler/templates/middleware/middleware-miniflare3-json-error.ts", "../bundle-vYmw0E/middleware-insertion-facade.js", "../../../../../../soot/node_modules/wrangler/templates/middleware/common.ts", "../bundle-vYmw0E/middleware-loader.entry.ts"],
4
- "sourceRoot": "/Users/n8/orez/src/cf-do/.wrangler/tmp/dev-qbho19",
5
- "sourcesContent": ["// @ts-nocheck \u2014 cloudflare:workers types not available in orez\nimport { DurableObject } from 'cloudflare:workers'\n\nimport { trackedChangeRow } from '../do-sql-tracking.js'\nimport { DurableWatermarkState } from './watermark.js'\n\n/**\n * zero-do: Durable Object that exposes raw SQL execution over ctx.storage.sql.\n *\n * The production Cloudflare path runs real zero-cache via\n * src/worker/zero-cache-embed-cf.ts, with DoBackend calling this DO for\n * Postgres-protocol-backed SQL. The WS sync handler here is kept for\n * development/protocol experiments only; it is not the production replacement\n * for zero-cache.\n *\n * Modes:\n * WS /sync/v49/connect \u2014 bespoke Zero sync protocol (dev/protocol testing)\n * POST /exec \u2014 raw SQL execution (from DoBackend adapter)\n * POST /batch \u2014 atomic batch execution via ctx.storage.transaction()\n */\n\ninterface Env {\n ZERO_DO: DurableObjectNamespace\n}\ninterface SchemaTable {\n primaryKey: string[]\n columns: Record<string, { type: string; optional?: boolean }>\n}\ninterface ClientSchema {\n tables: Record<string, SchemaTable>\n}\ninterface DesiredQuery {\n hash: string\n tableNames: string[]\n}\ninterface DesiredQueryPatchOp {\n op: 'put' | 'del' | 'clear'\n hash?: string\n name?: string\n ast?: any\n}\ninterface CrudOp {\n op: 'insert' | 'update' | 'upsert' | 'delete'\n tableName: string\n value?: Record<string, unknown>\n primaryKey?: string[]\n}\ninterface PushMutation {\n type: string\n name: string\n clientID: string\n id: number\n args: unknown[]\n}\ninterface PushBody {\n clientGroupID?: string\n mutations: PushMutation[]\n}\ninterface SqlTrack {\n tableName: string\n operation: 'INSERT' | 'UPDATE' | 'DELETE'\n returnRows?: boolean\n rowColumns?: string[]\n}\ninterface SqlExecStatement {\n sql: string\n params?: unknown[]\n track?: SqlTrack\n}\ninterface SocketAttachment {\n clientID: string\n clientGroupID: string\n userID: string\n cookie: string | null\n initialized: boolean\n desiredTableNames: string[]\n desiredQueries: DesiredQuery[]\n}\ninterface HibernatableWebSocket extends WebSocket {\n serializeAttachment(value: SocketAttachment): void\n deserializeAttachment(): SocketAttachment | undefined\n}\n\nconst SCHEMA_VERSION = 1\nconst SQL_ERROR_SNIPPET_RADIUS = 1600\nconst SQL_ERROR_FALLBACK_LIMIT = 4000\n\nfunction quoteIdent(name: string): string {\n return `\"${name.replace(/\"/g, '\"\"')}\"`\n}\n\nfunction sqliteErrorOffset(message: string): number | null {\n const marker = 'offset '\n const start = message.indexOf(marker)\n if (start < 0) return null\n let index = start + marker.length\n let digits = ''\n while (index < message.length) {\n const code = message.charCodeAt(index)\n if (code < 48 || code > 57) break\n digits += message[index]\n index++\n }\n if (!digits) return null\n const offset = Number(digits)\n return Number.isFinite(offset) ? offset : null\n}\n\nfunction sqlErrorSnippet(sql: string, message: string): string {\n const offset = sqliteErrorOffset(message)\n if (offset !== null) {\n const start = Math.max(0, offset - SQL_ERROR_SNIPPET_RADIUS)\n const end = Math.min(sql.length, offset + SQL_ERROR_SNIPPET_RADIUS)\n return `${start > 0 ? '...' : ''}${sql.slice(start, end)}${end < sql.length ? '...' : ''}`\n }\n if (sql.length <= SQL_ERROR_FALLBACK_LIMIT) return sql\n return `${sql.slice(0, SQL_ERROR_FALLBACK_LIMIT)}...`\n}\n\nexport class ZeroDO extends DurableObject {\n private sql: any\n private watermarks: DurableWatermarkState\n private schemaTables = new Set<string>()\n private tableSchemas = new Map<string, SchemaTable>()\n\n constructor(ctx: DurableObjectState, env: Env) {\n super(ctx, env)\n this.sql = ctx.storage.sql\n this.watermarks = new DurableWatermarkState(this.sql)\n }\n\n async fetch(request: Request): Promise<Response> {\n const url = new URL(request.url)\n if (request.method === 'OPTIONS') {\n return new Response(null, {\n headers: {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',\n 'Access-Control-Allow-Headers': '*',\n },\n })\n }\n if (url.pathname.startsWith('/sync/v') && url.pathname.endsWith('/connect'))\n return this.handleSyncConnect(request, url)\n if (\n (url.pathname === '/zero/push' || url.pathname === '/api/zero/push') &&\n request.method === 'POST'\n )\n return this.handleHttpPush(request)\n if (url.pathname === '/exec' && request.method === 'POST')\n return this.handleExec(request)\n if (url.pathname === '/batch' && request.method === 'POST')\n return this.handleBatch(request)\n if (\n url.pathname === '/changes' &&\n (request.method === 'GET' || request.method === 'POST')\n )\n return this.handleChanges(request, url)\n if (url.pathname === '/notify' && request.method === 'POST')\n return Response.json({ ok: true, cookie: this.cookie() })\n return new Response('not found', { status: 404 })\n }\n\n // \u2500\u2500 Zero sync protocol \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private handleSyncConnect(request: Request, url: URL): Response {\n if (request.headers.get('upgrade')?.toLowerCase() !== 'websocket') {\n return new Response('expected websocket upgrade', { status: 426 })\n }\n const pair = new WebSocketPair()\n const client = pair[0]\n const server = pair[1] as HibernatableWebSocket\n\n const clientID = url.searchParams.get('clientID') || 'anon'\n const clientGroupID = url.searchParams.get('clientGroupID') || 'default'\n const userID = url.searchParams.get('userID') || 'anon'\n const wsid = url.searchParams.get('wsid') || crypto.randomUUID()\n const baseCookie = url.searchParams.get('baseCookie')\n\n this.ctx.acceptWebSocket(server)\n server.serializeAttachment({\n clientID,\n clientGroupID,\n userID,\n cookie: baseCookie ? baseCookie : null,\n initialized: false,\n desiredTableNames: [],\n desiredQueries: [],\n })\n this.sendJSON(server, ['connected', { wsid, timestamp: Date.now() }])\n\n const secProtocol = request.headers.get('sec-websocket-protocol')\n if (secProtocol) {\n const initData = decodeInitConnection(secProtocol)\n if (initData) {\n const clientSchema = initData[1]?.clientSchema as ClientSchema | undefined\n const patch = (initData[1]?.desiredQueriesPatch || []) as DesiredQueryPatchOp[]\n this.applyDesiredQueries(server, patch, clientSchema)\n }\n }\n return new Response(null, {\n status: 101,\n headers: secProtocol ? { 'Sec-WebSocket-Protocol': secProtocol } : undefined,\n webSocket: client,\n } as ResponseInit & { webSocket: WebSocket })\n }\n\n async webSocketMessage(socket: WebSocket, messageData: string | ArrayBuffer) {\n this.watermarks.ensureTables()\n const ws = socket as HibernatableWebSocket\n const attachment = this.readSocketAttachment(ws)\n if (!attachment) return\n const message = this.parseMessage(messageData)\n if (!message) return\n const body = message[1] || {}\n\n switch (message[0]) {\n case 'initConnection':\n case 'changeDesiredQueries':\n this.applyDesiredQueries(\n ws,\n (body.desiredQueriesPatch || []) as DesiredQueryPatchOp[],\n body.clientSchema as ClientSchema | undefined\n )\n break\n case 'push':\n this.handlePush(ws, attachment, message[1] as PushBody)\n break\n case 'pull':\n this.handlePull(ws, message[1] as any)\n break\n case 'ping':\n this.sendJSON(ws, ['pong', {}])\n break\n }\n }\n\n webSocketClose(\n _socket: WebSocket,\n _code: number,\n _reason: string,\n _wasClean: boolean\n ) {}\n\n private applyDesiredQueries(\n socket: HibernatableWebSocket,\n patch: DesiredQueryPatchOp[],\n clientSchema?: ClientSchema\n ) {\n const attachment = this.readSocketAttachment(socket)\n if (!attachment) return\n if (clientSchema) this.ensureSchemaTables(clientSchema)\n\n let nextAttachment = this.applyDesiredQueryPatch(attachment, patch)\n socket.serializeAttachment(nextAttachment)\n\n if (!nextAttachment.initialized) {\n nextAttachment = this.sendSyncPoke(\n socket,\n { ...nextAttachment, initialized: true },\n { lastMutationIDChanges: {}, rowsPatch: [] }\n )\n }\n\n if (patch.length === 0) return\n\n const rowsPatch = [\n { op: 'clear' as const },\n ...this.rowsPatchForTables(nextAttachment.desiredTableNames),\n ]\n this.sendSyncPoke(socket, nextAttachment, {\n gotQueriesPatch: this.gotQueriesPatch(patch),\n rowsPatch,\n })\n }\n\n private applyDesiredQueryPatch(\n attachment: SocketAttachment,\n patch: DesiredQueryPatchOp[]\n ): SocketAttachment {\n const desiredQueries = new Map<string, string[]>()\n for (const query of attachment.desiredQueries || [])\n desiredQueries.set(query.hash, query.tableNames)\n\n for (const op of patch) {\n if (op.op === 'clear') {\n desiredQueries.clear()\n } else if (op.op === 'put' && op.hash) {\n desiredQueries.set(op.hash, this.resolveTablesFromPatch([op]))\n } else if (op.op === 'del' && op.hash) {\n desiredQueries.delete(op.hash)\n }\n }\n\n const queries = [...desiredQueries.entries()].map(([hash, tableNames]) => ({\n hash,\n tableNames,\n }))\n return {\n ...attachment,\n desiredQueries: queries,\n desiredTableNames: [...new Set(queries.flatMap((query) => query.tableNames))],\n }\n }\n\n private gotQueriesPatch(patch: DesiredQueryPatchOp[]) {\n const got: Array<{ op: 'put' | 'del'; hash: string } | { op: 'clear' }> = []\n for (const op of patch) {\n if (op.op === 'clear') got.push({ op: 'clear' })\n else if (op.hash) got.push({ op: op.op, hash: op.hash })\n }\n return got\n }\n\n private rowsPatchForTables(tableNames: string[]): any[] {\n const rowsPatch: any[] = []\n for (const tn of tableNames) {\n if (!this.tableExists(tn)) continue\n for (const row of this.readAllRows(tn))\n rowsPatch.push({ op: 'put', tableName: tn, value: row })\n }\n return rowsPatch\n }\n\n private resolveTablesFromPatch(patch: DesiredQueryPatchOp[]): string[] {\n const tables: string[] = []\n for (const op of patch) {\n const tableFromName = this.tableNameFromOperationName(op.name)\n if (tableFromName) tables.push(tableFromName)\n if (op.ast) this.extractTableFromAST(op.ast, tables)\n }\n return tables\n }\n\n private extractTableFromAST(ast: any, tables: string[]) {\n if (ast?.table) tables.push(ast.table)\n if (ast?.related)\n for (const rel of ast.related) {\n if (rel?.subquery?.table) tables.push(rel.subquery.table)\n if (rel?.subquery?.related) this.extractTableFromAST(rel.subquery, tables)\n }\n }\n\n private handlePush(socket: WebSocket, attachment: SocketAttachment, body: PushBody) {\n const mutations = Array.isArray(body?.mutations) ? body.mutations : []\n const before = this.watermark()\n const mutationResults: any[] = []\n const lastMutationIDChanges: Record<string, number> = {}\n for (const m of mutations) {\n const result = this.applyMutation(m)\n mutationResults.push({ id: { clientID: m.clientID, id: m.id }, result })\n lastMutationIDChanges[m.clientID] = m.id\n }\n this.sendJSON(socket, ['pushResponse', { mutations: mutationResults }])\n const after = this.watermark()\n const changes = after > before ? this.readChangesSince(before) : []\n const rowsPatch = changes.map((c) => this.syncRowPatchFromChange(c))\n if (Object.keys(lastMutationIDChanges).length > 0 || rowsPatch.length > 0)\n this.broadcastMutationPoke(attachment, {\n lastMutationIDChanges,\n rowsPatch,\n })\n }\n\n private async handleHttpPush(request: Request): Promise<Response> {\n try {\n const body = (await request.json()) as any\n const before = this.watermark()\n const mutations = Array.isArray(body?.mutations) ? body.mutations : []\n const mutationResults: any[] = []\n const lastMutationIDChanges: Record<string, number> = {}\n for (const m of mutations) {\n const result = this.applyMutation(m)\n mutationResults.push({ id: { clientID: m.clientID, id: m.id }, result })\n lastMutationIDChanges[m.clientID] = m.id\n }\n const after = this.watermark()\n const changes = after > before ? this.readChangesSince(before) : []\n const rowsPatch = changes.map((c) => this.syncRowPatchFromChange(c))\n if (Object.keys(lastMutationIDChanges).length > 0 || rowsPatch.length > 0)\n this.broadcastPoke(body?.clientGroupID || 'default', {\n lastMutationIDChanges,\n rowsPatch,\n })\n return Response.json({ mutations: mutationResults })\n } catch (err: any) {\n return Response.json({ error: err.message }, { status: 500 })\n }\n }\n\n private handlePull(socket: HibernatableWebSocket, body: { requestID?: string }) {\n this.sendJSON(socket, [\n 'pull',\n {\n requestID: body?.requestID || crypto.randomUUID(),\n cookie: this.cookie(),\n lastMutationIDChanges: {},\n patch: [],\n },\n ])\n }\n\n // \u2500\u2500 SQL execution endpoints \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async handleExec(request: Request): Promise<Response> {\n let sql = ''\n try {\n const body = (await request.json()) as {\n sql: string\n params?: unknown[]\n track?: SqlTrack\n }\n sql = body.sql\n const params = Array.isArray(body.params) ? body.params : []\n // Only wrap in ctx.storage.transaction() when the call has change-tracking\n // side effects (executeSQL writes BOTH the user table AND _zero_changes,\n // which must commit together to keep source-tab sync flicker-free). A\n // bare /exec is single-statement and ctx.storage.sql already serializes;\n // the transaction wrap was adding ~2-5ms \u00D7 every call, which on chat's\n // 27k-stmt boot pushed orez backend startup past chat's 60s wait-for-port.\n const result = body.track\n ? await this.ctx.storage.transaction(() =>\n this.executeSQL(sql, params, body.track)\n )\n : this.executeSQL(sql, params)\n return Response.json(result)\n } catch (err: any) {\n const suffix = sql ? ` while executing: ${sqlErrorSnippet(sql, err.message)}` : ''\n console.error(`[exec-500] ${err.message} :: SQL=${sql.slice(0, 800)}`)\n return Response.json({ error: `${err.message}${suffix}` }, { status: 500 })\n }\n }\n\n /** Execute multiple statements atomically via ctx.storage.transaction() */\n private async handleBatch(request: Request): Promise<Response> {\n try {\n const { statements } = (await request.json()) as {\n statements: Array<string | SqlExecStatement>\n }\n const allRows = await this.ctx.storage.transaction(() => {\n const results: any[] = []\n for (const statement of statements) {\n const item = typeof statement === 'string' ? { sql: statement } : statement\n if (!item?.sql?.trim()) continue\n try {\n results.push(\n this.executeSQL(\n item.sql,\n Array.isArray(item.params) ? item.params : [],\n item.track\n )\n )\n } catch (err: any) {\n throw new Error(\n `${err.message} while executing: ${sqlErrorSnippet(item.sql, err.message)}`\n )\n }\n }\n return results\n })\n return Response.json({ results: allRows })\n } catch (err: any) {\n return Response.json({ error: err.message }, { status: 500 })\n }\n }\n\n private async handleChanges(request: Request, url: URL): Promise<Response> {\n try {\n let watermark = Number(\n url.searchParams.get('watermark') ?? url.searchParams.get('since') ?? 0\n )\n let limit = Number(url.searchParams.get('limit') ?? 1000)\n if (request.method === 'POST') {\n const body = (await request.json().catch(() => ({}))) as {\n watermark?: unknown\n since?: unknown\n limit?: unknown\n }\n watermark = Number(body.watermark ?? body.since ?? watermark)\n limit = Number(body.limit ?? limit)\n }\n if (!Number.isFinite(watermark) || watermark < 0) watermark = 0\n if (!Number.isFinite(limit) || limit <= 0) limit = 1000\n return Response.json({\n watermark: this.watermark(),\n changes: this.readChangesSince(watermark).slice(0, Math.min(limit, 10_000)),\n })\n } catch (err: any) {\n return Response.json({ error: err.message }, { status: 500 })\n }\n }\n\n private executeSQL(\n sql: string,\n params: unknown[] = [],\n track?: SqlTrack\n ): { rows: Record<string, unknown>[]; columns: string[]; affectedRows?: number } {\n const cursor = this.sql.exec(sql, ...params)\n const columns = Array.isArray(cursor.columnNames) ? cursor.columnNames : []\n const rows = this.cursorRows(cursor)\n if (!track) return { rows, columns }\n\n for (const row of rows) {\n const trackedRow = trackedChangeRow(row, track)\n if (track.operation === 'DELETE')\n this.appendTrackedChange(track.tableName, 'DELETE', null, trackedRow)\n else this.appendTrackedChange(track.tableName, track.operation, trackedRow, null)\n }\n\n return {\n rows: track.returnRows ? rows : [],\n columns: track.returnRows ? columns : [],\n affectedRows: rows.length,\n }\n }\n\n private cursorRows(cursor: any): Record<string, unknown>[] {\n return cursor.toArray().map((row: any) => {\n const obj: Record<string, unknown> = {}\n for (const k of Object.keys(row)) obj[k] = row[k]\n return obj\n })\n }\n\n // \u2500\u2500 CRUD operations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private applyMutation(mutation: PushMutation) {\n if (mutation.type === 'crud' && mutation.name === '_zero_crud') {\n return this.applyCrudMutation(mutation)\n }\n if (mutation.name === '_zero_cleanupResults') return {}\n if (mutation.type === 'custom') return this.applyTableMutation(mutation)\n return {\n error: 'app',\n message: `unsupported mutation ${mutation.type}:${mutation.name}`,\n }\n }\n\n private applyTableMutation(mutation: PushMutation) {\n const [tableName, action] = this.tableActionFromMutationName(mutation.name)\n if (!tableName || !action)\n return { error: 'app', message: `invalid mutation name ${mutation.name}` }\n if (!this.tableExists(tableName))\n return { error: 'app', message: `unknown table ${tableName}` }\n const value = (mutation.args[0] || {}) as Record<string, unknown>\n const primaryKey = this.primaryKeyForTable(tableName, [])\n\n if (action === 'insert') this.insertRow(tableName, value, primaryKey)\n else if (action === 'upsert') this.upsertRow(tableName, value, primaryKey)\n else if (action === 'delete') this.deleteRow(tableName, value, primaryKey)\n else this.updateRow(tableName, value, primaryKey)\n return {}\n }\n\n private tableActionFromMutationName(name: string): [string, string] {\n if (name.includes('|')) return name.split('|', 2) as [string, string]\n return name.split('.', 2) as [string, string]\n }\n\n private tableNameFromOperationName(name?: string): string | null {\n if (!name) return null\n return name.split(/[.|]/, 1)[0] || null\n }\n\n private applyCrudMutation(mutation: PushMutation) {\n const arg = mutation.args[0] as { ops?: CrudOp[] } | undefined\n const ops = Array.isArray(arg?.ops) ? arg.ops : []\n for (const crud of ops) {\n if (!crud?.tableName) return { error: 'app', message: 'invalid crud mutation' }\n if (!this.tableExists(crud.tableName))\n return { error: 'app', message: `unknown table ${crud.tableName}` }\n const value = crud.value || {}\n const primaryKey = this.primaryKeyForTable(crud.tableName, crud.primaryKey || [])\n if (crud.op === 'insert') this.insertRow(crud.tableName, value, primaryKey)\n else if (crud.op === 'upsert') this.upsertRow(crud.tableName, value, primaryKey)\n else if (crud.op === 'update') this.updateRow(crud.tableName, value, primaryKey)\n else if (crud.op === 'delete') this.deleteRow(crud.tableName, value, primaryKey)\n }\n return {}\n }\n\n private insertRow(tn: string, value: Record<string, unknown>, pk: string[]) {\n if (this.readRowByPrimaryKey(tn, value, pk)) return\n const row = this.storageRow(tn, value, true)\n const cols = Object.keys(row)\n if (!cols.length) return\n const qc = cols.map((c) => quoteIdent(c)).join(', ')\n const ph = cols.map(() => '?').join(', ')\n this.sql.exec(\n `INSERT INTO ${quoteIdent(tn)} (${qc}) VALUES (${ph})`,\n ...cols.map((c) => row[c])\n )\n const next = this.readRowByPrimaryKey(tn, value, pk) || this.normalizeRow(tn, row)\n this.appendChange(tn, 'INSERT', next, null)\n }\n\n private upsertRow(tn: string, value: Record<string, unknown>, pk: string[]) {\n const existing = this.readRowByPrimaryKey(tn, value, pk)\n if (existing) {\n this.updateRow(tn, value, pk)\n return\n }\n this.insertRow(tn, value, pk)\n }\n\n private updateRow(tn: string, value: Record<string, unknown>, pk: string[]) {\n if (!pk.length) return\n const existing = this.readRowByPrimaryKey(tn, value, pk)\n if (!existing) return\n const nk = Object.keys(value).filter((c) => !pk.includes(c))\n if (!nk.length) return\n const storage = this.storageRow(tn, value, false)\n this.sql.exec(\n `UPDATE ${quoteIdent(tn)} SET ${nk.map((c) => `${quoteIdent(c)} = ?`).join(', ')} WHERE ${this.primaryKeyWhere(pk)}`,\n ...nk.map((c) => storage[c]),\n ...pk.map((c) => this.storageColumnValue(tn, c, value[c]))\n )\n const next = this.readRowByPrimaryKey(tn, value, pk)\n if (next) this.appendChange(tn, 'UPDATE', next, existing)\n }\n\n private deleteRow(tn: string, value: Record<string, unknown>, pk: string[]) {\n if (!pk.length) return\n const existing = this.readRowByPrimaryKey(tn, value, pk)\n if (!existing) return\n this.sql.exec(\n `DELETE FROM ${quoteIdent(tn)} WHERE ${this.primaryKeyWhere(pk)}`,\n ...pk.map((c) => this.storageColumnValue(tn, c, value[c]))\n )\n this.appendChange(tn, 'DELETE', null, existing)\n }\n\n private appendChange(\n tn: string,\n op: 'INSERT' | 'UPDATE' | 'DELETE',\n rowData: Record<string, unknown> | null,\n oldData: Record<string, unknown> | null\n ) {\n this.appendTrackedChange(tn, op, rowData, oldData)\n }\n\n private appendTrackedChange(\n tableName: string,\n op: 'INSERT' | 'UPDATE' | 'DELETE',\n rowData: Record<string, unknown> | null,\n oldData: Record<string, unknown> | null\n ) {\n this.watermarks.ensureTables()\n const watermark = this.watermarks.next()\n this.sql.exec(\n 'INSERT INTO _zero_changes (watermark, table_name, op, row_data, old_data) VALUES (?, ?, ?, ?, ?)',\n watermark,\n tableName,\n op,\n rowData ? JSON.stringify(rowData) : null,\n oldData ? JSON.stringify(oldData) : null\n )\n this.watermarks.mark(watermark)\n }\n\n private readChangesSince(watermark: number) {\n this.watermarks.ensureTables()\n return this.sql\n .exec(\n 'SELECT watermark, table_name, op, row_data, old_data FROM _zero_changes WHERE watermark > ? ORDER BY watermark',\n watermark\n )\n .toArray()\n .map((row: any) => ({\n watermark: Number(row.watermark),\n tableName: String(row.table_name),\n op: String(row.op),\n rowData: row.row_data ? JSON.parse(String(row.row_data)) : null,\n oldData: row.old_data ? JSON.parse(String(row.old_data)) : null,\n }))\n }\n\n private watermark(): number {\n return this.watermarks.current()\n }\n\n private ensureSchemaTables(clientSchema: ClientSchema) {\n this.ensureSchemaMetadataTable()\n for (const [name, def] of Object.entries(clientSchema.tables)) {\n this.tableSchemas.set(name, def)\n this.sql.exec(\n 'INSERT OR REPLACE INTO _zero_schema_tables (name, schema_json) VALUES (?, ?)',\n name,\n JSON.stringify(def)\n )\n if (this.schemaTables.has(name)) continue\n const pk = def.primaryKey.map((c) => quoteIdent(c))\n const pkClause = pk.length ? `, PRIMARY KEY (${pk.join(', ')})` : ''\n const colDefs = Object.entries(def.columns).map(([cn, cd]) => {\n const t: Record<string, string> = {\n string: 'TEXT',\n number: 'REAL',\n boolean: 'INTEGER',\n json: 'TEXT',\n bigint: 'TEXT',\n }\n return `${quoteIdent(cn)} ${t[cd.type] || 'TEXT'}`\n })\n this.sql.exec(\n `CREATE TABLE IF NOT EXISTS ${quoteIdent(name)} (${colDefs.join(', ')}${pkClause})`\n )\n this.schemaTables.add(name)\n }\n }\n\n private ensureSchemaMetadataTable() {\n this.sql.exec(\n 'CREATE TABLE IF NOT EXISTS _zero_schema_tables (name TEXT PRIMARY KEY, schema_json TEXT NOT NULL)'\n )\n }\n\n private schemaForTable(tableName: string): SchemaTable | undefined {\n const cached = this.tableSchemas.get(tableName)\n if (cached) return cached\n try {\n this.ensureSchemaMetadataTable()\n const row = this.sql\n .exec('SELECT schema_json FROM _zero_schema_tables WHERE name = ?', tableName)\n .one()\n if (!row?.schema_json) return undefined\n const schema = JSON.parse(String(row.schema_json)) as SchemaTable\n this.tableSchemas.set(tableName, schema)\n return schema\n } catch {\n return undefined\n }\n }\n\n private tableExists(n: string): boolean {\n try {\n return !!this.sql\n .exec(\"SELECT name FROM sqlite_master WHERE type='table' AND name=?\", n)\n .one()\n } catch {\n return false\n }\n }\n\n private readAllRows(tn: string): Record<string, unknown>[] {\n try {\n return this.sql\n .exec(`SELECT * FROM ${quoteIdent(tn)}`)\n .toArray()\n .map((row: any) => this.normalizeRow(tn, row))\n } catch {\n return []\n }\n }\n\n private readRowByPrimaryKey(\n tn: string,\n value: Record<string, unknown>,\n pk: string[]\n ): Record<string, unknown> | null {\n if (!pk.length) return null\n try {\n const row = this.sql\n .exec(\n `SELECT * FROM ${quoteIdent(tn)} WHERE ${this.primaryKeyWhere(pk)}`,\n ...pk.map((c) => this.storageColumnValue(tn, c, value[c]))\n )\n .one()\n return row ? this.normalizeRow(tn, row) : null\n } catch {\n return null\n }\n }\n\n private primaryKeyWhere(pk: string[]): string {\n return pk.map((c) => `${quoteIdent(c)} = ?`).join(' AND ')\n }\n\n private primaryKeyForTable(tn: string, fallback: string[]): string[] {\n const schema = this.schemaForTable(tn)\n if (schema?.primaryKey?.length) return schema.primaryKey\n return fallback\n }\n\n private storageRow(\n tn: string,\n value: Record<string, unknown>,\n includeMissingSchemaColumns: boolean\n ): Record<string, unknown> {\n const schema = this.schemaForTable(tn)\n const row: Record<string, unknown> = {}\n if (schema && includeMissingSchemaColumns) {\n for (const column of Object.keys(schema.columns))\n row[column] = this.storageColumnValue(tn, column, value[column] ?? null)\n }\n for (const column of Object.keys(value)) {\n if (value[column] !== undefined)\n row[column] = this.storageColumnValue(tn, column, value[column])\n }\n return row\n }\n\n private storageColumnValue(tn: string, column: string, value: unknown): unknown {\n if (value === undefined || value === null) return null\n const type = this.schemaForTable(tn)?.columns?.[column]?.type\n if (type === 'boolean') return value ? 1 : 0\n if (type === 'json') return typeof value === 'string' ? value : JSON.stringify(value)\n if (type === 'number') return Number(value)\n if (type === 'bigint') return String(value)\n return value\n }\n\n private normalizeRow(\n tn: string,\n row: Record<string, unknown>\n ): Record<string, unknown> {\n const schema = this.schemaForTable(tn)\n const normalized: Record<string, unknown> = {}\n for (const key of Object.keys(row)) {\n const type = schema?.columns?.[key]?.type\n const value = row[key]\n if (value === null || value === undefined) {\n normalized[key] = null\n } else if (type === 'boolean') {\n normalized[key] =\n value === true || value === 1 || value === '1' || value === 'true'\n } else if (type === 'number') {\n normalized[key] = Number(value)\n } else if (type === 'json' && typeof value === 'string') {\n try {\n normalized[key] = JSON.parse(value)\n } catch {\n normalized[key] = value\n }\n } else {\n normalized[key] = value\n }\n }\n return normalized\n }\n\n private sendSyncPoke(\n socket: HibernatableWebSocket,\n attachment: SocketAttachment,\n part: {\n rowsPatch?: any[]\n gotQueriesPatch?: any[]\n lastMutationIDChanges?: Record<string, number>\n }\n ): SocketAttachment {\n const cookie = this.nextCookie()\n const pokeID = crypto.randomUUID()\n this.sendJSON(socket, [\n 'pokeStart',\n {\n pokeID,\n baseCookie: attachment.cookie,\n schemaVersions: {\n minSupportedVersion: SCHEMA_VERSION,\n maxSupportedVersion: SCHEMA_VERSION,\n },\n timestamp: Date.now(),\n },\n ])\n this.sendJSON(socket, ['pokePart', { pokeID, ...part }])\n this.sendJSON(socket, ['pokeEnd', { pokeID, cookie }])\n const nextAttachment = { ...attachment, cookie }\n socket.serializeAttachment(nextAttachment)\n return nextAttachment\n }\n\n private broadcastPoke(\n clientGroupID: string,\n part: { rowsPatch?: any[]; lastMutationIDChanges?: Record<string, number> }\n ) {\n for (const socket of this.ctx.getWebSockets()) {\n const ws = socket as HibernatableWebSocket\n const attachment = this.readSocketAttachment(ws)\n if (!attachment) continue\n if (attachment.clientGroupID !== clientGroupID) continue\n this.sendSyncPoke(ws, attachment, part)\n }\n }\n\n private broadcastMutationPoke(\n sourceAttachment: SocketAttachment,\n part: { rowsPatch?: any[]; lastMutationIDChanges?: Record<string, number> }\n ) {\n const rowsPatch = part.rowsPatch || []\n const changedTables = new Set(\n rowsPatch\n .map((op) => op?.tableName)\n .filter((tableName): tableName is string => !!tableName)\n )\n const hasLastMutationIDChanges =\n Object.keys(part.lastMutationIDChanges || {}).length > 0\n\n for (const socket of this.ctx.getWebSockets()) {\n const ws = socket as HibernatableWebSocket\n const attachment = this.readSocketAttachment(ws)\n if (!attachment) continue\n if (attachment.userID !== sourceAttachment.userID) continue\n\n const isSourceClientGroup =\n attachment.clientGroupID === sourceAttachment.clientGroupID\n const wantsChangedRows =\n changedTables.size > 0 &&\n attachment.desiredTableNames.some((tableName) => changedTables.has(tableName))\n\n const nextPart: {\n rowsPatch?: any[]\n lastMutationIDChanges?: Record<string, number>\n } = {}\n if (wantsChangedRows) nextPart.rowsPatch = rowsPatch\n if (isSourceClientGroup && hasLastMutationIDChanges)\n nextPart.lastMutationIDChanges = part.lastMutationIDChanges\n\n if (!nextPart.rowsPatch && !nextPart.lastMutationIDChanges) continue\n this.sendSyncPoke(ws, attachment, nextPart)\n }\n }\n\n private syncRowPatchFromChange(change: any): any {\n if (change.op === 'DELETE')\n return {\n op: 'del',\n tableName: change.tableName,\n id: this.primaryKeyValue(change.tableName, change.oldData || {}),\n }\n return {\n op: 'put',\n tableName: change.tableName,\n value: this.normalizeRow(change.tableName, change.rowData || {}),\n }\n }\n\n private primaryKeyValue(\n tableName: string,\n row: Record<string, unknown>\n ): Record<string, unknown> {\n const pk = this.primaryKeyForTable(tableName, [])\n if (pk.length) return Object.fromEntries(pk.map((column) => [column, row[column]]))\n if ('id' in row) return { id: row.id }\n return row\n }\n\n private cookie(): string {\n return String(this.watermark()).padStart(20, '0')\n }\n\n private nextCookie(): string {\n const watermark = this.watermarks.next()\n this.watermarks.mark(watermark)\n return String(watermark).padStart(20, '0')\n }\n\n private readSocketAttachment(socket: HibernatableWebSocket): SocketAttachment | null {\n const attachment = socket.deserializeAttachment()\n if (!attachment) return null\n return {\n ...attachment,\n initialized: attachment.initialized === true,\n desiredTableNames: attachment.desiredTableNames || [],\n desiredQueries: attachment.desiredQueries || [],\n }\n }\n\n private sendJSON(socket: WebSocket, msg: unknown) {\n try {\n socket.send(JSON.stringify(msg))\n } catch {}\n }\n private parseMessage(data: string | ArrayBuffer): unknown {\n try {\n return JSON.parse(typeof data === 'string' ? data : new TextDecoder().decode(data))\n } catch {\n return null\n }\n }\n}\n\nexport default {\n async fetch(request: Request, env: Env): Promise<Response> {\n const url = new URL(request.url)\n const id = env.ZERO_DO.idFromName('singleton')\n if (url.pathname.startsWith('/sync/v') && url.pathname.endsWith('/connect')) {\n return env.ZERO_DO.get(id).fetch(request)\n }\n if (\n (url.pathname === '/zero/push' || url.pathname === '/api/zero/push') &&\n request.method === 'POST'\n ) {\n return env.ZERO_DO.get(id).fetch(request)\n }\n if (url.pathname === '/exec' && request.method === 'POST') {\n return env.ZERO_DO.get(id).fetch(request)\n }\n if (url.pathname === '/batch' && request.method === 'POST') {\n return env.ZERO_DO.get(id).fetch(request)\n }\n if (\n url.pathname === '/changes' &&\n (request.method === 'GET' || request.method === 'POST')\n ) {\n return env.ZERO_DO.get(id).fetch(request)\n }\n if (url.pathname === '/notify' && request.method === 'POST') {\n return env.ZERO_DO.get(id).fetch(request)\n }\n return new Response('not found', { status: 404 })\n },\n}\n\nfunction decodeInitConnection(\n secProtocol: string\n): [string, Record<string, unknown>] | null {\n try {\n const decoded = decodeURIComponent(secProtocol)\n const bytes = Uint8Array.from(atob(decoded), (char) => char.charCodeAt(0))\n const protocols = JSON.parse(new TextDecoder().decode(bytes)) as {\n initConnectionMessage?: unknown\n }\n const message = protocols.initConnectionMessage\n if (Array.isArray(message) && message[0] === 'initConnection') {\n return message as [string, Record<string, unknown>]\n }\n return null\n } catch {\n return null\n }\n}\n\ninterface DurableObjectState {\n storage: { sql: any; transaction<T>(fn: () => T | Promise<T>): Promise<T> }\n acceptWebSocket(socket: WebSocket, tags?: string[]): void\n getWebSockets(tag?: string): WebSocket[]\n}\ninterface WebSocketPair {\n 0: WebSocket\n 1: WebSocket\n}\ndeclare const WebSocketPair: { new (): { 0: WebSocket; 1: WebSocket } }\n", "export const RETURNING_INTERNAL_PREFIX = '__orez_returning_'\n\nexport interface TrackedRowFilter {\n rowColumns?: string[]\n}\n\nexport function trackedChangeRow(\n row: Record<string, unknown>,\n track: TrackedRowFilter\n): Record<string, unknown> {\n const allowed = track.rowColumns ? new Set(track.rowColumns) : null\n const out: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(row)) {\n if (key.startsWith(RETURNING_INTERNAL_PREFIX)) continue\n if (allowed && !allowed.has(key)) continue\n out[key] = value\n }\n return out\n}\n", "export interface DurableSqlResult {\n one(): Record<string, unknown> | undefined\n toArray(): Array<Record<string, unknown>>\n}\n\nexport interface DurableSqlStorage {\n exec(sql: string, ...params: unknown[]): DurableSqlResult\n}\n\nconst WATERMARK_STATE_TABLE = '_zero_change_state'\n\nfunction quoteIdent(name: string): string {\n return `\"${name.replace(/\"/g, '\"\"')}\"`\n}\n\nfunction finitePositiveNumber(value: unknown): number {\n const number = Number(value ?? 0)\n return Number.isFinite(number) && number > 0 ? number : 0\n}\n\nexport class DurableWatermarkState {\n constructor(private readonly sql: DurableSqlStorage) {}\n\n ensureTables(): void {\n this.sql.exec(\n \"CREATE TABLE IF NOT EXISTS _zero_changes (watermark INTEGER PRIMARY KEY AUTOINCREMENT, table_name TEXT NOT NULL, op TEXT NOT NULL CHECK (op IN ('INSERT', 'UPDATE', 'DELETE')), row_data TEXT, old_data TEXT, created_at INTEGER NOT NULL DEFAULT (unixepoch()))\"\n )\n this.sql.exec(\n `CREATE TABLE IF NOT EXISTS ${quoteIdent(WATERMARK_STATE_TABLE)} (id INTEGER PRIMARY KEY CHECK (id = 1), last_value INTEGER NOT NULL DEFAULT 0)`\n )\n this.setWatermarkState(this.watermarkState())\n }\n\n next(): number {\n return this.current() + 1\n }\n\n mark(watermark: number): void {\n this.setWatermarkState(watermark)\n this.updateWatermarkSequences(watermark)\n }\n\n current(): number {\n this.ensureTables()\n const state = this.watermarkState()\n const row = this.sql\n .exec('SELECT COALESCE(MAX(watermark), 0) AS watermark FROM _zero_changes')\n .one() as { watermark?: unknown } | undefined\n const tableWatermark = finitePositiveNumber(row?.watermark)\n const sequenceWatermark = this.watermarkSequenceValue()\n const watermark = Math.max(state, tableWatermark, sequenceWatermark)\n if (watermark > state) this.setWatermarkState(watermark)\n if (watermark > sequenceWatermark) this.updateWatermarkSequences(watermark)\n return watermark\n }\n\n private watermarkState(): number {\n try {\n const table = quoteIdent(WATERMARK_STATE_TABLE)\n const row = this.sql.exec(`SELECT last_value FROM ${table} WHERE id = 1`).one() as\n | { last_value?: unknown }\n | undefined\n return finitePositiveNumber(row?.last_value)\n } catch {\n return 0\n }\n }\n\n private setWatermarkState(watermark: number): void {\n const table = quoteIdent(WATERMARK_STATE_TABLE)\n this.sql.exec(`INSERT OR IGNORE INTO ${table} (id, last_value) VALUES (1, 0)`)\n this.sql.exec(`UPDATE ${table} SET last_value = ? WHERE id = 1`, watermark)\n }\n\n private watermarkSequenceValue(): number {\n let watermark = 0\n for (const name of this.watermarkSequenceTables()) {\n try {\n const row = this.sql\n .exec(`SELECT last_value, is_called FROM ${quoteIdent(name)} WHERE dummy = 1`)\n .one() as { last_value?: unknown; is_called?: unknown } | undefined\n if (!row || !row.is_called) continue\n watermark = Math.max(watermark, finitePositiveNumber(row.last_value))\n } catch {\n /* not an orez sequence table */\n }\n }\n return watermark\n }\n\n private watermarkSequenceTables(): string[] {\n return this.sql\n .exec(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%zero_watermark%'\"\n )\n .toArray()\n .map((row) => String(row.name || ''))\n .filter(Boolean)\n }\n\n private updateWatermarkSequences(watermark: number): void {\n for (const name of this.watermarkSequenceTables()) {\n const table = quoteIdent(name)\n try {\n this.sql.exec(\n `INSERT OR IGNORE INTO ${table} (dummy, last_value, is_called) VALUES (1, ?, 1)`,\n watermark\n )\n this.sql.exec(\n `UPDATE ${table} SET last_value = ?, is_called = 1 WHERE dummy = 1`,\n watermark\n )\n } catch {\n /* not an orez sequence table */\n }\n }\n }\n}\n", "import type { Middleware } from \"./common\";\n\nconst drainBody: Middleware = async (request, env, _ctx, middlewareCtx) => {\n\ttry {\n\t\treturn await middlewareCtx.next(request, env);\n\t} finally {\n\t\ttry {\n\t\t\tif (request.body !== null && !request.bodyUsed) {\n\t\t\t\tconst reader = request.body.getReader();\n\t\t\t\twhile (!(await reader.read()).done) {}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.error(\"Failed to drain the unused request body.\", e);\n\t\t}\n\t}\n};\n\nexport default drainBody;\n", "import type { Middleware } from \"./common\";\n\ninterface JsonError {\n\tmessage?: string;\n\tname?: string;\n\tstack?: string;\n\tcause?: JsonError;\n}\n\nfunction reduceError(e: any): JsonError {\n\treturn {\n\t\tname: e?.name,\n\t\tmessage: e?.message ?? String(e),\n\t\tstack: e?.stack,\n\t\tcause: e?.cause === undefined ? undefined : reduceError(e.cause),\n\t};\n}\n\n// See comment in `bundle.ts` for details on why this is needed\nconst jsonError: Middleware = async (request, env, _ctx, middlewareCtx) => {\n\ttry {\n\t\treturn await middlewareCtx.next(request, env);\n\t} catch (e: any) {\n\t\tconst error = reduceError(e);\n\t\treturn Response.json(error, {\n\t\t\tstatus: 500,\n\t\t\theaders: { \"MF-Experimental-Error-Stack\": \"true\" },\n\t\t});\n\t}\n};\n\nexport default jsonError;\n", "\t\t\t\timport worker, * as OTHER_EXPORTS from \"/Users/n8/orez/src/cf-do/worker.ts\";\n\t\t\t\timport * as __MIDDLEWARE_0__ from \"/Users/n8/soot/node_modules/wrangler/templates/middleware/middleware-ensure-req-body-drained.ts\";\nimport * as __MIDDLEWARE_1__ from \"/Users/n8/soot/node_modules/wrangler/templates/middleware/middleware-miniflare3-json-error.ts\";\n\n\t\t\t\texport * from \"/Users/n8/orez/src/cf-do/worker.ts\";\n\t\t\t\tconst MIDDLEWARE_TEST_INJECT = \"__INJECT_FOR_TESTING_WRANGLER_MIDDLEWARE__\";\n\t\t\t\texport const __INTERNAL_WRANGLER_MIDDLEWARE__ = [\n\t\t\t\t\t\n\t\t\t\t\t__MIDDLEWARE_0__.default,__MIDDLEWARE_1__.default\n\t\t\t\t]\n\t\t\t\texport default worker;", "export type Awaitable<T> = T | Promise<T>;\n// TODO: allow dispatching more events?\nexport type Dispatcher = (\n\ttype: \"scheduled\",\n\tinit: { cron?: string }\n) => Awaitable<void>;\n\nexport type IncomingRequest = Request<\n\tunknown,\n\tIncomingRequestCfProperties<unknown>\n>;\n\nexport interface MiddlewareContext {\n\tdispatch: Dispatcher;\n\tnext(request: IncomingRequest, env: any): Awaitable<Response>;\n}\n\nexport type Middleware = (\n\trequest: IncomingRequest,\n\tenv: any,\n\tctx: ExecutionContext,\n\tmiddlewareCtx: MiddlewareContext\n) => Awaitable<Response>;\n\nconst __facade_middleware__: Middleware[] = [];\n\n// The register functions allow for the insertion of one or many middleware,\n// We register internal middleware first in the stack, but have no way of controlling\n// the order that addMiddleware is run in service workers so need an internal function.\nexport function __facade_register__(...args: (Middleware | Middleware[])[]) {\n\t__facade_middleware__.push(...args.flat());\n}\nexport function __facade_registerInternal__(\n\t...args: (Middleware | Middleware[])[]\n) {\n\t__facade_middleware__.unshift(...args.flat());\n}\n\nfunction __facade_invokeChain__(\n\trequest: IncomingRequest,\n\tenv: any,\n\tctx: ExecutionContext,\n\tdispatch: Dispatcher,\n\tmiddlewareChain: Middleware[]\n): Awaitable<Response> {\n\tconst [head, ...tail] = middlewareChain;\n\tconst middlewareCtx: MiddlewareContext = {\n\t\tdispatch,\n\t\tnext(newRequest, newEnv) {\n\t\t\treturn __facade_invokeChain__(newRequest, newEnv, ctx, dispatch, tail);\n\t\t},\n\t};\n\treturn head(request, env, ctx, middlewareCtx);\n}\n\nexport function __facade_invoke__(\n\trequest: IncomingRequest,\n\tenv: any,\n\tctx: ExecutionContext,\n\tdispatch: Dispatcher,\n\tfinalMiddleware: Middleware\n): Awaitable<Response> {\n\treturn __facade_invokeChain__(request, env, ctx, dispatch, [\n\t\t...__facade_middleware__,\n\t\tfinalMiddleware,\n\t]);\n}\n", "// This loads all middlewares exposed on the middleware object and then starts\n// the invocation chain. The big idea is that we can add these to the middleware\n// export dynamically through wrangler, or we can potentially let users directly\n// add them as a sort of \"plugin\" system.\n\nimport ENTRY, { __INTERNAL_WRANGLER_MIDDLEWARE__ } from \"/Users/n8/orez/src/cf-do/.wrangler/tmp/bundle-vYmw0E/middleware-insertion-facade.js\";\nimport { __facade_invoke__, __facade_register__, Dispatcher } from \"/Users/n8/soot/node_modules/wrangler/templates/middleware/common.ts\";\nimport type { WorkerEntrypointConstructor } from \"/Users/n8/orez/src/cf-do/.wrangler/tmp/bundle-vYmw0E/middleware-insertion-facade.js\";\n\n// Preserve all the exports from the worker\nexport * from \"/Users/n8/orez/src/cf-do/.wrangler/tmp/bundle-vYmw0E/middleware-insertion-facade.js\";\n\nclass __Facade_ScheduledController__ implements ScheduledController {\n\treadonly #noRetry: ScheduledController[\"noRetry\"];\n\n\tconstructor(\n\t\treadonly scheduledTime: number,\n\t\treadonly cron: string,\n\t\tnoRetry: ScheduledController[\"noRetry\"]\n\t) {\n\t\tthis.#noRetry = noRetry;\n\t}\n\n\tnoRetry() {\n\t\tif (!(this instanceof __Facade_ScheduledController__)) {\n\t\t\tthrow new TypeError(\"Illegal invocation\");\n\t\t}\n\t\t// Need to call native method immediately in case uncaught error thrown\n\t\tthis.#noRetry();\n\t}\n}\n\nfunction wrapExportedHandler(worker: ExportedHandler): ExportedHandler {\n\t// If we don't have any middleware defined, just return the handler as is\n\tif (\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0\n\t) {\n\t\treturn worker;\n\t}\n\t// Otherwise, register all middleware once\n\tfor (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {\n\t\t__facade_register__(middleware);\n\t}\n\n\tconst fetchDispatcher: ExportedHandlerFetchHandler = function (\n\t\trequest,\n\t\tenv,\n\t\tctx\n\t) {\n\t\tif (worker.fetch === undefined) {\n\t\t\tthrow new Error(\"Handler does not export a fetch() function.\");\n\t\t}\n\t\treturn worker.fetch(request, env, ctx);\n\t};\n\n\treturn {\n\t\t...worker,\n\t\tfetch(request, env, ctx) {\n\t\t\tconst dispatcher: Dispatcher = function (type, init) {\n\t\t\t\tif (type === \"scheduled\" && worker.scheduled !== undefined) {\n\t\t\t\t\tconst controller = new __Facade_ScheduledController__(\n\t\t\t\t\t\tDate.now(),\n\t\t\t\t\t\tinit.cron ?? \"\",\n\t\t\t\t\t\t() => {}\n\t\t\t\t\t);\n\t\t\t\t\treturn worker.scheduled(controller, env, ctx);\n\t\t\t\t}\n\t\t\t};\n\t\t\treturn __facade_invoke__(request, env, ctx, dispatcher, fetchDispatcher);\n\t\t},\n\t};\n}\n\nfunction wrapWorkerEntrypoint(\n\tklass: WorkerEntrypointConstructor\n): WorkerEntrypointConstructor {\n\t// If we don't have any middleware defined, just return the handler as is\n\tif (\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0\n\t) {\n\t\treturn klass;\n\t}\n\t// Otherwise, register all middleware once\n\tfor (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {\n\t\t__facade_register__(middleware);\n\t}\n\n\t// `extend`ing `klass` here so other RPC methods remain callable\n\treturn class extends klass {\n\t\t#fetchDispatcher: ExportedHandlerFetchHandler<Record<string, unknown>> = (\n\t\t\trequest,\n\t\t\tenv,\n\t\t\tctx\n\t\t) => {\n\t\t\tthis.env = env;\n\t\t\tthis.ctx = ctx;\n\t\t\tif (super.fetch === undefined) {\n\t\t\t\tthrow new Error(\"Entrypoint class does not define a fetch() function.\");\n\t\t\t}\n\t\t\treturn super.fetch(request);\n\t\t};\n\n\t\t#dispatcher: Dispatcher = (type, init) => {\n\t\t\tif (type === \"scheduled\" && super.scheduled !== undefined) {\n\t\t\t\tconst controller = new __Facade_ScheduledController__(\n\t\t\t\t\tDate.now(),\n\t\t\t\t\tinit.cron ?? \"\",\n\t\t\t\t\t() => {}\n\t\t\t\t);\n\t\t\t\treturn super.scheduled(controller);\n\t\t\t}\n\t\t};\n\n\t\tfetch(request: Request<unknown, IncomingRequestCfProperties>) {\n\t\t\treturn __facade_invoke__(\n\t\t\t\trequest,\n\t\t\t\tthis.env,\n\t\t\t\tthis.ctx,\n\t\t\t\tthis.#dispatcher,\n\t\t\t\tthis.#fetchDispatcher\n\t\t\t);\n\t\t}\n\t};\n}\n\nlet WRAPPED_ENTRY: ExportedHandler | WorkerEntrypointConstructor | undefined;\nif (typeof ENTRY === \"object\") {\n\tWRAPPED_ENTRY = wrapExportedHandler(ENTRY);\n} else if (typeof ENTRY === \"function\") {\n\tWRAPPED_ENTRY = wrapWorkerEntrypoint(ENTRY);\n}\nexport default WRAPPED_ENTRY;\n"],
6
- "mappings": "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",
7
- "names": ["quoteIdent"]
8
- }
@@ -1,93 +0,0 @@
1
- # orez/cf-do architecture - READ FIRST
2
-
3
- ## The fundamental constraint
4
-
5
- **Cloudflare Durable Objects have a 128 MB memory budget per instance.**
6
-
7
- PGlite + WASM Postgres + extension binaries pushes real deployments over that
8
- budget. That is the dead end. zero-cache is still essential: it owns the sync
9
- protocol, IVM/CVR machinery, replication handling, and client semantics.
10
-
11
- The orez Cloudflare path is therefore:
12
-
13
- - **yes** real `@rocicorp/zero` zero-cache
14
- - **yes** Durable Object SQLite as the durable storage engine
15
- - **yes** orez `DoBackend` serving Postgres-protocol semantics to zero-cache
16
- - **no** PGlite
17
- - **no** `pglite.wasm`, `pglite.data`, extension `.so` files, or WASM Postgres
18
-
19
- ## Production shape
20
-
21
- ```
22
- ┌────────────────────────────────────────────────────────────────┐
23
- │ Worker │
24
- │ │
25
- │ /sync/v* and /api/zero/* ─────► ZERO_CACHE_DO singleton │
26
- │ everything else ──────────────► ASSETS │
27
- └────────────────────────────────────────────────────────────────┘
28
-
29
- ┌────────────────────────────────────────────────────────────────┐
30
- │ ZERO_CACHE_DO Durable Object │
31
- │ │
32
- │ startZeroCacheEmbedCF() runs real zero-cache in-process │
33
- │ │ │
34
- │ ├─ zero-cache replica/CVR/CDB SQLite │
35
- │ │ @rocicorp/zero-sqlite3 -> orez worker SQLite shim │
36
- │ │ backed by ctx.storage.sql │
37
- │ │ │
38
- │ └─ zero-cache upstream Postgres connections │
39
- │ postgres -> orez postgres browser shim │
40
- │ DoBackend -> ZERO_SQL_DO /exec and /batch │
41
- └────────────────────────────────────────────────────────────────┘
42
-
43
- ┌────────────────────────────────────────────────────────────────┐
44
- │ ZERO_SQL_DO Durable Object │
45
- │ │
46
- │ ZeroDO raw SQL endpoints │
47
- │ /exec, /batch, /changes, /notify, /__orez/* │
48
- │ ctx.storage.sql │
49
- │ _orez.changes populated by SQL tracking triggers │
50
- └────────────────────────────────────────────────────────────────┘
51
- ```
52
-
53
- All app traffic for a deployed project must use singleton DO IDs for both
54
- `ZERO_CACHE_DO` and `ZERO_SQL_DO`; otherwise browser sessions will not share the
55
- same zero-cache process and durable SQLite state.
56
-
57
- ## Important files
58
-
59
- - `src/worker/zero-cache-embed-cf.ts` - starts real zero-cache inside a Durable
60
- Object and wires its storage/network dependencies to CF-safe shims.
61
- - `src/worker/cf-patches.ts` - patches zero-cache internals so its worker
62
- graph and writer run in the Workers runtime.
63
- - `src/pg-proxy-do-backend.ts` - translates Postgres protocol operations from
64
- zero-cache into DO SQL endpoint requests.
65
- - `src/cf-do/worker.ts` - `ZeroDO`, the generic DO SQL backend. It also still
66
- contains a bespoke Zero sync protocol handler used for development and
67
- protocol experiments, but the production Soot deploy path uses real
68
- zero-cache through `startZeroCacheEmbedCF()`.
69
- - `src/do-sql-tracking.ts` and `src/replication/*` - change tracking and
70
- logical replication support over `_orez.changes`.
71
-
72
- ## What not to do
73
-
74
- - Do not import `@electric-sql/pglite` into the Cloudflare DO deploy path.
75
- - Do not bundle PGlite WASM/data/extensions into the deploy template.
76
- - Do not replace zero-cache with the bespoke handler for production sync.
77
- - Do not add a second fallback path that silently switches between PGlite,
78
- bespoke sync, and zero-cache. There should be one production path:
79
- zero-cache -> orez Postgres protocol -> DO SQLite.
80
-
81
- If a future change needs more Postgres behavior, implement it in
82
- `DoBackend`/the SQL translator or the DO SQL backend. Do not put PGlite back in
83
- the request path.
84
-
85
- ## Running the chat e2e harness against this backend
86
-
87
- See `src/cf-do/CHAT_E2E.md`. The DO path is exercised end-to-end by chat's
88
- `--lite` mode harness, which has a hard 60-second `waitForPort(zero)` budget
89
- during boot. Three amplification bugs in `DoBackend` were fixed
90
- 2026-05-26 (snapshot fan-out, metadata persist per-row HTTP, metadata persist
91
- per-statement-in-tx); boot now completes in ~13s on a developer laptop. If
92
- boot regresses past the budget again, re-capture the /exec distribution as
93
- described in `CHAT_E2E.md` §3 before guessing at fixes.
@@ -1,213 +0,0 @@
1
- # orez DO mode + chat e2e — what to know before debugging
2
-
3
- If you landed here because chat e2e is failing against the orez Cloudflare DO
4
- backend, read this whole file first. The same handful of pitfalls have eaten
5
- multiple agent-sessions; the goal is for the next one to spend zero time
6
- re-discovering them.
7
-
8
- ## 1. The architecture in one paragraph
9
-
10
- chat in `--lite` mode launches `orez` as its database. orez exposes a Postgres
11
- wire protocol on `VITE_PORT_POSTGRES`. zero-cache (also embedded in lite mode)
12
- connects to orez over PG protocol and reads/writes both schema and data. orez,
13
- in DO mode, forwards every translated SQL statement as an HTTP POST to a
14
- wrangler-hosted `ZeroDO` worker. That worker executes against
15
- `ctx.storage.sql` (DO SQLite). When chat e2e fails, it almost always fails at
16
- **chat's 60-second `waitForPort(ports.zero, { timeoutMs: 60_000 })`** in
17
- `scripts/test/e2e.ts`. That deadline measures orez+zero boot, including
18
- hundreds of migration statements.
19
-
20
- ```
21
- chat lite mode (one process tree)
22
- ├── bun run:dev orez --disable-wasm-sqlite ...
23
- │ └── orez PG-protocol server (port 5632 by default; +PORT_OFFSET in tests)
24
- │ └── DoBackend (src/pg-proxy-do-backend.ts)
25
- │ └── HTTP POST /exec or /batch → wrangler dev (port 8799)
26
- │ └── ZeroDO durable object (src/cf-do/worker.ts)
27
- │ └── ctx.storage.sql (DO SQLite)
28
- ├── bun migrate run (chat's --on-db-ready callback)
29
- └── zero-cache process — waits for orez PG, then reads schema, opens port 5048
30
- ```
31
-
32
- ## 2. The single number that matters: 60 seconds
33
-
34
- `scripts/test/e2e.ts` in chat does:
35
-
36
- ```ts
37
- await waitForPort(ports.postgres, { timeoutMs: 60_000 })
38
- await waitForPort(ports.zero, { timeoutMs: 60_000 })
39
- await waitForPort(ports.web, { timeoutMs: 120_000 })
40
- ```
41
-
42
- Postgres opens almost immediately (orez TCP server). Web opens after Vite. The
43
- `zero` port is what kills you — zero-cache only opens it after orez has
44
- finished applying all of chat's migrations AND zero has finished reading the
45
- resulting schema. If boot takes >60s the whole harness fails with
46
- `task: backend failed after 1m 1s` and the test runner never even starts.
47
-
48
- **Do not "fix" this by bumping the timeout silently.** Boot time is a real
49
- budget that needs to fit on a developer's laptop and CI. If you need more, do
50
- it deliberately in `scripts/test-chat-e2e.ts` (the wrapper) by post-sync
51
- patching the file — and document why.
52
-
53
- ## 3. Where boot HTTP calls go (measured 2026-05-26)
54
-
55
- A 15s window of chat e2e boot, captured by adding
56
- `console.log(\`[exec] ${sql.slice(0, 80)}\`)`at the top of`handleExec`in`src/cf-do/worker.ts`, produced ~3,120 /exec calls per 15s, split roughly:
57
-
58
- | count | shape | source |
59
- | ----- | --------------------------------------------------------- | ------------------ |
60
- | 1858 | `INSERT INTO reaction(...) ON CONFLICT DO NOTHING` | chat seed data |
61
- | 665 | `UPDATE reaction SET keywords=?,category=? WHERE value=?` | chat metadata fill |
62
- | 550 | `INSERT OR REPLACE INTO "_orez_pg_metadata" ...` | orez (was per-row) |
63
- | ~40 | misc DDL / catalog probes | migrations |
64
-
65
- The first two are chat seed loops — you cannot reduce them without changing
66
- chat. The third is **pure orez overhead** and was the obvious target.
67
-
68
- To re-capture this distribution, add the same `console.log` temporarily, run
69
- the harness, then:
70
-
71
- ```bash
72
- awk -F'[exec] ' '{print $2}' /tmp/wrangler-do.log | \
73
- awk '{$1=""; print}' | sort | uniq -c | sort -rn | head -30
74
- ```
75
-
76
- ## 4. The three amplification bugs we fixed (commit landed 2026-05-26)
77
-
78
- All in `src/pg-proxy-do-backend.ts`. Before/after:
79
-
80
- ### 4a. `persistDurableMetadata` was a per-row HTTP loop
81
-
82
- It iterated `schemaMetadata` (all tables × all columns) and `publications` and
83
- issued one `await doExecResult` per row. A migration that added five columns
84
- to a table with already-known columns re-persisted _every_ metadata row, every
85
- time. Fix: build one multi-row `INSERT OR REPLACE INTO ... VALUES (?,?,?,?),
86
- (?,?,?,?),...` chunked at 200 rows (SQLite ~999 param cap / 4 cols).
87
-
88
- ### 4b. `applyStatementMetadata` was called after every SQL statement
89
-
90
- Inside a chat migration transaction, this fired N times instead of once. Fix:
91
- when `inTransaction`, set `txMetadataDirty = true` and skip; flush in
92
- `commitTransaction` (and the existing `rollbackTransaction` persist already
93
- covers the rollback path).
94
-
95
- ### 4c. `snapshotTransactionChangeTables` re-ran a `sqlite_master` scan per write
96
-
97
- For every tracked write inside a transaction, this called
98
- `tableExistsInDo('_zero_changes')`, `tableExistsInDo('_zero_change_state')`,
99
- and a `SELECT name FROM sqlite_master WHERE name LIKE '%zero_watermark%'`.
100
- The change tables only need snapshotting ONCE per transaction. Chat's seed
101
- loops do thousands of tracked writes inside one tx — this was ~4 extra HTTPs
102
- per write, easily 7,000+ wasted HTTPs during boot. Fix: add a
103
- `txChangeTablesSnapshotted` boolean, early-return when true, reset in
104
- `clearTransactionState`.
105
-
106
- ### 4d. `snapshotTransactionTable` probed sqlite_master on every first-write-per-tx
107
-
108
- For every first write to a table within a transaction,
109
- `snapshotTransactionTable` called `tableExistsInDo` (1 /exec to sqlite_master)
110
- before doing the snapshot CREATE. But we already have `schemaMetadata` —
111
- populated as a side-effect of every CREATE TABLE we translate — so if a
112
- table is in there, it exists. Fix: check `schemaMetadata.has(table)` first
113
- and only fall back to the sqlite_master probe for tables we haven't
114
- registered. Saves one HTTP per first-tx-write per known table.
115
-
116
- This last optimization is what closed the mutation-race gap for the unseen
117
- "speed bellwether" test (see §5b). Removing it will likely cause that test
118
- to start failing again.
119
-
120
- **Combined effect:** orez backend boot dropped from "fails at 60s" to "ready in
121
- ~13s" against the same wrangler + same chat harness on the same laptop, and
122
- **all 51 chat e2e tests pass on first attempt** (4.2 min total runtime).
123
-
124
- ## 5. Running chat e2e against your local changes
125
-
126
- From `~/orez`:
127
-
128
- ```bash
129
- # 1. Build orez and start wrangler hosting the DO worker
130
- bun run build
131
- cd src/cf-do && bunx wrangler dev --port 8799 --local --no-show-interactive-dev-session > /tmp/wrangler-do.log 2>&1 &
132
- cd -
133
-
134
- # 2. Run the wrapper that syncs chat → test-chat and launches the e2e harness
135
- PORT_OFFSET=30 bun scripts/test-chat-e2e.ts > /tmp/orez-e2e.log 2>&1 &
136
-
137
- # 3. Tail logs
138
- tail -f /tmp/orez-e2e.log
139
- ```
140
-
141
- The wrapper (`scripts/test-chat-e2e.ts`) is the canonical entry point. It:
142
-
143
- 1. Mirrors `~/chat` (or wherever `CHAT_DIR` points) into `~/orez/test-chat/`.
144
- 2. Copies orez `dist/` into `test-chat/node_modules/orez/dist/`.
145
- 3. Sets `OREZ_DATA_DIR=/tmp/orez-{PORT_OFFSET}` and PORT_OFFSET-shifted ports.
146
- 4. Sets `DO_BACKEND_URL=http://127.0.0.1:8799` so orez picks the DO backend.
147
- 5. Runs `bun run test e2e --integration --lite` in `test-chat/`.
148
-
149
- Multiple e2e runs share one wrangler instance. Reset DO state between runs by
150
- deleting `~/orez/src/cf-do/.wrangler/state/v3/do/` (so migrations re-apply
151
- fresh). Resetting only orez state without resetting DO state will leave
152
- orphaned tables and miss migration-replay bugs.
153
-
154
- ## 5b. The "speed bellwether" test
155
-
156
- `channel-unseen.test.ts` → `multiple channels track unseen independently` is
157
- the test that fails first when the backend is too slow. It sends two
158
- messages from a second browser context back-to-back then closes the context
159
- without waiting for them to round-trip — so the mutation push has to clear
160
- in the time between `sendMessageIn` returning and `ctxB.close()` returning.
161
-
162
- A slow backend loses that race; the mutations get cancelled when the
163
- context closes; user a never sees the unseen indicator update; the
164
- `expectChannelUnseen(page, 'Ops', true)` assertion fails.
165
-
166
- It is **not** flaky in a healthy config. If you see this test fail, the
167
- backend is too slow. Fix the backend, don't "fix" the test. The optimization
168
- in §4d (skip `tableExistsInDo` when schemaMetadata knows the table) is what
169
- got HEAD over the line — adding HTTP round trips back to the
170
- first-write-per-tx path will likely regress this test.
171
-
172
- ## 6. Common failure modes and what they mean
173
-
174
- | symptom | likely cause |
175
- | ---------------------------------------------------------------- | ------------------------------------------------------------------- |
176
- | `task: backend failed after 1m 1s` | zero port didn't open within 60s — orez boot too slow |
177
- | `task: backend failed` with no time | wrangler not running or `DO_BACKEND_URL` not set |
178
- | `ECONNREFUSED 127.0.0.1:8799` | wrangler dev died or never started |
179
- | `TG_OP is not defined` or trigger errors | chat trigger function uses Postgres `TG_OP`; orez skips these on DO |
180
- | "Ignoring mutation from X with ID N as it was already processed" | chat-side mutation dedup, not orez — non-fatal |
181
- | First test passes, second hangs | leftover state from previous run; reset `.wrangler/state/v3/do/` |
182
-
183
- ## 7. What never to touch
184
-
185
- - **Chat source.** The test harness must be identical to what chat ships. If
186
- you need to change behaviour for a test run, do it as a post-sync patch in
187
- `scripts/test-chat-e2e.ts` and document why.
188
- - **`maxFailures`, `timeout`, or `retries` in `test-chat/playwright.config.ts`.**
189
- Those are mirrored from chat; touching them is a cheat that masks real
190
- regressions and gets reverted next sync.
191
- - **PGlite.** This whole path exists because PGlite doesn't fit in the
192
- Cloudflare DO 128 MB budget. Do not add a PGlite fallback for DO mode.
193
-
194
- ## 8. Future optimization opportunities
195
-
196
- If chat boot grows past the 60s budget again, the cheapest remaining wins
197
- look like:
198
-
199
- - **Batch the chat seed inserts on the orez side.** chat sends ~1,858 individual
200
- `INSERT INTO reaction ... ON CONFLICT DO NOTHING` over the wire. If we
201
- detect a series of identical-shape inserts within one tx, we could
202
- accumulate and flush via `/batch` (one HTTP for N inserts). Risky because
203
- prepared statements + bind params don't line up; would need careful
204
- tracking.
205
- - **Skip `tableExistsInDo` after first-time table creation.** `DoBackend`
206
- could memoize known-existing tables for the life of the connection and
207
- drop the probe.
208
- - **Pipeline `/exec` HTTP calls.** Each call is round-tripped serially through
209
- wrangler. A small queue + single in-flight HTTP/2 socket would amortize
210
- the per-call overhead.
211
-
212
- Do _not_ attempt these speculatively. Re-measure boot HTTP distribution first
213
- (see §3), then target the largest bucket.
@@ -1,103 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
-
3
- import { DurableWatermarkState } from './watermark.js'
4
-
5
- class FakeResult {
6
- constructor(private readonly rows: Array<Record<string, unknown>> = []) {}
7
-
8
- one() {
9
- return this.rows[0]
10
- }
11
-
12
- toArray() {
13
- return this.rows
14
- }
15
- }
16
-
17
- class FakeSql {
18
- changes: Array<{ watermark: number }> = []
19
- state = 0
20
- sequence = { name: '_orez___zero_watermark', last_value: 1, is_called: 0 }
21
-
22
- exec(sql: string, ...params: unknown[]) {
23
- if (sql.startsWith('CREATE TABLE IF NOT EXISTS')) return new FakeResult()
24
-
25
- if (sql.startsWith('SELECT last_value FROM "_zero_change_state"')) {
26
- return new FakeResult([{ last_value: this.state }])
27
- }
28
-
29
- if (sql.startsWith('INSERT OR IGNORE INTO "_zero_change_state"')) {
30
- return new FakeResult()
31
- }
32
-
33
- if (sql.startsWith('UPDATE "_zero_change_state" SET last_value = ?')) {
34
- this.state = Number(params[0])
35
- return new FakeResult()
36
- }
37
-
38
- if (
39
- sql.startsWith('SELECT COALESCE(MAX(watermark), 0) AS watermark FROM _zero_changes')
40
- ) {
41
- const watermark = Math.max(0, ...this.changes.map((change) => change.watermark))
42
- return new FakeResult([{ watermark }])
43
- }
44
-
45
- if (sql.includes('sqlite_master') && sql.includes('%zero_watermark%')) {
46
- return new FakeResult([{ name: this.sequence.name }])
47
- }
48
-
49
- if (sql.startsWith('SELECT last_value, is_called FROM "_orez___zero_watermark"')) {
50
- return new FakeResult([
51
- {
52
- last_value: this.sequence.last_value,
53
- is_called: this.sequence.is_called,
54
- },
55
- ])
56
- }
57
-
58
- if (sql.startsWith('INSERT OR IGNORE INTO "_orez___zero_watermark"')) {
59
- return new FakeResult()
60
- }
61
-
62
- if (sql.startsWith('UPDATE "_orez___zero_watermark" SET last_value = ?')) {
63
- this.sequence.last_value = Number(params[0])
64
- this.sequence.is_called = 1
65
- return new FakeResult()
66
- }
67
-
68
- throw new Error(`unexpected fake sql: ${sql}`)
69
- }
70
- }
71
-
72
- describe('DurableWatermarkState', () => {
73
- it('does not reuse watermarks after consumed changes are purged', () => {
74
- const sql = new FakeSql()
75
- const watermarks = new DurableWatermarkState(sql)
76
-
77
- expect(watermarks.current()).toBe(0)
78
-
79
- const first = watermarks.next()
80
- sql.changes.push({ watermark: first })
81
- watermarks.mark(first)
82
- expect(first).toBe(1)
83
-
84
- sql.changes = []
85
-
86
- const second = watermarks.next()
87
- sql.changes.push({ watermark: second })
88
- watermarks.mark(second)
89
-
90
- expect(second).toBe(2)
91
- expect(sql.sequence).toMatchObject({ last_value: 2, is_called: 1 })
92
- })
93
-
94
- it('synchronizes from existing change rows and sequence state', () => {
95
- const sql = new FakeSql()
96
- sql.changes.push({ watermark: 7 })
97
- const watermarks = new DurableWatermarkState(sql)
98
-
99
- expect(watermarks.current()).toBe(7)
100
- expect(sql.state).toBe(7)
101
- expect(sql.sequence).toMatchObject({ last_value: 7, is_called: 1 })
102
- })
103
- })