fix: BUG-20 clamp trips sequence after recompute + renumber migration
This commit is contained in:
@@ -24,6 +24,20 @@ When CLOSED, move the entire entry to Resolved — don't duplicate.
|
|||||||
fills the cards immediately on load (and every 15 s) via REST. Needs in-car
|
fills the cards immediately on load (and every 15 s) via REST. Needs in-car
|
||||||
verification.
|
verification.
|
||||||
|
|
||||||
|
### BUG-20 — Server trip IDs inflate far beyond the real trip count
|
||||||
|
- **Status**: `OPEN` 2026-08-14
|
||||||
|
- **Phase**: 29
|
||||||
|
- **Symptom**: the portal shows trip IDs in the tens of thousands (e.g. 25136, 27091) even
|
||||||
|
though there are only ~10 real trips (verified: `COUNT=10`, `MAX(id)=27091`).
|
||||||
|
- **Cause**: `trips.id` is `BIGSERIAL`, and `compute_trips_for_device()` upserts every trip on
|
||||||
|
every tracking batch via `INSERT … ON CONFLICT (device_id, start_time) DO UPDATE`. PostgreSQL
|
||||||
|
consumes a sequence value on every INSERT attempt — including the conflict/update path — so
|
||||||
|
the sequence advances by the trip count on every recompute (which runs after every upload
|
||||||
|
batch). Cosmetic only: nothing references `trips.id` as a foreign key (`deleted_trip_markers`
|
||||||
|
keys on `(device_id, start_time)`).
|
||||||
|
- **Fix**: clamp the sequence to `MAX(id)` after each recompute in `compute_trips_for_device()`,
|
||||||
|
plus a one-time migration that renumbers existing trips compactly and resets the sequence.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Resolved
|
## Resolved
|
||||||
|
|||||||
@@ -2279,6 +2279,10 @@ logged as `BUG-XX` entries in [BUGS.md](./BUGS.md) (BUG-16 onward) and fixed + v
|
|||||||
`SET TIME!`). SIM868 CR1220 installed + its RTC set via `AT+CCLK` (was 2004 default); hold
|
`SET TIME!`). SIM868 CR1220 installed + its RTC set via `AT+CCLK` (was 2004 default); hold
|
||||||
across power-off to confirm on next cycle. Optional follow-up: `AT+CCLK` boot-time clock
|
across power-off to confirm on next cycle. Optional follow-up: `AT+CCLK` boot-time clock
|
||||||
fallback in `app_gps.py`.
|
fallback in `app_gps.py`.
|
||||||
|
- **BUG-20 (server trip IDs inflate) — 🚧 IN PROGRESS**: `trips.id BIGSERIAL` burns sequence
|
||||||
|
values on every upsert (recompute runs after each upload batch), so IDs run far past the real
|
||||||
|
trip count (~10 trips, ids 27000+). Fix: clamp the sequence after each recompute + one-time
|
||||||
|
renumber migration.
|
||||||
|
|
||||||
Open items from the drive — fill in as reported:
|
Open items from the drive — fill in as reported:
|
||||||
- (none clock-related — BUG-17/BUG-18 closed 2026-08-14).
|
- (none clock-related — BUG-17/BUG-18 closed 2026-08-14).
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ services:
|
|||||||
- ./sql/migrate_phase25_5a.sql:/docker-entrypoint-initdb.d/migrate_phase25_5a.sql:ro
|
- ./sql/migrate_phase25_5a.sql:/docker-entrypoint-initdb.d/migrate_phase25_5a.sql:ro
|
||||||
- ./sql/migrate_phase25_5c.sql:/docker-entrypoint-initdb.d/migrate_phase25_5c.sql:ro
|
- ./sql/migrate_phase25_5c.sql:/docker-entrypoint-initdb.d/migrate_phase25_5c.sql:ro
|
||||||
- ./sql/migrate_phase26_deleted_trips.sql:/docker-entrypoint-initdb.d/migrate_phase26_deleted_trips.sql:ro
|
- ./sql/migrate_phase26_deleted_trips.sql:/docker-entrypoint-initdb.d/migrate_phase26_deleted_trips.sql:ro
|
||||||
|
- ./sql/migrate_phase29_trip_ids.sql:/docker-entrypoint-initdb.d/migrate_phase29_trip_ids.sql:ro
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-yarisobd}"]
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-yarisobd}"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
|
|||||||
@@ -509,6 +509,13 @@ def compute_trips_for_device(device_id):
|
|||||||
""",
|
""",
|
||||||
{"device_id": device_id, **t},
|
{"device_id": device_id, **t},
|
||||||
)
|
)
|
||||||
|
# BIGSERIAL consumes a sequence value on every INSERT attempt, even when
|
||||||
|
# the ON CONFLICT (DO UPDATE) path is taken. Clamp the sequence back to the
|
||||||
|
# real max id so trip IDs don't inflate by trip_count on every recompute.
|
||||||
|
cur.execute(
|
||||||
|
"SELECT setval(pg_get_serial_sequence('trips','id'), "
|
||||||
|
"(SELECT COALESCE(MAX(id), 0) FROM trips))"
|
||||||
|
)
|
||||||
return len(trips)
|
return len(trips)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
-- Phase 29 (BUG-20): compact trip IDs and stop BIGSERIAL inflation.
|
||||||
|
-- trips.id has no foreign-key references (deleted_trip_markers keys on
|
||||||
|
-- (device_id, start_time)), so renumbering is purely cosmetic.
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- Shift all ids up first so the compact ids (1..N) can't collide with any
|
||||||
|
-- id that still exists during the renumber.
|
||||||
|
UPDATE trips SET id = id + 1000000;
|
||||||
|
|
||||||
|
-- Renumber compactly in start_time order.
|
||||||
|
WITH renumbered AS (
|
||||||
|
SELECT id, row_number() OVER (ORDER BY start_time, id) AS new_id
|
||||||
|
FROM trips
|
||||||
|
)
|
||||||
|
UPDATE trips t
|
||||||
|
SET id = r.new_id
|
||||||
|
FROM renumbered r
|
||||||
|
WHERE t.id = r.id;
|
||||||
|
|
||||||
|
-- Reset the sequence to the real max id so the next insert gets MAX(id) + 1.
|
||||||
|
SELECT setval(
|
||||||
|
pg_get_serial_sequence('trips', 'id'),
|
||||||
|
(SELECT COALESCE(MAX(id), 0) FROM trips)
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
Reference in New Issue
Block a user