fix: report OPFS completion honestly and bound public cache staging
A durable write whose journal transaction could not be completed returned plain success with `SUCCEEDED` telemetry. The payload was committed but the transaction stayed `COMMITTED`, so the reconcile backlog and its quota pressure grew while every caller was told the write had settled. That is now a `RECONCILE` failure with the effect certainty preserved, and an unfinished delete is observed `DEGRADED` rather than clean. The worker seam lost causes in both directions. A bootstrap failure answered every request with kind `CAPABILITIES`, so the gateway read a kind mismatch and replaced the real `BLOCKED` or `QUOTA_EXCEEDED` with a generic `UNSUPPORTED`; the envelope's correlation is now captured once at the listener. On the client, the pending row and its timer were released before the reply was decoded, so a trap that threw inside the decoder left the public promise pending with nothing left to time it out, and a throwing `requestId` getter produced a timeout instead of a prompt protocol failure. Public cache staging handed its signal to each `Request` and called that ownership. A fetch that ignored it held the mutation lock forever, and a digest that finished after the abort still wrote both the asset and the activation marker — publishing a release nobody was waiting for. One terminal owner now covers the whole staging body and every await re-checks it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
df18349682
commit
632b230c82
@@ -157,12 +157,21 @@ export async function startBrowserOpfsDedicatedWorker(
|
||||
host.addEventListener("message", (event) => {
|
||||
if (!hasRequestId(event.data)) return;
|
||||
const requestData = event.data;
|
||||
// NS-05. The envelope's correlation is captured once, up front. Answering a
|
||||
// bootstrap failure with a default `CAPABILITIES` kind made the client see
|
||||
// an expected-kind mismatch and overwrite the real cause — a `BLOCKED` or
|
||||
// `QUOTA_EXCEEDED` outage was reported to operators as `UNSUPPORTED`.
|
||||
const correlation = requestCorrelation(requestData);
|
||||
void runtimePromise
|
||||
.then((runtime) => runtime.handleRequest(requestData))
|
||||
.then((response) => postWorkerResponse(host, response))
|
||||
.catch((error: unknown) => {
|
||||
host.postMessage(
|
||||
failure(requestData.requestId, mapRuntimeFailure(error)),
|
||||
failure(
|
||||
correlation.requestId,
|
||||
mapRuntimeFailure(error),
|
||||
correlation.kind,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1871,6 +1880,31 @@ function hasRequestId(
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* NS-05. Reads a request envelope's correlation exactly once, through its own
|
||||
* data descriptors, so a reply can name the request it answers even when the
|
||||
* runtime that would have handled it never came up. An envelope whose kind
|
||||
* cannot be read stays a protocol-level failure rather than borrowing an
|
||||
* unrelated kind.
|
||||
*/
|
||||
function requestCorrelation(
|
||||
value: Readonly<{ requestId: string }>,
|
||||
): Readonly<{ requestId: string; kind: OpfsWorkerRequest["kind"] }> {
|
||||
let kind: unknown;
|
||||
try {
|
||||
kind = Object.getOwnPropertyDescriptor(value, "kind")?.value;
|
||||
} catch {
|
||||
kind = undefined;
|
||||
}
|
||||
return {
|
||||
requestId: value.requestId,
|
||||
kind:
|
||||
typeof kind === "string" && WORKER_REQUEST_KINDS.has(kind)
|
||||
? (kind as OpfsWorkerRequest["kind"])
|
||||
: "CAPABILITIES",
|
||||
};
|
||||
}
|
||||
|
||||
function isWorkerRequest(value: unknown): value is OpfsWorkerRequest {
|
||||
return Boolean(
|
||||
hasRequestId(value) &&
|
||||
|
||||
Reference in New Issue
Block a user