Keep flow state across a restart, and tighten the flow typing

The engine fell back to MemoryState because there was no Redis to talk
to, so every value was lost on restart. Adds a redis service with
append-only persistence, reachable only from the backend, and points
REDIS_HOST at it.

state.py and pipeline.py leave the strict-mypy exclusion. redis-py types
its calls as sync/async unions; the casts narrow that at the points of
use rather than switching to redis.asyncio, which would make a
deliberately synchronous backend asynchronous. nodes.py stays excluded.

The .env.example CORS entry belongs with the CI work that follows.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KkmeRiyeYmVZqJVwuyHq9o
This commit is contained in:
Melvin Strobl
2026-08-15 21:19:21 +02:00
co-authored by Claude Opus 5
parent 82356810ce
commit 11d491dae0
6 changed files with 67 additions and 21 deletions
+3
View File
@@ -45,6 +45,9 @@ services:
ports:
- "127.0.0.1:8080:8080"
redis:
restart: "no"
backend:
restart: "no"
ports:
+27
View File
@@ -29,6 +29,27 @@ services:
- POSTGRES_USER=${POSTGRES_USER?Variable not set}
- POSTGRES_DB=${POSTGRES_DB?Variable not set}
redis:
image: redis:8.2-alpine
container_name: fluksio-redis
restart: always
security_opt:
- no-new-privileges:true
# Flow state, not a cache: append-only persistence keeps the last value of
# every message across a restart.
command: redis-server --appendonly yes
# Deliberately not on `proxy` and not published: only the backend talks to it.
networks:
- default
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
retries: 5
start_period: 10s
timeout: 5s
volumes:
- app-redis-data:/data
adminer:
image: adminer
container_name: fluksio-adminer
@@ -94,6 +115,9 @@ services:
db:
condition: service_healthy
restart: true
redis:
condition: service_healthy
restart: true
prestart:
condition: service_completed_successfully
env_file:
@@ -116,6 +140,8 @@ services:
- POSTGRES_USER=${POSTGRES_USER?Variable not set}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set}
- SENTRY_DSN=${SENTRY_DSN}
# Flow state survives a restart in Redis; without a host it stays in memory.
- REDIS_HOST=redis
# Flows are files in a git repository; secrets sit encrypted beside it.
- FLOWS_DIR=/data/flows
- SECRETS_FILE=/data/secrets.enc
@@ -183,6 +209,7 @@ services:
volumes:
app-db-data:
app-redis-data:
app-flow-data:
networks: