`receive_text` raises `WebSocketDisconnect` once the peer has gone and `RuntimeError` on every call after that. The loop swallowed both — the exception was checked only to decide whether the frame held a media subscription — and immediately made another read, which raised again. A closed tab therefore left a coroutine reading a dead socket at full tilt: around 15,000 turns a second, one orphaned `Queue.get()` per turn parked on the bus queue's waiter list. The event loop stalled behind it, `/health` answered 503 on its loop-lag check, and Docker's probe plus Traefik took the API out of the pool mid-request — which is what `make verify` was dying on, with `TypeError: Failed to fetch` from the browser. The spin ended only when an event finally reached the send path and the socket raised there, so it lasted from milliseconds to minutes depending on what the bus happened to be carrying. Four abandoned sockets logged 2,518 `Task was destroyed but it is pending!` lines and up to 2.6s of loop lag; twenty now log none and cost 1.0ms. A failed read is the disconnect, so it ends the stream. The getter created beside it is cancelled rather than abandoned: nothing reads it after the turn that made it, and left behind it would also take an event the live reader wanted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CL9zvnnvcp1mvA8o7impxk
Fluksio App
Fluksio is a node-based automation software that brings trust and reliability to your flow. It just works and looks good.
The core of Fluksio: a node-based, test-driven automation software built to scale. This
repo holds the FastAPI backend, the flow engine, and the dashboard SPA. It is served on
app.${DOMAIN} (SPA) and api.${DOMAIN} (API)
Layout
backend/ FastAPI + SQLModel + Alembic + SQLite
fluksio/flow/ the flow engine (nodes, pipeline, state backends, controller)
fluksio/cli.py `fluksio serve` / `enroll` / `worker`
worker/ the `fluksio-worker` distribution: the agent and the node runner
frontend/ React 19 + TanStack Router + Tailwind 4 + shadcn/ui
docs/ the public documentation site (zensical), served on docs.${DOMAIN}
docker/ compose.yml → compose.dev.yml → compose.local.yml (+ compose.traefik.yml)
scripts/ generate-client.sh, test.sh
Install without Docker
Get started quickly by running
pip install fluksio
fluksio serve
Then, head over to fluksio.com, sign up and add a new instance. Using the code provided, run
fluksio enroll <code>
and you're ready to rock.
Fluksio is distributed at it's heart. A machine that should only run nodes for an engine elsewhere installs less:
pip install fluksio-worker
fluksio-worker --url wss://api.fluksio.com/api/v1/workers/attach --token "$TOKEN" --labels gpu
Getting started
Normally driven from the workspace root (make init once, then make dev). Standalone:
make install # uv sync + bun install
make dev-utils # proxy and mailcatcher only
make dev-backend # FastAPI on :8000, hot reload
make dev-frontend # Vite on :5173
make test # pytest + Playwright (the e2e half needs the stack up)
make lint # ruff + mypy + biome
make generate-client # regenerate the frontend SDK from the OpenAPI schema
make help lists every target.
Documentation
The public site lives in docs/ and is built with zensical:
make docs-serve # live preview on :8000
make docs # static build into ./site
It is served at docs.${DOMAIN} by the docs service in docker/compose.yml,
and .gitea/workflows/docs.yml builds it with --strict on every push.
License
Copyright (C) 2026 Melvin Strobl - GNU Affero General Public License v3.0 or later. See LICENSE.