orez-sync-cf-host 0.4.64 → 0.4.66
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/package.json +1 -1
- package/src/generated/sync_wasm_bg.wasm +0 -0
- package/src/host.ts +33 -7
- package/src/ingest-harness-worker.ts +27 -2
package/package.json
CHANGED
|
Binary file
|
package/src/host.ts
CHANGED
|
@@ -73,6 +73,13 @@ type MutationResult = {
|
|
|
73
73
|
result: Record<string, unknown>
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
type DelegatedMutationResult = { id?: { clientID?: unknown; id?: unknown } }
|
|
77
|
+
type DelegatedPushBody = {
|
|
78
|
+
mutations?: DelegatedMutationResult[]
|
|
79
|
+
pushResponse?: unknown
|
|
80
|
+
[key: string]: unknown
|
|
81
|
+
}
|
|
82
|
+
|
|
76
83
|
type EngineState = { watermark: string; floor: string; upstreamWatermark: string }
|
|
77
84
|
type UpstreamBatch = {
|
|
78
85
|
watermark: number
|
|
@@ -135,6 +142,18 @@ function json(value: unknown, status = 200): Response {
|
|
|
135
142
|
})
|
|
136
143
|
}
|
|
137
144
|
|
|
145
|
+
function isStructuredPushFailed(value: unknown): value is Record<string, unknown> {
|
|
146
|
+
if (typeof value !== 'object' || value === null) return false
|
|
147
|
+
const body = value as Record<string, unknown>
|
|
148
|
+
return (
|
|
149
|
+
body.kind === 'PushFailed' &&
|
|
150
|
+
typeof body.origin === 'string' &&
|
|
151
|
+
typeof body.reason === 'string' &&
|
|
152
|
+
typeof body.message === 'string' &&
|
|
153
|
+
Array.isArray(body.mutationIDs)
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
138
157
|
function statusOf(error: unknown): number {
|
|
139
158
|
if (typeof error === 'object' && error !== null && 'status' in error) {
|
|
140
159
|
const status = Number(error.status)
|
|
@@ -1057,14 +1076,21 @@ export function createSyncDurableObject<Env extends SyncHostEnv>(
|
|
|
1057
1076
|
if (!upstreamResponse.ok) {
|
|
1058
1077
|
return new Response(upstreamResponse.body, upstreamResponse)
|
|
1059
1078
|
}
|
|
1060
|
-
const upstreamBody = (await upstreamResponse.json()) as
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1079
|
+
const upstreamBody = (await upstreamResponse.json()) as DelegatedPushBody
|
|
1080
|
+
const delegatedResponse = upstreamBody.pushResponse ?? upstreamBody
|
|
1081
|
+
if (isStructuredPushFailed(delegatedResponse)) {
|
|
1082
|
+
// PushFailed is a successful protocol response describing an
|
|
1083
|
+
// application-level failure. There are intentionally no mutation
|
|
1084
|
+
// acknowledgements to finalize in the host; preserve the body so
|
|
1085
|
+
// the Zero client can apply its retry/error policy.
|
|
1086
|
+
return json({ pushResponse: delegatedResponse })
|
|
1065
1087
|
}
|
|
1066
1088
|
const acknowledged =
|
|
1067
|
-
upstreamBody.pushResponse
|
|
1089
|
+
typeof upstreamBody.pushResponse === 'object' &&
|
|
1090
|
+
upstreamBody.pushResponse !== null &&
|
|
1091
|
+
'mutations' in upstreamBody.pushResponse
|
|
1092
|
+
? upstreamBody.pushResponse.mutations
|
|
1093
|
+
: upstreamBody.mutations
|
|
1068
1094
|
if (!Array.isArray(acknowledged)) {
|
|
1069
1095
|
throw new Error('delegated push returned no mutation results')
|
|
1070
1096
|
}
|
|
@@ -1104,7 +1130,7 @@ export function createSyncDurableObject<Env extends SyncHostEnv>(
|
|
|
1104
1130
|
)
|
|
1105
1131
|
}
|
|
1106
1132
|
await this.#ingest(upstreamPath)
|
|
1107
|
-
return json({ pushResponse:
|
|
1133
|
+
return json({ pushResponse: delegatedResponse })
|
|
1108
1134
|
} catch (error) {
|
|
1109
1135
|
const status = statusOf(error)
|
|
1110
1136
|
return json(errorBody(error), status)
|
|
@@ -32,6 +32,7 @@ const numericTextNamespaces = new Set<string>()
|
|
|
32
32
|
const hydratedNamespaces = new Set<string>()
|
|
33
33
|
let delegatedFailuresRemaining = 0
|
|
34
34
|
let delegatedAttempts = 0
|
|
35
|
+
let delegatedPushFailedRemaining = 0
|
|
35
36
|
|
|
36
37
|
const config: SyncHostConfig<Env> = {
|
|
37
38
|
hostVersion: 'upstream-ingest-harness',
|
|
@@ -191,6 +192,18 @@ export class AppService extends WorkerEntrypoint<Env> {
|
|
|
191
192
|
)
|
|
192
193
|
}
|
|
193
194
|
delegatedAttempts++
|
|
195
|
+
if (delegatedPushFailedRemaining > 0) {
|
|
196
|
+
delegatedPushFailedRemaining--
|
|
197
|
+
return Promise.resolve(
|
|
198
|
+
Response.json({
|
|
199
|
+
kind: 'PushFailed',
|
|
200
|
+
origin: 'server',
|
|
201
|
+
reason: 'database',
|
|
202
|
+
mutationIDs: [{ clientID: 'writer', id: 2 }],
|
|
203
|
+
message: 'synthetic mutation result persistence failure',
|
|
204
|
+
})
|
|
205
|
+
)
|
|
206
|
+
}
|
|
194
207
|
if (delegatedFailuresRemaining > 0) {
|
|
195
208
|
delegatedFailuresRemaining--
|
|
196
209
|
return Promise.resolve(
|
|
@@ -236,7 +249,11 @@ export default {
|
|
|
236
249
|
if (url.pathname === '/delegation-control') {
|
|
237
250
|
if (request.method === 'GET') {
|
|
238
251
|
return Promise.resolve(
|
|
239
|
-
Response.json({
|
|
252
|
+
Response.json({
|
|
253
|
+
delegatedFailuresRemaining,
|
|
254
|
+
delegatedPushFailedRemaining,
|
|
255
|
+
delegatedAttempts,
|
|
256
|
+
})
|
|
240
257
|
)
|
|
241
258
|
}
|
|
242
259
|
return request
|
|
@@ -247,8 +264,16 @@ export default {
|
|
|
247
264
|
0,
|
|
248
265
|
Number((body as { failures?: unknown }).failures) || 0
|
|
249
266
|
)
|
|
267
|
+
delegatedPushFailedRemaining = Math.max(
|
|
268
|
+
0,
|
|
269
|
+
Number((body as { pushFailed?: unknown }).pushFailed) || 0
|
|
270
|
+
)
|
|
250
271
|
delegatedAttempts = 0
|
|
251
|
-
return Response.json({
|
|
272
|
+
return Response.json({
|
|
273
|
+
delegatedFailuresRemaining,
|
|
274
|
+
delegatedPushFailedRemaining,
|
|
275
|
+
delegatedAttempts,
|
|
276
|
+
})
|
|
252
277
|
})
|
|
253
278
|
}
|
|
254
279
|
if (url.pathname.startsWith('/upstream/')) {
|