fix: bound Workbench read model latency (#1912)

This commit is contained in:
Lyon
2026-06-22 18:58:31 +08:00
committed by GitHub
parent 5c98660816
commit df487ec088
2 changed files with 27 additions and 5 deletions
+5 -2
View File
@@ -557,7 +557,10 @@ lanes:
HWLAB_BOOTSTRAP_ADMIN_API_KEY: secretRef:hwlab-v03-master-server-admin-api-key/api-key
HWLAB_USER_BILLING_URL: http://hwlab-user-billing.hwlab-v03.svc.cluster.local:6670
HWLAB_WORKBENCH_RUNTIME_URL: http://hwlab-workbench-runtime.hwlab-v03.svc.cluster.local:6671
HWLAB_WORKBENCH_RUNTIME_TIMEOUT_MS: "10000"
HWLAB_WORKBENCH_RUNTIME_TIMEOUT_MS: "1800"
HWLAB_WORKBENCH_FACTS_QUERY_MAX_ATTEMPTS: "2"
HWLAB_WORKBENCH_FACTS_QUERY_BACKOFF_BASE_MS: "120"
HWLAB_WORKBENCH_FACTS_QUERY_BACKOFF_MAX_MS: "250"
HWLAB_USER_BILLING_LOGIN_RETRY_ATTEMPTS: "2"
HWLAB_USER_BILLING_LOGIN_RETRY_DELAY_MS: "250"
HWLAB_USER_BILLING_CODE_AGENT_ENABLED: "1"
@@ -586,7 +589,7 @@ lanes:
HWLAB_WORKBENCH_RUNTIME_DB_URL: secretRef:hwlab-cloud-api-v03-db/database-url
HWLAB_WORKBENCH_RUNTIME_PORT: "6671"
HWLAB_WORKBENCH_RUNTIME_DB_POOL_MAX: "32"
HWLAB_WORKBENCH_RUNTIME_QUERY_TIMEOUT_MS: "10000"
HWLAB_WORKBENCH_RUNTIME_QUERY_TIMEOUT_MS: "1500"
HWLAB_WORKBENCH_RUNTIME_READY_TIMEOUT_MS: "2000"
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: http://otel-collector.platform-infra.svc.cluster.local:4318/v1/traces
OTEL_SERVICE_NAME: hwlab-workbench-runtime
+22 -3
View File
@@ -136,7 +136,7 @@ export async function handleWorkbenchRealtimeHttp(request, response, url, option
});
emitWorkbenchRealtimeAcceptedOtelSpan(request, options.env);
if (activeTraceId) {
await (perf ? perf.measure("workbench_initial_trace", () => writeTraceRealtimeSnapshot({ writeEvent, options, actor: auth.actor, traceId: activeTraceId, reason: "initial" })) : writeTraceRealtimeSnapshot({ writeEvent, options, actor: auth.actor, traceId: activeTraceId, reason: "initial" }));
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;
@@ -158,7 +158,7 @@ export async function handleWorkbenchRealtimeHttp(request, response, url, option
cursor: { traceSeq: row.projectedSeq, outboxSeq: row.outboxSeq },
projectionStatus: { terminal: row.terminal, sealed: row.sealed }
});
void writeTraceRealtimeSnapshot({ writeEvent, options, actor: auth.actor, traceId: activeTraceId, reason: "terminal" });
void writeTraceRealtimeSnapshotSafe({ writeEvent, options, actor: auth.actor, traceId: activeTraceId, reason: "terminal" });
} else {
writeEvent("workbench.trace.event", {
type: "trace.event",
@@ -203,7 +203,7 @@ export async function handleWorkbenchRealtimeHttp(request, response, url, option
});
}
if (event?.terminal === true || TERMINAL_STATUSES.has(normalizeStatus(event?.status))) {
void writeTraceRealtimeSnapshot({ writeEvent, options, actor: auth.actor, traceId: activeTraceId, reason: "terminal" });
void writeTraceRealtimeSnapshotSafe({ writeEvent, options, actor: auth.actor, traceId: activeTraceId, reason: "terminal" });
}
});
cleanup.push(unsubscribe);
@@ -1826,6 +1826,25 @@ async function writeTraceRealtimeSnapshot({ writeEvent, options, actor, traceId,
});
}
async function writeTraceRealtimeSnapshotSafe(input) {
try {
await writeTraceRealtimeSnapshot(input);
} catch (error) {
input.writeEvent("workbench.error", {
type: "error",
traceId: input.traceId,
reason: input.reason,
error: {
code: "workbench_trace_snapshot_failed",
causeCode: error?.code ?? null,
retryable: error?.data?.retryable === true,
message: error?.message ?? "Workbench trace snapshot failed.",
valuesRedacted: true
}
});
}
}
async function visibleTraceContext(options, actor, traceId) {
const readModel = createWorkbenchReadModel(options, actor);
const result = readModel.resultForTrace(traceId);