fix(workbench): stream session outbox events over sse (#1962)
This commit is contained in:
@@ -144,34 +144,45 @@ export async function handleWorkbenchRealtimeHttp(request, response, url, option
|
||||
emitWorkbenchRealtimeAcceptedOtelSpan(request, options.env);
|
||||
if (activeTraceId) {
|
||||
await (perf ? perf.measure("workbench_initial_trace", () => writeTraceRealtimeSnapshotSafe({ writeEvent, options, actor: auth.actor, traceId: activeTraceId, reason: "initial" })) : writeTraceRealtimeSnapshotSafe({ writeEvent, options, actor: auth.actor, traceId: activeTraceId, reason: "initial" }));
|
||||
const runtimeStore = options.runtimeStore ?? null;
|
||||
const outboxPollMs = parsePositiveInteger(options.env?.HWLAB_WORKBENCH_SSE_OUTBOX_POLL_MS, 2000);
|
||||
let outboxCursor = 0;
|
||||
if (typeof runtimeStore?.readWorkbenchProjectionOutbox === "function") {
|
||||
}
|
||||
const runtimeStore = options.runtimeStore ?? null;
|
||||
const outboxPollMs = parsePositiveInteger(options.env?.HWLAB_WORKBENCH_SSE_OUTBOX_POLL_MS, 2000);
|
||||
let outboxCursor = 0;
|
||||
const outboxTraceSnapshots = new Set(activeTraceId ? [activeTraceId] : []);
|
||||
if (typeof runtimeStore?.readWorkbenchProjectionOutbox === "function" && (streamSessionId || activeTraceId)) {
|
||||
const pollOutbox = async () => {
|
||||
if (closed || response.destroyed) return;
|
||||
try {
|
||||
const rows = await runtimeStore.readWorkbenchProjectionOutbox({ afterSeq: outboxCursor, limit: 50, traceId: activeTraceId });
|
||||
const query = { afterSeq: outboxCursor, limit: 50 };
|
||||
if (streamSessionId) query.sessionId = streamSessionId;
|
||||
else query.traceId = activeTraceId;
|
||||
const rows = await runtimeStore.readWorkbenchProjectionOutbox(query);
|
||||
for (const row of rows) {
|
||||
if (closed || response.destroyed) break;
|
||||
outboxCursor = row.outboxSeq;
|
||||
const rowTraceId = safeTraceId(row.traceId) ?? activeTraceId;
|
||||
const rowSessionId = safeSessionId(row.sessionId ?? streamSessionId) ?? streamSessionId;
|
||||
if (rowTraceId && !outboxTraceSnapshots.has(rowTraceId)) {
|
||||
outboxTraceSnapshots.add(rowTraceId);
|
||||
await writeTraceRealtimeSnapshotSafe({ writeEvent, options, actor: auth.actor, traceId: rowTraceId, reason: "outbox-session" });
|
||||
}
|
||||
if (row.commitType === "terminal") {
|
||||
writeEvent("workbench.trace.snapshot", {
|
||||
type: "trace.snapshot",
|
||||
sessionId: row.sessionId ?? streamSessionId,
|
||||
sessionId: rowSessionId,
|
||||
threadId: streamThreadId,
|
||||
traceId: row.traceId ?? activeTraceId,
|
||||
traceId: rowTraceId,
|
||||
reason: "outbox-terminal",
|
||||
cursor: { traceSeq: row.projectedSeq, outboxSeq: row.outboxSeq },
|
||||
projectionStatus: { terminal: row.terminal, sealed: row.sealed }
|
||||
});
|
||||
void writeTraceRealtimeSnapshotSafe({ writeEvent, options, actor: auth.actor, traceId: activeTraceId, reason: "terminal" });
|
||||
if (rowTraceId) void writeTraceRealtimeSnapshotSafe({ writeEvent, options, actor: auth.actor, traceId: rowTraceId, reason: "terminal" });
|
||||
} else {
|
||||
writeEvent("workbench.trace.event", {
|
||||
type: "trace.event",
|
||||
sessionId: row.sessionId ?? streamSessionId,
|
||||
sessionId: rowSessionId,
|
||||
threadId: streamThreadId,
|
||||
traceId: row.traceId ?? activeTraceId,
|
||||
traceId: rowTraceId,
|
||||
cursor: { traceSeq: row.projectedSeq, outboxSeq: row.outboxSeq }
|
||||
});
|
||||
}
|
||||
@@ -186,7 +197,7 @@ export async function handleWorkbenchRealtimeHttp(request, response, url, option
|
||||
await pollOutbox();
|
||||
const outboxTimer = setInterval(() => { void pollOutbox(); }, Math.max(500, outboxPollMs));
|
||||
cleanup.push(() => clearInterval(outboxTimer));
|
||||
} else {
|
||||
} else if (activeTraceId) {
|
||||
const unsubscribe = traceStore.subscribe(activeTraceId, (event, snapshot) => {
|
||||
if (event) {
|
||||
writeEvent("workbench.trace.event", {
|
||||
|
||||
Reference in New Issue
Block a user