Let a node's failure outlive the run that followed it
A node's error cleared the moment it ran again, so a failure that genuinely fired an alert could leave no trace on the canvas by the time anyone looked. The engine records it now — on the node's status, so it survives a reload and every client agrees — and reading the traceback is what clears it. The seam is the event bus, which is where every failing path already meets: a queued live run, an explicit run, a preview, and a single triggered node all publish `node_error`, while the controller's own observer would have seen only one of them. That was half the confusion. The other half: clicking a failed neuron on Home often landed on a flow where everything looked fine. Nodes merge into one neuron by instance key — every InfluxDB node pointing at the same bucket is one neuron — and the click went to whichever flow contributed a member first, not the one that failed. It now goes to the failing member and selects it, and the canvas marks a failing node rather than leaving it to the dot alone. The inject node emitted one payload to every port it declared, whatever their types, so an inject on a bool port carrying the text "true" raised at publish time. Each port gets its own field now, typed and parsed by that port's dtype, and remembers what it last sent. A port that is renamed carries its value with it; one that is removed takes its value with it. An inject written before this keeps emitting exactly what it did. The derived-cron chip also appeared on the delay node, where `interval` is a rate limit and a schedule derived from it means nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uq8mtNb97A7praJLyeEYgs
This commit is contained in:
@@ -3,6 +3,7 @@ import { useQueryClient } from "@tanstack/react-query"
|
||||
import { useEffect } from "react"
|
||||
|
||||
import { OpenAPI } from "@/client"
|
||||
import { dashboardKeys, panelKeys } from "@/components/Dashboard/queries"
|
||||
import { connectionStore } from "@/lib/connectionStore"
|
||||
import { apiToken } from "@/lib/portal"
|
||||
import { type LogLine, liveStore, type ValueSource } from "./liveStore"
|
||||
@@ -87,6 +88,7 @@ type FlowEvent =
|
||||
nodes: { id: string; status: string; error?: string | null }[]
|
||||
paused?: string[]
|
||||
}
|
||||
| { type: "dashboard_changed"; dashboard?: string; ts?: number }
|
||||
|
||||
function socketUrl(): string {
|
||||
const base = String(OpenAPI.BASE || window.location.origin)
|
||||
@@ -237,6 +239,18 @@ function connect() {
|
||||
// markers on the flow chips are stale until the list is refetched.
|
||||
client?.invalidateQueries({ queryKey: flowKeys.all })
|
||||
break
|
||||
case "dashboard_changed":
|
||||
// Someone published, or changed which dashboards a panel shows. Refetch
|
||||
// rather than reload: a wall screen must not blank or sign in again.
|
||||
// `exact` matters — the list key is a prefix of every detail key,
|
||||
// including the draft an editor may have open.
|
||||
client?.invalidateQueries({ queryKey: dashboardKeys.all, exact: true })
|
||||
client?.invalidateQueries({
|
||||
queryKey: message.dashboard
|
||||
? dashboardKeys.detail(message.dashboard)
|
||||
: panelKeys.all,
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user