Files
app/backend/tests/test_db.py
T
stroblmeandClaude Opus 5 961a8f881d Keep the engine's state in SQLite, not Postgres
One process owns this database — the image has run a single uvicorn
worker for that reason since the four-engines bug — so a file beside the
flows is the honest shape for it, and it is what lets `fluksio serve`
need no infrastructure at all. Live values, node execution and the work
queue never came here anyway; what does is a rollup a minute at a time,
a row per cascade and the run history, and WAL keeps the readers going
while that one writer works.

DATA_DIR is now the one setting that moves everything an installation
keeps; the rest derive from it and the images still spell theirs out.
The schema is prepared in-process at startup, so the prestart service is
gone, and the ten Postgres-only revisions collapse into one portable
baseline.

Three things only worked because psycopg was casting for us: a token's
subject arriving as a string where the column is a UUID, `greatest`, and
`date_bin`. The timestamps needed a column type of their own — SQLite
stores no offset, and a naive datetime read back either raises against an
aware `now` or serialises as local time.

Postgres stays in the stack only for Umami, behind the analytics profile.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 22:19:45 +02:00

34 lines
1.3 KiB
Python

"""What the database has to keep true whatever dialect is under it."""
from datetime import datetime, timedelta, timezone
from sqlmodel import Session, select
from fluksio.core.db import engine
from fluksio.models import EngineEvent
# The `db` fixture is session-scoped and autouse, so the schema is already there.
def test_a_stored_instant_comes_back_aware_and_in_utc() -> None:
"""SQLite stores no offset, so the column type has to put one back.
Without it a timestamp read from the database is naive: comparing it to
`datetime.now(timezone.utc)` raises, and serialising it hands the frontend
a time with no zone, which it reads as local.
"""
stamp = datetime(2026, 8, 21, 15, 30, tzinfo=timezone(timedelta(hours=2)))
with Session(engine) as session:
session.add(
EngineEvent(ts=stamp, type="node_error", flow="tz", node="n", detail="")
)
session.commit()
with Session(engine) as session:
stored = session.exec(select(EngineEvent).where(EngineEvent.flow == "tz")).one()
assert stored.ts.tzinfo is not None
assert stored.ts.utcoffset() == timedelta(0)
assert stored.ts == stamp
# And it still compares against an aware "now" rather than raising.
assert stored.ts < datetime.now(timezone.utc)