Graph view: unique pill keys for chunk jobs (second duplicate-key consumer)
The graph page's pipeline pills keyed rows by run.chatId — the source id, shared by every chunk job of a fan-out (the dock got the same fix in 8f66f47; this consumer was missed). /api/graph/status rows now carry an id (the registry job key: source id, or 'src#i'), and the pills key by it. chatId stays the SOURCE id — the reveal refetch and per-run cost refresh track chatId SETS, which dedupe naturally and fire when the source's LAST row leaves the feed.
This commit is contained in:
@@ -13,6 +13,11 @@ export const dynamic = "force-dynamic";
|
||||
|
||||
export async function GET() {
|
||||
const runs = extractionStatuses().map((run) => ({
|
||||
// Unique row id (the registry job key: source id, or "src#i" for
|
||||
// chunk jobs) — one source's rows share chatId, and React keys on
|
||||
// it would collide. chatId stays the SOURCE id: reveal/cost
|
||||
// tracking in the view is source-scoped by design.
|
||||
id: run.part ? `${run.chatId}#${run.part.i}` : run.chatId,
|
||||
chatId: run.chatId,
|
||||
// The run's own label (the file path for notes imports) wins; chat
|
||||
// runs fall back to the chat store's title. Chunk jobs append their
|
||||
|
||||
@@ -1067,7 +1067,10 @@ export function GraphView() {
|
||||
// merge is its own graph change and must surface immediately, not wait
|
||||
// for the whole feed to drain. A redundant fetch on aborted runs is
|
||||
// free — the same doctrine as the deletion-refresh path below.
|
||||
const [pipelineRuns, setPipelineRuns] = useState<{ chatId: string; title: string; phase: string; startedAt: number }[]>([]);
|
||||
// Row ids are the registry JOB keys (source id, or "src#i" for chunk
|
||||
// jobs) — unique per pill; chatId stays the SOURCE id (reveal/cost
|
||||
// tracking is source-scoped).
|
||||
const [pipelineRuns, setPipelineRuns] = useState<{ id: string; chatId: string; title: string; phase: string; startedAt: number }[]>([]);
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
let prevIds = new Set<string>();
|
||||
@@ -1552,7 +1555,7 @@ export function GraphView() {
|
||||
{costs && costs.runs.length > 0 && <GraphCostControl costs={costs} />}
|
||||
{pipelineRuns.map((run) => (
|
||||
<div
|
||||
key={run.chatId}
|
||||
key={run.id}
|
||||
className="flex items-center gap-2 rounded-full border bg-card/85 px-3 py-1.5 text-xs text-muted-foreground shadow-lg backdrop-blur"
|
||||
>
|
||||
<Loader2Icon className="size-3.5 shrink-0 animate-spin" />
|
||||
|
||||
Reference in New Issue
Block a user