1f9fd08b403fd2e877f2237092a4d7bad82cd144
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c312e37b4a
|
Drop the pooler from the MVP: point everything straight at Postgres
.env.example and the README still told people to use pgCat on :6432, the exact setup that hangs on every parameterised query. With no prod and one backend instance there is nothing for a pooler to multiplex, and postgres-js already pools in-process, so DATABASE_URL now points at Postgres on :5432 in .env.example, dev-env.sh and drizzle.config.ts. prepare:false is kept in src/db/index.ts on purpose, so adding PgBouncer later (tested working) is a config change rather than a code change. The long measurement narrative in that file's comment is cut to the decision and the pointer to PLAN.md, where the numbers now live. |
||
|
|
0e6a4aaa93
|
Record that this client cannot run behind pgCat 1.2.0, and stop lying about it
A real pooled database became available, so the deployment assumption in src/db/index.ts - "points at pgCat/PgBouncer, so keep prepared statements disabled" - was finally testable. It does not hold. Through pgCat 1.2.0 an unparameterised `select 1` succeeds, and so does `select count(*) from organisations`, but any query carrying a bind parameter hangs forever. That is true with prepare:false, with prepare:true, with fetch_types:false, and inside an explicit transaction. The same queries straight at Postgres all pass, and psql's \bind through the same pool returns its row, so the fault is specific to how postgres-js frames those messages rather than to extended protocol. Every Drizzle query binds parameters, so no subset of this app works there. drizzle-kit hung at commit for the same reason - it builds its own client and drizzle.config.ts cannot pass prepare:false - having executed all 14 statements of 0000, which then rolled back. Transaction-mode pooling itself was confirmed, not assumed: in one client session consecutive statements hopped between server backends while statements inside BEGIN..COMMIT stayed pinned to one. So the comment now records what was measured, names PgBouncer as the pooler this configuration actually suits, and says migrations go straight at Postgres. dev-env.sh's note gets the same correction. Two real bugs found on the way there: - e2e-authz.sh and e2e-edge.sh hardcoded `psql -h localhost -U continuum -d continuum` while both read DATABASE_URL for the backend under test. Point DATABASE_URL elsewhere and the suite seeds fixtures into one database while exercising another - and its own failure message says "no database at $DATABASE_URL", naming a URL nothing ever tried. Both now use `psql "$DATABASE_URL"`. - drizzle.config.ts fell back to port 6432, where nothing listens here, so a bare db:migrate failed confusingly. It now matches dev-env.sh's DEV_DATABASE_URL. bun test 128 pass / 0 fail; e2e-authz.sh PASS with 68 checks against local Postgres after the psql_q change. e2e-edge.sh was not re-run because it drives the real printers, and its change is the same line. |
||
|
|
d827b465cf
|
Commit the first migration, and apply schema the same way everywhere
`drizzle/` was gitignored, so every environment re-derived the schema from src/db/schema and nothing recorded what a given release expected. That is survivable while nothing is deployed and a problem the moment something is. The generated migration is now committed: four tables, three enums, five foreign keys, and the per-farm unique index on gateway_printer_id. It needed one hand-added line to be usable on its own. drizzle-kit does not emit extension statements, but frame_embeddings.embedding is vector(512) with an ivfflat index, so as generated the migration only applied to a database somebody had already run `CREATE EXTENSION vector` on - which was true locally precisely because dev-env.sh does that, and would not have been true on a fresh deploy. `CREATE EXTENSION IF NOT EXISTS vector` now leads the file, and it survives regeneration: drizzle only appends new migrations, and the diffing snapshot lives in meta/0000_snapshot.json rather than in the SQL. Verified by dropping the database, recreating it with no extensions at all (`pg_extension` count 0), and running db:migrate: the extension and all four tables were created, `db:generate` then reported no pending changes, and the e2e script still passed against both live printers on the result. `dev-env.sh schema` now runs `migrate` instead of `push`, so a local database and a deployed one get the schema by the same route - testing `push` locally while production runs `migrate` tests two different things. `push` is still available as its own command for iterating on a table that is still moving, with a comment about what it does not record. |
||
|
|
42d4b3820a
|
Add a runnable dev environment, and fix the pins that stopped it booting
The edge route had never been run. Adding a way to run it turned up that the server could not start at all, for two independent dependency reasons that typechecking could not see: - `elysia: ^1.1.26` had resolved to 1.4.30, which calls `t.Module` - a TypeBox 0.34 API - while this repo pinned TypeBox 0.33. `t.Module is not a function`. - `drizzle-typebox: ^0.2.1` resolved to a version whose peers demand `drizzle-orm >= 0.36`, against the `^0.33.0` pinned here. Importing it threw `Export named 'getViewSelectedFields' not found`. Both are caret ranges that drifted into combinations nobody chose. elysia, @sinclair/typebox and the drizzle packages are now pinned tightly, TypeBox forward to 0.34.52 (which satisfies Elysia and drizzle-typebox 0.1.1 alike), and tests/dependency_identity.test.ts fails if the TypeBox version ever differs between here and @continuum/ts-types - the skew that made every shared schema invalid, with an error message pointing at Standard Schema instead. Dropping to drizzle-typebox 0.1.1 widens `jsonb` in the generated validators, so `metadata` needs an explicit object shape in validators.ts; the column is declared `$type<Record<string, unknown>>()` and a validated body otherwise is not assignable to `.values()`. scripts/: - `install-docker.sh` - one-time host setup, kept separate because it touches the machine rather than containers. - `dev-env.sh up|down|reset|status|psql|schema|env` - Valkey + Postgres/pgvector. Uses docker-compose.yml when a daemon answers, and otherwise runs the same two services from apt. That fallback is not hypothetical: Docker cannot run in this sandbox at all. dockerd needs CAP_NET_ADMIN to build its bridge; with `--bridge=none --iptables=false` it starts but cannot unpack an image without CAP_SYS_ADMIN; with `--storage-driver=vfs` it still fails because registering a layer needs user namespaces, which are blocked outright. All three are host-level grants, so no script can work around them - hence a second path rather than a broken first one. - `e2e-edge.sh` - the test the unit tests cannot be. Seeds a farm, claims its printers, mints an edge token, runs the real continuum-proxy, and asserts live telemetry reached Postgres and a command reached a printer. It only sends a fan speed, only to a printer reporting IDLE, and puts it back afterwards. - `capture-gateway-frames.js` - records what a gateway really sends, for refreshing tests/fixtures/. Read-only unless FAN_TEST_PRINTER is set. The test comment referred to this before it existed. Verified end to end, from a dropped and freshly migrated database: `h2c` persisted as printing/RUNNING 22% layer 2/25 nozzle 230 bed 35 with 3 HMS alerts, `p1p` as idle/IDLE, and `POST /printers/:id/commands` reached the P1P's fan and came back ok:true. An unclaimed printer is refused 409 PRINTER_UNREACHABLE rather than guessed at. Two things the e2e script got wrong first, both now fixed in it: it waited for the first printer row instead of all of them, which silently tested only the v2 printer (a v1 Bambu reports one tick later); and `$!` after `( cd ... ) &` is the subshell, so cleanup left an orphaned gateway reconnecting with a token for a deleted farm and polluting the next run. Note: `drizzle/` is gitignored, so the generated migration is not committed and there is no migration history in the repo. Left as-is deliberately - that is a workflow call, flagged in PLAN.md. |