Surface a failing connector poll as node health and a flow issue
The poll loop remembered what it read rather than what it published, so a value the node could not publish counted as said: the next poll skipped it, succeeded, and health went back to ok with the port still dark. Remember it only after inject returns, and report ok last. A node reporting itself down is now derived into its flow's issues on read and counted on the health summary, so the canvas marks it and Home says so. Being down does not stop the flow, and the issue clears by itself when the node reports well again. The repeating poll warning is logged once per outage rather than once per tick. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K1moruzue2kTJd3uVisgNk
This commit is contained in:
@@ -104,6 +104,40 @@ def test_a_failing_poll_reports_down_and_keeps_going():
|
||||
assert health[-1][0] == "ok"
|
||||
|
||||
|
||||
def test_an_undeclared_port_keeps_failing_until_the_node_declares_it():
|
||||
"""A publication that raised is retried, not remembered as published.
|
||||
|
||||
The loop remembers what it published. If it remembered what it read, a
|
||||
value the node cannot publish would be skipped on the next poll, the poll
|
||||
would succeed, and the node would go back to reporting itself healthy with
|
||||
its port still dark.
|
||||
"""
|
||||
|
||||
class Chatty(Sensor):
|
||||
"""Reads a port it never declared."""
|
||||
|
||||
async def poll(self) -> dict[str, Any]:
|
||||
self.polls += 1
|
||||
return {"reading": 21.5, "lat": 48.1}
|
||||
|
||||
health: list[tuple[str, str | None]] = []
|
||||
node = Chatty(
|
||||
provides=[MessageSpec(name="reading", dtype=DType.FLOAT)],
|
||||
params={"poll_interval": 0.01},
|
||||
)
|
||||
node.assign_flow("demo", "sensor")
|
||||
node._on_health = lambda _node, status, detail: health.append((status, detail))
|
||||
pipeline = Pipeline(nodes=[node])
|
||||
|
||||
run_briefly(node)
|
||||
|
||||
assert pipeline.state.get("demo.reading") is None
|
||||
assert health[-1][0] == "down"
|
||||
assert "NodeOutputError" in (health[-1][1] or "")
|
||||
# Still failing on the last poll, not just the first.
|
||||
assert len([entry for entry in health if entry[0] == "down"]) > 1
|
||||
|
||||
|
||||
class Actuator(ConnectorNode):
|
||||
"""A connector that commands something instead of reading it."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user