From 88cc98f3cc36882f601e699c3133faba5777d827 Mon Sep 17 00:00:00 2001 From: Julian Cuni Date: Fri, 1 May 2026 10:37:31 +0200 Subject: [PATCH] Switch to timescaledb-ha image; enable PostGIS in migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migration 0001_positions.sql now runs CREATE EXTENSION IF NOT EXISTS postgis alongside timescaledb. PostGIS isn't used in Phase 1 but enabling it now means Phase 2's geofence engine doesn't need a separate migration step. The deploy stack uses the timescale/timescaledb-ha:*-all image which ships both extensions. Integration test (pipeline.integration.test.ts) updated to use the same timescale/timescaledb-ha:pg16.6-ts2.17.2-all image as the deploy stack. Stock POSTGRES_USER/PASSWORD/DB env vars retained — if recent ha-image revisions don't accept them, the test container will fail clearly on first run with Docker, and we'll switch to the right env-var scheme. --- src/db/migrations/0001_positions.sql | 11 ++++++++++- test/pipeline.integration.test.ts | 14 ++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/db/migrations/0001_positions.sql b/src/db/migrations/0001_positions.sql index 9745a64..91aaca8 100644 --- a/src/db/migrations/0001_positions.sql +++ b/src/db/migrations/0001_positions.sql @@ -6,8 +6,17 @@ -- writes to (timing_records, stage_results, etc.) are defined in Directus. -- Do NOT modify this table from the Directus admin UI. --- Enable TimescaleDB extension (no-op if already installed at the DB level). +-- Enable required Postgres extensions. No-ops if already installed at the +-- DB level. The deploy stack uses the `timescale/timescaledb-ha:*-all` +-- image which ships TimescaleDB and PostGIS binaries — these CREATE +-- EXTENSION statements just register them on this database. +-- +-- TimescaleDB: hypertable partitioning for the positions table below. +-- PostGIS: not used in Phase 1, but enabled now so Phase 2's geofence +-- engine doesn't need a separate migration step. Geometry columns will +-- be added by the Directus-owned migrations for the geofences table. CREATE EXTENSION IF NOT EXISTS timescaledb; +CREATE EXTENSION IF NOT EXISTS postgis; -- Raw position history. High-volume append-only table; the hypertable -- partitioning column is `ts` (device-reported GPS time). diff --git a/test/pipeline.integration.test.ts b/test/pipeline.integration.test.ts index a384060..d665827 100644 --- a/test/pipeline.integration.test.ts +++ b/test/pipeline.integration.test.ts @@ -1,9 +1,11 @@ /** * Integration test: end-to-end pipeline round-trip via testcontainers. * - * Spins up Redis 7 and TimescaleDB (timescale/timescaledb:latest-pg16) containers, - * runs the Processor migration, starts the consumer pipeline, publishes synthetic - * Position records, and asserts the resulting rows in `positions`. + * Spins up Redis 7 and TimescaleDB-HA (timescale/timescaledb-ha:pg16.6-ts2.17.2-all, + * matching the deploy stack image) containers, runs the Processor migration, + * starts the consumer pipeline, publishes synthetic Position records, and asserts + * the resulting rows in `positions`. The `-all` image variant ships PostGIS too, + * so the migration's `CREATE EXTENSION IF NOT EXISTS postgis` succeeds. * * If Docker is unavailable (CI runner without Docker, local dev without Docker * Desktop), the suite skips — it does not fail the build. Docker availability is @@ -139,9 +141,9 @@ beforeAll(async () => { return; } - // --- Step 2: start TimescaleDB container ------------------------------------ + // --- Step 2: start TimescaleDB-HA container (same image as deploy stack) --- try { - pgContainer = await new GenericContainer('timescale/timescaledb:latest-pg16') + pgContainer = await new GenericContainer('timescale/timescaledb-ha:pg16.6-ts2.17.2-all') .withExposedPorts(5432) .withEnvironment({ POSTGRES_USER: 'postgres', @@ -152,7 +154,7 @@ beforeAll(async () => { .start(); } catch (err) { console.warn( - `[pipeline.integration.test] Failed to start TimescaleDB container: ${String(err)} — skipping`, + `[pipeline.integration.test] Failed to start TimescaleDB-HA container: ${String(err)} — skipping`, ); dockerAvailable = false; await redisContainer?.stop().catch(() => {});