orez-sync-cf-host 0.5.19 → 0.5.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -6
- package/dist/bun-wasm-loader.d.ts +1 -0
- package/dist/bun-wasm-loader.js +20 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +93 -0
- package/{src → dist}/generated/sync_wasm_bg.wasm +0 -0
- package/dist/host.d.ts +12 -0
- package/dist/host.js +1512 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +4 -0
- package/dist/mutation-error.d.ts +9 -0
- package/dist/mutation-error.js +23 -0
- package/dist/node-wasm-loader.d.ts +1 -0
- package/dist/node-wasm-loader.js +22 -0
- package/dist/post-commit.d.ts +13 -0
- package/dist/post-commit.js +31 -0
- package/dist/query-compiler.d.ts +4 -0
- package/dist/query-compiler.js +4 -0
- package/dist/sql-storage-adapter.d.ts +69 -0
- package/dist/sql-storage-adapter.js +194 -0
- package/dist/transaction-query.d.ts +72 -0
- package/dist/transaction-query.js +379 -0
- package/dist/types.d.ts +159 -0
- package/dist/types.js +5 -0
- package/dist/vite-wasm-loader.d.ts +3 -0
- package/dist/vite-wasm-loader.js +24 -0
- package/dist/wasm.d.ts +1 -0
- package/dist/wasm.js +7 -0
- package/dist/write-safeguards.d.ts +53 -0
- package/dist/write-safeguards.js +186 -0
- package/package.json +59 -19
- package/src/bun-wasm-loader.ts +0 -16
- package/src/config.ts +0 -102
- package/src/harness-config.ts +0 -487
- package/src/harness-worker.ts +0 -33
- package/src/host.ts +0 -1958
- package/src/index.ts +0 -47
- package/src/ingest-harness-worker.ts +0 -535
- package/src/mutation-error.ts +0 -28
- package/src/platform-probe-worker.ts +0 -418
- package/src/post-commit.ts +0 -40
- package/src/query-compiler.ts +0 -16
- package/src/sql-storage-adapter.ts +0 -254
- package/src/transaction-query.ts +0 -494
- package/src/types.ts +0 -195
- package/src/wasm-platform.ts +0 -10
- package/src/wasm.ts +0 -34
- package/src/write-safeguards.ts +0 -248
- /package/{src → dist}/generated/package.json +0 -0
- /package/{src → dist}/generated/sync_wasm.d.ts +0 -0
- /package/{src → dist}/generated/sync_wasm.js +0 -0
- /package/{src → dist}/generated/sync_wasm_bg.wasm.d.ts +0 -0
|
@@ -1,418 +0,0 @@
|
|
|
1
|
-
import { ZeroDO } from '../../../src/cf-do/worker.js'
|
|
2
|
-
import { createQueryCompiler } from './query-compiler.js'
|
|
3
|
-
import {
|
|
4
|
-
SqlStorageDirect,
|
|
5
|
-
SqlStorageMutatorTransaction,
|
|
6
|
-
SqlStorageSyncDb,
|
|
7
|
-
} from './sql-storage-adapter.js'
|
|
8
|
-
import {
|
|
9
|
-
init_probe_schema,
|
|
10
|
-
pull_snapshot,
|
|
11
|
-
push_finalize,
|
|
12
|
-
push_preflight,
|
|
13
|
-
rust_panic_after_writes,
|
|
14
|
-
value_round_trip,
|
|
15
|
-
} from './wasm-platform.js'
|
|
16
|
-
|
|
17
|
-
import type { TransactionQueryFormat } from './transaction-query.js'
|
|
18
|
-
import type { ZeroSchemaConfig } from './types.js'
|
|
19
|
-
|
|
20
|
-
interface Env {
|
|
21
|
-
PROBE_DO: DurableObjectNamespace<ProbeDurableObject>
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
type DeferredEffect = { mutationID: string; kind: string }
|
|
25
|
-
type MutatorName = 'read-then-write' | 'multi-table' | 'application-error'
|
|
26
|
-
|
|
27
|
-
const transactionQuerySchema = {
|
|
28
|
-
tables: {
|
|
29
|
-
account: {
|
|
30
|
-
name: 'account',
|
|
31
|
-
serverName: 'accounts',
|
|
32
|
-
columns: {
|
|
33
|
-
id: { type: 'string' },
|
|
34
|
-
balance: { type: 'number' },
|
|
35
|
-
},
|
|
36
|
-
primaryKey: ['id'],
|
|
37
|
-
},
|
|
38
|
-
entry: {
|
|
39
|
-
name: 'entry',
|
|
40
|
-
serverName: 'ledger',
|
|
41
|
-
columns: {
|
|
42
|
-
id: { type: 'number' },
|
|
43
|
-
accountId: { type: 'string', serverName: 'account_id' },
|
|
44
|
-
amount: { type: 'number' },
|
|
45
|
-
note: { type: 'string' },
|
|
46
|
-
},
|
|
47
|
-
primaryKey: ['id'],
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
} as const satisfies ZeroSchemaConfig
|
|
51
|
-
|
|
52
|
-
const transactionQueryAst = {
|
|
53
|
-
table: 'account',
|
|
54
|
-
where: {
|
|
55
|
-
type: 'simple',
|
|
56
|
-
op: '=',
|
|
57
|
-
left: { type: 'column', name: 'id' },
|
|
58
|
-
right: { type: 'literal', value: 'primary' },
|
|
59
|
-
},
|
|
60
|
-
related: [
|
|
61
|
-
{
|
|
62
|
-
correlation: { parentField: ['id'], childField: ['accountId'] },
|
|
63
|
-
subquery: { table: 'entry', alias: 'entries', orderBy: [['id', 'asc']] },
|
|
64
|
-
},
|
|
65
|
-
],
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const transactionQueryFormat = {
|
|
69
|
-
singular: true,
|
|
70
|
-
relationships: { entries: { singular: false, relationships: {} } },
|
|
71
|
-
} as const satisfies TransactionQueryFormat
|
|
72
|
-
|
|
73
|
-
const compileTransactionQuery = createQueryCompiler(transactionQuerySchema)
|
|
74
|
-
|
|
75
|
-
// Deterministic local analogue of normal DO idle eviction, matching the
|
|
76
|
-
// harness/cf probe: discard all in-memory state after an idle gap while SQL
|
|
77
|
-
// storage remains intact. This keeps the test sub-second instead of waiting
|
|
78
|
-
// for workerd/platform eviction heuristics.
|
|
79
|
-
const IDLE_TEARDOWN_MS = 250
|
|
80
|
-
|
|
81
|
-
const json = (value: unknown, status = 200) =>
|
|
82
|
-
Response.json(value, {
|
|
83
|
-
status,
|
|
84
|
-
headers: { 'cache-control': 'no-store' },
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
export class ProbeDurableObject extends ZeroDO {
|
|
88
|
-
readonly #db: SqlStorageSyncDb
|
|
89
|
-
#bootID = crypto.randomUUID()
|
|
90
|
-
#lastRequestAt = 0
|
|
91
|
-
#reinstantiations = 0
|
|
92
|
-
#effects: Array<DeferredEffect & { observedCommitted: boolean }> = []
|
|
93
|
-
|
|
94
|
-
constructor(ctx: DurableObjectState, env: Env) {
|
|
95
|
-
super(ctx, env as never)
|
|
96
|
-
this.#db = new SqlStorageSyncDb(ctx.storage.sql)
|
|
97
|
-
ctx.storage.transactionSync(() => init_probe_schema(this.#db))
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
#maybeReinstantiate(now: number): void {
|
|
101
|
-
if (this.#lastRequestAt > 0 && now - this.#lastRequestAt >= IDLE_TEARDOWN_MS) {
|
|
102
|
-
this.#bootID = crypto.randomUUID()
|
|
103
|
-
this.#effects = []
|
|
104
|
-
this.#reinstantiations++
|
|
105
|
-
}
|
|
106
|
-
this.#lastRequestAt = now
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
#state(): Record<string, unknown> {
|
|
110
|
-
const row = this.ctx.storage.sql
|
|
111
|
-
.exec(
|
|
112
|
-
`SELECT
|
|
113
|
-
CAST((SELECT lmid FROM probe_state WHERE singleton = 1) AS TEXT) AS lmid,
|
|
114
|
-
(SELECT balance FROM accounts WHERE id = 'primary') AS balance,
|
|
115
|
-
(SELECT COUNT(*) FROM ledger) AS ledgerCount,
|
|
116
|
-
(SELECT COUNT(*) FROM outbox) AS outboxCount,
|
|
117
|
-
(SELECT COUNT(*) FROM mutation_log) AS mutationCount,
|
|
118
|
-
(SELECT COUNT(*) FROM value_probe) AS valueCount`
|
|
119
|
-
)
|
|
120
|
-
.one()
|
|
121
|
-
return {
|
|
122
|
-
...row,
|
|
123
|
-
sideEffectCount: this.#effects.length,
|
|
124
|
-
sideEffects: this.#effects,
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async #mutate(name: MutatorName, deferred: DeferredEffect[]): Promise<void> {
|
|
129
|
-
if (name === 'read-then-write') {
|
|
130
|
-
const { balance } = this.ctx.storage.sql
|
|
131
|
-
.exec("SELECT balance FROM accounts WHERE id = 'primary'")
|
|
132
|
-
.one() as { balance: number }
|
|
133
|
-
await Promise.resolve()
|
|
134
|
-
this.ctx.storage.sql.exec(
|
|
135
|
-
"UPDATE accounts SET balance = ? WHERE id = 'primary'",
|
|
136
|
-
balance + 10
|
|
137
|
-
)
|
|
138
|
-
this.ctx.storage.sql.exec(
|
|
139
|
-
'INSERT INTO ledger (account_id, amount, note) VALUES (?, ?, ?)',
|
|
140
|
-
'primary',
|
|
141
|
-
10,
|
|
142
|
-
'read-then-write'
|
|
143
|
-
)
|
|
144
|
-
deferred.push({ mutationID: '', kind: 'balance-notification' })
|
|
145
|
-
return
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (name === 'multi-table') {
|
|
149
|
-
this.ctx.storage.sql.exec(
|
|
150
|
-
"UPDATE accounts SET balance = balance - 5 WHERE id = 'primary'"
|
|
151
|
-
)
|
|
152
|
-
await Promise.resolve()
|
|
153
|
-
this.ctx.storage.sql.exec(
|
|
154
|
-
'INSERT INTO ledger (account_id, amount, note) VALUES (?, ?, ?)',
|
|
155
|
-
'primary',
|
|
156
|
-
-5,
|
|
157
|
-
'multi-table'
|
|
158
|
-
)
|
|
159
|
-
this.ctx.storage.sql.exec(
|
|
160
|
-
'INSERT INTO outbox (topic, payload) VALUES (?, ?)',
|
|
161
|
-
'account.changed',
|
|
162
|
-
JSON.stringify({ id: 'primary', delta: -5 })
|
|
163
|
-
)
|
|
164
|
-
deferred.push({ mutationID: '', kind: 'outbox-notification' })
|
|
165
|
-
return
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const { balance } = this.ctx.storage.sql
|
|
169
|
-
.exec("SELECT balance FROM accounts WHERE id = 'primary'")
|
|
170
|
-
.one() as { balance: number }
|
|
171
|
-
this.ctx.storage.sql.exec(
|
|
172
|
-
"UPDATE accounts SET balance = ? WHERE id = 'primary'",
|
|
173
|
-
balance + 777
|
|
174
|
-
)
|
|
175
|
-
await Promise.resolve()
|
|
176
|
-
this.ctx.storage.sql.exec(
|
|
177
|
-
'INSERT INTO ledger (account_id, amount, note) VALUES (?, ?, ?)',
|
|
178
|
-
'primary',
|
|
179
|
-
777,
|
|
180
|
-
'application-error'
|
|
181
|
-
)
|
|
182
|
-
deferred.push({ mutationID: '', kind: 'must-not-run' })
|
|
183
|
-
throw new Error('intentional application mutator error')
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async #push(name: MutatorName, mutationID: string): Promise<Response> {
|
|
187
|
-
this.#db.resetStats()
|
|
188
|
-
const deferred: DeferredEffect[] = []
|
|
189
|
-
const started = performance.now()
|
|
190
|
-
let lmid: string | undefined
|
|
191
|
-
let wasmMs = 0
|
|
192
|
-
try {
|
|
193
|
-
await this.ctx.storage.transaction(async () => {
|
|
194
|
-
let wasmStarted = performance.now()
|
|
195
|
-
const expected = push_preflight(this.#db, mutationID)
|
|
196
|
-
wasmMs += performance.now() - wasmStarted
|
|
197
|
-
|
|
198
|
-
// MutatorSql methods resolve through the microtask queue. Cross that
|
|
199
|
-
// same boundary here without admitting timers or other external work
|
|
200
|
-
// into the storage transaction.
|
|
201
|
-
await Promise.resolve()
|
|
202
|
-
await this.#mutate(name, deferred)
|
|
203
|
-
|
|
204
|
-
wasmStarted = performance.now()
|
|
205
|
-
lmid = push_finalize(this.#db, mutationID, expected)
|
|
206
|
-
wasmMs += performance.now() - wasmStarted
|
|
207
|
-
})
|
|
208
|
-
} catch (error) {
|
|
209
|
-
return json(
|
|
210
|
-
{
|
|
211
|
-
ok: false,
|
|
212
|
-
error: String(error),
|
|
213
|
-
awaitedInsideTransaction: true,
|
|
214
|
-
state: this.#state(),
|
|
215
|
-
effectsDeferredButNotRun: deferred.length,
|
|
216
|
-
},
|
|
217
|
-
409
|
|
218
|
-
)
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// External effects are not even inspected until the transaction promise
|
|
222
|
-
// resolves. Each effect independently verifies its mutation is durable.
|
|
223
|
-
for (const effect of deferred) {
|
|
224
|
-
effect.mutationID = mutationID
|
|
225
|
-
const committed =
|
|
226
|
-
this.ctx.storage.sql
|
|
227
|
-
.exec(
|
|
228
|
-
'SELECT 1 AS committed FROM mutation_log WHERE mutation_id = ?',
|
|
229
|
-
mutationID
|
|
230
|
-
)
|
|
231
|
-
.toArray().length === 1
|
|
232
|
-
this.#effects.push({ ...effect, observedCommitted: committed })
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return json({
|
|
236
|
-
ok: true,
|
|
237
|
-
lmid,
|
|
238
|
-
awaitedInsideTransaction: true,
|
|
239
|
-
state: this.#state(),
|
|
240
|
-
timing: {
|
|
241
|
-
elapsedMs: performance.now() - started,
|
|
242
|
-
wasmMs,
|
|
243
|
-
...this.#db.stats,
|
|
244
|
-
},
|
|
245
|
-
})
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
async fetch(request: Request): Promise<Response> {
|
|
249
|
-
this.#maybeReinstantiate(Date.now())
|
|
250
|
-
const url = new URL(request.url)
|
|
251
|
-
const [, , ...routeParts] = url.pathname.split('/')
|
|
252
|
-
const route = `/${routeParts.join('/')}`
|
|
253
|
-
|
|
254
|
-
if (route === '/status') {
|
|
255
|
-
return json({
|
|
256
|
-
bootID: this.#bootID,
|
|
257
|
-
idleTeardownMs: IDLE_TEARDOWN_MS,
|
|
258
|
-
reinstantiations: this.#reinstantiations,
|
|
259
|
-
state: this.#state(),
|
|
260
|
-
})
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (route === '/pull') {
|
|
264
|
-
this.#db.resetStats()
|
|
265
|
-
const started = performance.now()
|
|
266
|
-
const snapshot = this.ctx.storage.transactionSync(() => pull_snapshot(this.#db))
|
|
267
|
-
return json({
|
|
268
|
-
snapshot,
|
|
269
|
-
transaction: 'transactionSync',
|
|
270
|
-
timing: { elapsedMs: performance.now() - started, ...this.#db.stats },
|
|
271
|
-
})
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (route.startsWith('/push/')) {
|
|
275
|
-
const name = route.slice('/push/'.length) as MutatorName
|
|
276
|
-
if (!['read-then-write', 'multi-table', 'application-error'].includes(name)) {
|
|
277
|
-
return json({ error: 'unknown mutator' }, 404)
|
|
278
|
-
}
|
|
279
|
-
const body = (await request.json()) as { mutationID: string }
|
|
280
|
-
return this.#push(name, body.mutationID)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
if (route === '/js-exception') {
|
|
284
|
-
const before = this.#state()
|
|
285
|
-
try {
|
|
286
|
-
await this.ctx.storage.transaction(async () => {
|
|
287
|
-
const expected = push_preflight(this.#db, 'js-exception')
|
|
288
|
-
this.ctx.storage.sql.exec(
|
|
289
|
-
"UPDATE accounts SET balance = balance + 123 WHERE id = 'primary'"
|
|
290
|
-
)
|
|
291
|
-
await Promise.resolve()
|
|
292
|
-
this.ctx.storage.sql.exec(
|
|
293
|
-
'INSERT INTO outbox (topic, payload) VALUES (?, ?)',
|
|
294
|
-
'must.rollback',
|
|
295
|
-
'{}'
|
|
296
|
-
)
|
|
297
|
-
push_finalize(this.#db, 'js-exception', expected)
|
|
298
|
-
throw new Error('intentional JS exception after finalization')
|
|
299
|
-
})
|
|
300
|
-
} catch (error) {
|
|
301
|
-
return json(
|
|
302
|
-
{ ok: false, error: String(error), before, after: this.#state() },
|
|
303
|
-
409
|
|
304
|
-
)
|
|
305
|
-
}
|
|
306
|
-
return json({ error: 'JS exception did not escape transaction' }, 500)
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
if (route === '/rust-panic') {
|
|
310
|
-
const before = this.#state()
|
|
311
|
-
try {
|
|
312
|
-
this.ctx.storage.transactionSync(() => rust_panic_after_writes(this.#db))
|
|
313
|
-
} catch (error) {
|
|
314
|
-
return json(
|
|
315
|
-
{ ok: false, error: String(error), before, after: this.#state() },
|
|
316
|
-
409
|
|
317
|
-
)
|
|
318
|
-
}
|
|
319
|
-
return json({ error: 'Rust panic did not escape transaction' }, 500)
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
if (route === '/values') {
|
|
323
|
-
const input = await request.json()
|
|
324
|
-
const output = this.ctx.storage.transactionSync(() =>
|
|
325
|
-
value_round_trip(this.#db, input)
|
|
326
|
-
)
|
|
327
|
-
return json(output)
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (route === '/adapter-guard') {
|
|
331
|
-
const errors: string[] = []
|
|
332
|
-
for (const [sql, params] of [
|
|
333
|
-
['BEGIN TRANSACTION', []],
|
|
334
|
-
['SELECT ?1', [{ kind: 'integer', value: '1' }]],
|
|
335
|
-
] as const) {
|
|
336
|
-
try {
|
|
337
|
-
this.#db.exec(sql, [...params] as never)
|
|
338
|
-
} catch (error) {
|
|
339
|
-
errors.push(String(error))
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
return json({ errors })
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
if (route === '/transaction-query') {
|
|
346
|
-
let plan: ReturnType<typeof compileTransactionQuery> | undefined
|
|
347
|
-
const tx = new SqlStorageMutatorTransaction(
|
|
348
|
-
new SqlStorageDirect(this.ctx.storage.sql),
|
|
349
|
-
(queryAst, queryFormat) => {
|
|
350
|
-
plan = compileTransactionQuery(queryAst, queryFormat)
|
|
351
|
-
return plan
|
|
352
|
-
}
|
|
353
|
-
)
|
|
354
|
-
const result = await tx.queryAst(
|
|
355
|
-
transactionQueryAst,
|
|
356
|
-
transactionQueryFormat,
|
|
357
|
-
'platformTransactionQuery'
|
|
358
|
-
)
|
|
359
|
-
let malformedFormatStatus: unknown
|
|
360
|
-
try {
|
|
361
|
-
await tx.queryAst(transactionQueryAst, undefined as never)
|
|
362
|
-
} catch (error) {
|
|
363
|
-
malformedFormatStatus = (error as { status?: unknown }).status
|
|
364
|
-
}
|
|
365
|
-
return json({ result, malformedFormatStatus, plan })
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
if (route === '/application-transaction-query') {
|
|
369
|
-
const result = await this.runApplicationTransaction(
|
|
370
|
-
compileTransactionQuery,
|
|
371
|
-
(tx) =>
|
|
372
|
-
tx.queryAst(
|
|
373
|
-
transactionQueryAst,
|
|
374
|
-
transactionQueryFormat,
|
|
375
|
-
'applicationTransactionQuery'
|
|
376
|
-
),
|
|
377
|
-
{ maxSelects: 8, maxRows: 20 }
|
|
378
|
-
)
|
|
379
|
-
return json({ result })
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
if (route === '/application-transaction-query-budget') {
|
|
383
|
-
try {
|
|
384
|
-
await this.runApplicationTransaction(
|
|
385
|
-
compileTransactionQuery,
|
|
386
|
-
(tx) =>
|
|
387
|
-
tx.queryAst(
|
|
388
|
-
transactionQueryAst,
|
|
389
|
-
transactionQueryFormat,
|
|
390
|
-
'budgetedApplicationTransactionQuery'
|
|
391
|
-
),
|
|
392
|
-
{ maxSelects: 1 }
|
|
393
|
-
)
|
|
394
|
-
} catch (error) {
|
|
395
|
-
return json(
|
|
396
|
-
{
|
|
397
|
-
code: Reflect.get(error as object, 'code'),
|
|
398
|
-
query: Reflect.get(error as object, 'query'),
|
|
399
|
-
selects: Reflect.get(error as object, 'selects'),
|
|
400
|
-
},
|
|
401
|
-
409
|
|
402
|
-
)
|
|
403
|
-
}
|
|
404
|
-
return json({ error: 'query budget did not abort the transaction' }, 500)
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
return json({ error: 'not found', route }, 404)
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
export default {
|
|
412
|
-
fetch(request: Request, env: Env): Promise<Response> {
|
|
413
|
-
const url = new URL(request.url)
|
|
414
|
-
const [, namespace] = url.pathname.split('/')
|
|
415
|
-
if (!namespace) return Promise.resolve(new Response('orez rust sync M0 probe'))
|
|
416
|
-
return env.PROBE_DO.get(env.PROBE_DO.idFromName(namespace)).fetch(request)
|
|
417
|
-
},
|
|
418
|
-
} satisfies ExportedHandler<Env>
|
package/src/post-commit.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export type DeferredEffect = () => void | Promise<void>
|
|
2
|
-
|
|
3
|
-
export type PostCommitEffects = {
|
|
4
|
-
/** discard effects from a storage-transaction attempt before starting another */
|
|
5
|
-
beginAttempt(): void
|
|
6
|
-
defer(effect: DeferredEffect): void
|
|
7
|
-
/** run the committed attempt's effects in order without rejecting */
|
|
8
|
-
runAfterCommit(onError: (error: unknown) => void): Promise<void>
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* collect external work during a retryable transaction and run only the effects
|
|
13
|
-
* belonging to the attempt that commits.
|
|
14
|
-
*/
|
|
15
|
-
export function createPostCommitEffects(): PostCommitEffects {
|
|
16
|
-
const effects: DeferredEffect[] = []
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
beginAttempt() {
|
|
20
|
-
effects.length = 0
|
|
21
|
-
},
|
|
22
|
-
defer(effect) {
|
|
23
|
-
effects.push(effect)
|
|
24
|
-
},
|
|
25
|
-
async runAfterCommit(onError) {
|
|
26
|
-
const committed = effects.splice(0)
|
|
27
|
-
for (const effect of committed) {
|
|
28
|
-
try {
|
|
29
|
-
await effect()
|
|
30
|
-
} catch (error) {
|
|
31
|
-
try {
|
|
32
|
-
onError(error)
|
|
33
|
-
} catch {
|
|
34
|
-
// reporting must not turn a committed effect failure into a rejection
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
}
|
|
40
|
-
}
|
package/src/query-compiler.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { engine_compile_query } from './wasm.js'
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
CompiledTransactionQueryPlan,
|
|
5
|
-
TransactionQueryFormat,
|
|
6
|
-
} from './transaction-query.js'
|
|
7
|
-
import type { ZeroSchemaConfig } from './types.js'
|
|
8
|
-
|
|
9
|
-
export type TransactionQueryCompiler = (
|
|
10
|
-
ast: unknown,
|
|
11
|
-
format: TransactionQueryFormat
|
|
12
|
-
) => CompiledTransactionQueryPlan
|
|
13
|
-
|
|
14
|
-
export function createQueryCompiler(schema: ZeroSchemaConfig): TransactionQueryCompiler {
|
|
15
|
-
return (ast, format) => engine_compile_query(schema, ast, format)
|
|
16
|
-
}
|