From 0aea20953ebad647b2deb7251e518ca55a1cfe13 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Wed, 10 Jun 2026 12:22:48 -0400 Subject: [PATCH] fix(weight): dedup identical same-day readings on ingest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bt-scale gateway burst-posts the same reading several times as it settles (e.g. six identical 272.20 rows for 2026-06-07 within 4 seconds), and InsertW appended every one — the source of the duplicate rows that DeleteW now has to mop up by date. InsertW now skips the insert when a row already exists for the same date and weight, while still allowing a genuinely different value on the same day (the log shows the latest recorded_at, so multiple distinct weigh-ins per day remain supported). NUMERIC comparison makes "272.2" and "272.20" equal. Verified against a live-data preview: posting the same (date, weight) three times yields one row; a different value the same day yields two; a re-posted formatting variant dedups. No schema change. Co-Authored-By: Claude Opus 4.8 --- internal/store/postgres.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/internal/store/postgres.go b/internal/store/postgres.go index 0a9fda5..be3dd99 100644 --- a/internal/store/postgres.go +++ b/internal/store/postgres.go @@ -300,8 +300,19 @@ func (s *PostgresStore) InsertW(w models.BodyWeight) error { if w.RecordedAt != "" { recordedAt = w.RecordedAt } + // Dedup identical same-day readings. The bt-scale gateway burst-posts the + // same value several times as the reading settles/re-sends, which would + // otherwise pile up duplicate rows (the reason DeleteW deletes by date). + // A genuinely different value on the same day still inserts, so multiple + // distinct weigh-ins per day remain supported (latest recorded_at wins for + // display). NUMERIC comparison ignores decimal-string formatting, so + // "272.2" and "272.20" are treated as equal. _, err := s.pool.Exec(context.Background(), - "INSERT INTO weight (date, recorded_at, weight) VALUES ($1::date, COALESCE($2::timestamptz, NOW()), $3)", + `INSERT INTO weight (date, recorded_at, weight) + SELECT $1::date, COALESCE($2::timestamptz, NOW()), $3::numeric + WHERE NOT EXISTS ( + SELECT 1 FROM weight WHERE date = $1::date AND weight = $3::numeric + )`, w.Date, recordedAt, w.Weight.String()) return err }