Split the node types into a package, and stop reconnecting per message

nodes.py had grown to 2k lines holding every integration behind a single
blanket mypy exemption. It is now a package split by the outside world
each node talks to, so the exemption shrinks to the four integration
modules; base and mlp are type-checked, which turned up a dozen missing
annotations.

The senders opened a fresh connection — and, in the MQTT case, a fresh
thread pool and event loop — for every single message. HTTP senders now
share one pooled client, and a publisher holds one broker connection for
its lifetime, fed from a bounded queue that drops the oldest value when
the broker cannot keep up.

An HTTP sender also no longer trips over a JSON reply that is not an
object: outputs are keyed by port, so a bare scalar is a valid reply with
nothing to publish.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LF61rxW1FG5YCD2J9YqjY
This commit is contained in:
root
2026-08-16 07:33:10 +02:00
co-authored by Claude Fable 5
parent e7e48c4f13
commit f8693daad6
12 changed files with 2308 additions and 2038 deletions
+7 -3
View File
@@ -60,9 +60,13 @@ Deferring because out of scope is fine, but don't mention deferring than.
runs of that one job collide.
- PERF/UI: (deferred for now) the Monaco chunk is 2.6 MB. It only loads when a node panel opens, but the
editor could be trimmed further or swapped for CodeMirror if that becomes a problem.
- CHORE/FLOW: `app/flow/nodes.py` is excluded from strict mypy (`[[tool.mypy.overrides]]` in
`pyproject.toml`). The node classes still carry prototype typing, `croniter` ships no stubs
and `influxdb_client` does not re-export its names. Shrink it as each integration is revisited.
- CHORE/FLOW: four modules of `app/flow/nodes/` are still excluded from strict mypy
(`[[tool.mypy.overrides]]` in `pyproject.toml`): `mqtt`, `http`, `influx` and `delay`. They
carry prototype typing, `croniter` ships no stubs and `influxdb_client` does not re-export
its names. `base` and `mlp` are checked; shrink the rest as each integration is revisited.
- CHORE/FLOW: a node function returning something other than a dict raises `AttributeError`
in `Node._to_messages` rather than a named error. Outputs are keyed by port, so a non-dict
cannot be one — say so where the return value is mapped.
- PERF/FLOW: every save rebuilds the whole pipeline. Fine at the current flow count; rebuild
only the touched flow when it starts to show.
- FEAT/UI: reintroduce `--chart-*` tokens as one designed sequential scale when the first