fix(workbench): share sync reads and retry failed invalidations
This commit is contained in:
@@ -82,6 +82,7 @@ export async function consumeWorkbenchEvents(input: {
|
||||
after: number;
|
||||
getAccessToken?: AccessTokenProvider;
|
||||
onEvents: (events: WorkbenchEvent[]) => void;
|
||||
onOpen?: () => void;
|
||||
onReset: () => Promise<void>;
|
||||
signal: AbortSignal;
|
||||
}): Promise<"closed" | "reset"> {
|
||||
@@ -98,30 +99,36 @@ export async function consumeWorkbenchEvents(input: {
|
||||
throw new Error(getServerError(payload, response.status, "工作台事件连接"));
|
||||
}
|
||||
const reader = response.body.getReader();
|
||||
input.onOpen?.();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = "";
|
||||
while (!input.signal.aborted) {
|
||||
const { value, done } = await reader.read();
|
||||
buffer += decoder.decode(value, { stream: !done });
|
||||
if (buffer.length > 1_048_576) throw new Error("工作台事件帧超过大小限制");
|
||||
const events: WorkbenchEvent[] = [];
|
||||
let boundary = buffer.search(/\r?\n\r?\n/);
|
||||
while (boundary >= 0) {
|
||||
const separator = buffer.slice(boundary).match(/^\r?\n\r?\n/)?.[0] ?? "\n\n";
|
||||
const block = buffer.slice(0, boundary);
|
||||
buffer = buffer.slice(boundary + separator.length);
|
||||
const lines = block.split(/\r?\n/);
|
||||
const eventName = lines.find((line) => line.startsWith("event:"))?.slice(6).trim();
|
||||
const data = lines.filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).join("\n");
|
||||
if (eventName === "reset_required") {
|
||||
await input.onReset();
|
||||
return "reset";
|
||||
try {
|
||||
while (!input.signal.aborted) {
|
||||
const { value, done } = await reader.read();
|
||||
buffer += decoder.decode(value, { stream: !done });
|
||||
if (buffer.length > 1_048_576) throw new Error("工作台事件帧超过大小限制");
|
||||
const events: WorkbenchEvent[] = [];
|
||||
let boundary = buffer.search(/\r?\n\r?\n/);
|
||||
while (boundary >= 0) {
|
||||
const separator = buffer.slice(boundary).match(/^\r?\n\r?\n/)?.[0] ?? "\n\n";
|
||||
const block = buffer.slice(0, boundary);
|
||||
buffer = buffer.slice(boundary + separator.length);
|
||||
const lines = block.split(/\r?\n/);
|
||||
const eventName = lines.find((line) => line.startsWith("event:"))?.slice(6).trim();
|
||||
const data = lines.filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).join("\n");
|
||||
if (eventName === "reset_required") {
|
||||
await input.onReset();
|
||||
return "reset";
|
||||
}
|
||||
if (eventName === "workbench_event" && data) events.push(eventSchema.parse(JSON.parse(data)));
|
||||
boundary = buffer.search(/\r?\n\r?\n/);
|
||||
}
|
||||
if (eventName === "workbench_event" && data) events.push(eventSchema.parse(JSON.parse(data)));
|
||||
boundary = buffer.search(/\r?\n\r?\n/);
|
||||
if (events.length > 0) input.onEvents(events);
|
||||
if (done) return "closed";
|
||||
}
|
||||
if (events.length > 0) input.onEvents(events);
|
||||
if (done) return "closed";
|
||||
return "closed";
|
||||
} finally {
|
||||
await reader.cancel().catch(() => undefined);
|
||||
reader.releaseLock();
|
||||
}
|
||||
return "closed";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user