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(() => {});