fix(workbench): refresh work orders after projection events
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { shouldApplyWorkbenchSnapshot } from "./use-workbench-sync";
|
||||
import type { WorkbenchEvent } from "../api/workbench-sync-client";
|
||||
import { shouldApplyWorkbenchSnapshot, shouldRefreshWorkbenchRuntime } from "./use-workbench-sync";
|
||||
|
||||
describe("workbench snapshot ordering", () => {
|
||||
it("rejects an older concurrent response even when its cursor is valid", () => {
|
||||
@@ -29,3 +30,24 @@ describe("workbench snapshot ordering", () => {
|
||||
})).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("work-order projection readiness", () => {
|
||||
const event: WorkbenchEvent = {
|
||||
schema: "workbench-event@1",
|
||||
event_seq: 1,
|
||||
event_id: "324ff7ee-c2d4-5184-a84b-48fb14a2933e",
|
||||
project_id: "324ff7ee-c2d4-5184-a84b-48fb14a2933e",
|
||||
topic: "workbench.work_order.changed",
|
||||
aggregate_type: "peripheral_work_order",
|
||||
aggregate_id: "source-order",
|
||||
aggregate_revision: 1,
|
||||
occurred_at: "2026-10-08T00:00:00Z",
|
||||
metadata: { source: "peripheral_sample" }
|
||||
};
|
||||
|
||||
it("waits for authoritative projection events instead of fetching a premature snapshot", () => {
|
||||
expect(shouldRefreshWorkbenchRuntime(event)).toBe(false);
|
||||
expect(shouldRefreshWorkbenchRuntime({ ...event, aggregate_type: "operational_action" })).toBe(true);
|
||||
expect(shouldRefreshWorkbenchRuntime({ ...event, topic: "workbench.alert.changed", aggregate_type: "workbench_alert" })).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,6 +14,12 @@ const RUNTIME_TOPICS = new Set<WorkbenchEvent["topic"]>([
|
||||
"analysis.run.changed"
|
||||
]);
|
||||
|
||||
export function shouldRefreshWorkbenchRuntime(event: WorkbenchEvent) {
|
||||
// Source changes wake the backend synchronizer. Its committed task events
|
||||
// refresh the UI after the authoritative projection is ready.
|
||||
return RUNTIME_TOPICS.has(event.topic) && event.aggregate_type !== "peripheral_work_order";
|
||||
}
|
||||
|
||||
export type WorkbenchSyncState = {
|
||||
snapshot: WorkbenchSyncSnapshot | null;
|
||||
events: WorkbenchEvent[];
|
||||
@@ -99,7 +105,7 @@ export function useWorkbenchSync(getAccessToken?: AccessTokenProvider): Workbenc
|
||||
if (unseen.length === 0) return;
|
||||
cursorRef.current = unseen.at(-1)!.event_seq;
|
||||
setEvents((current) => [...current, ...unseen]);
|
||||
if (unseen.some((event) => RUNTIME_TOPICS.has(event.topic))) {
|
||||
if (unseen.some(shouldRefreshWorkbenchRuntime)) {
|
||||
if (runtimeRefreshRef.current !== undefined) window.clearTimeout(runtimeRefreshRef.current);
|
||||
runtimeRefreshRef.current = window.setTimeout(() => {
|
||||
void loadSnapshot().catch((nextError) => {
|
||||
|
||||
Reference in New Issue
Block a user