orez-sync-cf-host 0.4.62 → 0.4.64
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 +18 -3
- package/src/ingest-harness-worker.ts +63 -2
package/package.json
CHANGED
|
Binary file
|
package/src/host.ts
CHANGED
|
@@ -690,7 +690,8 @@ export function createSyncDurableObject<Env extends SyncHostEnv>(
|
|
|
690
690
|
async #fetchDelegatedPush(
|
|
691
691
|
endpoint: URL,
|
|
692
692
|
headers: Headers,
|
|
693
|
-
body: ArrayBuffer
|
|
693
|
+
body: ArrayBuffer,
|
|
694
|
+
provisioning = false
|
|
694
695
|
): Promise<Response> {
|
|
695
696
|
const binding = this.#serviceBinding(
|
|
696
697
|
config.mutateBinding ?? config.upstream?.binding
|
|
@@ -703,7 +704,9 @@ export function createSyncDurableObject<Env extends SyncHostEnv>(
|
|
|
703
704
|
method: 'POST',
|
|
704
705
|
headers,
|
|
705
706
|
body,
|
|
706
|
-
signal: AbortSignal.timeout(
|
|
707
|
+
signal: AbortSignal.timeout(
|
|
708
|
+
provisioning ? Math.max(delegateTimeoutMs, 25_000) : delegateTimeoutMs
|
|
709
|
+
),
|
|
707
710
|
})
|
|
708
711
|
} catch (error) {
|
|
709
712
|
lastError = error
|
|
@@ -1048,7 +1051,8 @@ export function createSyncDurableObject<Env extends SyncHostEnv>(
|
|
|
1048
1051
|
const upstreamResponse = await this.#fetchDelegatedPush(
|
|
1049
1052
|
endpoint,
|
|
1050
1053
|
headers,
|
|
1051
|
-
bytes
|
|
1054
|
+
bytes,
|
|
1055
|
+
this.#engineState()?.upstreamWatermark === '0'
|
|
1052
1056
|
)
|
|
1053
1057
|
if (!upstreamResponse.ok) {
|
|
1054
1058
|
return new Response(upstreamResponse.body, upstreamResponse)
|
|
@@ -1477,6 +1481,17 @@ export function createSyncDurableObject<Env extends SyncHostEnv>(
|
|
|
1477
1481
|
return this.#pull(request, claims, namespace)
|
|
1478
1482
|
}
|
|
1479
1483
|
if (route === '/push' && request.method === 'POST') {
|
|
1484
|
+
// A push may be the first request for a fresh namespace. DATA's
|
|
1485
|
+
// /changes call is also its schema-provisioning barrier, so complete it
|
|
1486
|
+
// before delegating the mutation to APP. Pull already enforces this
|
|
1487
|
+
// ordering above; skipping it here let APP race half-created tables and
|
|
1488
|
+
// surface a terminal, bodyless 500 to Zero.
|
|
1489
|
+
try {
|
|
1490
|
+
await this.#ingest(upstreamPath)
|
|
1491
|
+
} catch (error) {
|
|
1492
|
+
await request.arrayBuffer()
|
|
1493
|
+
return json(errorBody(error), statusOf(error))
|
|
1494
|
+
}
|
|
1480
1495
|
return this.#push(request, claims, namespace, upstreamPath)
|
|
1481
1496
|
}
|
|
1482
1497
|
return json({ error: 'not found' }, 404)
|
|
@@ -28,6 +28,8 @@ interface Env extends SyncHostEnv {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const runawayNamespaces = new Set<string>()
|
|
31
|
+
const numericTextNamespaces = new Set<string>()
|
|
32
|
+
const hydratedNamespaces = new Set<string>()
|
|
31
33
|
let delegatedFailuresRemaining = 0
|
|
32
34
|
let delegatedAttempts = 0
|
|
33
35
|
|
|
@@ -95,7 +97,7 @@ async function upstreamFetch(request: Request, env: Env): Promise<Response> {
|
|
|
95
97
|
|
|
96
98
|
/** Self service-binding target backed by the real ZeroSqlDO. */
|
|
97
99
|
export class DataService extends WorkerEntrypoint<Env> {
|
|
98
|
-
fetch(request: Request): Promise<Response> {
|
|
100
|
+
async fetch(request: Request): Promise<Response> {
|
|
99
101
|
const url = new URL(request.url)
|
|
100
102
|
const pathname = url.pathname
|
|
101
103
|
if (
|
|
@@ -108,6 +110,45 @@ export class DataService extends WorkerEntrypoint<Env> {
|
|
|
108
110
|
)
|
|
109
111
|
}
|
|
110
112
|
const namespace = pathname.split('/')[1] ?? ''
|
|
113
|
+
if (pathname.endsWith('/changes') && numericTextNamespaces.has(namespace)) {
|
|
114
|
+
const watermark = Number(new URL(request.url).searchParams.get('watermark') ?? 0)
|
|
115
|
+
return Promise.resolve(
|
|
116
|
+
Response.json({
|
|
117
|
+
watermark: 2,
|
|
118
|
+
changes:
|
|
119
|
+
watermark >= 2
|
|
120
|
+
? []
|
|
121
|
+
: [
|
|
122
|
+
{
|
|
123
|
+
watermark: 1,
|
|
124
|
+
tableName: 'item',
|
|
125
|
+
op: 'INSERT',
|
|
126
|
+
rowData: {
|
|
127
|
+
id: 'numeric-text',
|
|
128
|
+
label: 'SQL timestamp text',
|
|
129
|
+
rank: '2026-07-11 13:34:46',
|
|
130
|
+
done: false,
|
|
131
|
+
meta: null,
|
|
132
|
+
},
|
|
133
|
+
oldData: null,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
watermark: 2,
|
|
137
|
+
tableName: 'item',
|
|
138
|
+
op: 'INSERT',
|
|
139
|
+
rowData: {
|
|
140
|
+
id: 'numeric-native',
|
|
141
|
+
label: 'native JSON number',
|
|
142
|
+
rank: 1783776886000,
|
|
143
|
+
done: false,
|
|
144
|
+
meta: null,
|
|
145
|
+
},
|
|
146
|
+
oldData: null,
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
})
|
|
150
|
+
)
|
|
151
|
+
}
|
|
111
152
|
if (pathname.endsWith('/changes') && runawayNamespaces.has(namespace)) {
|
|
112
153
|
return Promise.resolve(
|
|
113
154
|
Response.json({
|
|
@@ -130,7 +171,9 @@ export class DataService extends WorkerEntrypoint<Env> {
|
|
|
130
171
|
})
|
|
131
172
|
)
|
|
132
173
|
}
|
|
133
|
-
|
|
174
|
+
const response = await upstreamFetch(request, this.env)
|
|
175
|
+
if (pathname.endsWith('/changes') && response.ok) hydratedNamespaces.add(namespace)
|
|
176
|
+
return response
|
|
134
177
|
}
|
|
135
178
|
}
|
|
136
179
|
|
|
@@ -141,6 +184,12 @@ export class AppService extends WorkerEntrypoint<Env> {
|
|
|
141
184
|
new Response('APP route rejected non-push request', { status: 418 })
|
|
142
185
|
)
|
|
143
186
|
}
|
|
187
|
+
const namespace = new URL(request.url).pathname.split('/')[1] ?? ''
|
|
188
|
+
if (!hydratedNamespaces.has(namespace)) {
|
|
189
|
+
return Promise.resolve(
|
|
190
|
+
Response.json({ error: 'schema provisioning has not completed' }, { status: 500 })
|
|
191
|
+
)
|
|
192
|
+
}
|
|
144
193
|
delegatedAttempts++
|
|
145
194
|
if (delegatedFailuresRemaining > 0) {
|
|
146
195
|
delegatedFailuresRemaining--
|
|
@@ -156,6 +205,18 @@ const syncWorker = createSyncWorker(config)
|
|
|
156
205
|
export default {
|
|
157
206
|
fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
|
158
207
|
const url = new URL(request.url)
|
|
208
|
+
if (url.pathname.startsWith('/numeric-text-control/')) {
|
|
209
|
+
const namespace = url.pathname.slice('/numeric-text-control/'.length)
|
|
210
|
+
return request
|
|
211
|
+
.json()
|
|
212
|
+
.catch(() => ({}))
|
|
213
|
+
.then((body) => {
|
|
214
|
+
if ((body as { enabled?: unknown }).enabled === true)
|
|
215
|
+
numericTextNamespaces.add(namespace)
|
|
216
|
+
else numericTextNamespaces.delete(namespace)
|
|
217
|
+
return Response.json({ ok: true, namespace })
|
|
218
|
+
})
|
|
219
|
+
}
|
|
159
220
|
if (url.pathname.startsWith('/runaway-control/')) {
|
|
160
221
|
const namespace = url.pathname.slice('/runaway-control/'.length)
|
|
161
222
|
return request
|