Files
music_library/backlog/completed/ml-11 - Telemetry.Storage-GenServer-funnels-synchronous-SQLite-writes.md
T
2026-05-04 21:22:27 +01:00

58 lines
2.5 KiB
Markdown

---
id: ML-11
title: Telemetry.Storage GenServer funnels synchronous SQLite writes
status: Done
assignee: []
created_date: "2026-04-20 08:49"
updated_date: "2026-04-24 09:29"
labels: []
dependencies: []
references:
- "https://github.com/cloud8421/music_library/issues/172"
priority: medium
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
_GitHub: created 2026-04-16 · updated 2026-04-16_
## Summary
`MusicLibraryWeb.Telemetry.Storage` is a single named GenServer that receives a cast for every telemetry event and performs two synchronous SQLite writes per event. A page with 10 DB queries plus a render can push 30+ messages into this one mailbox, all queued behind serial disk I/O.
## Evidence
- `lib/music_library_web/telemetry/storage.ex:51``GenServer.cast(__MODULE__, {:store, ...})`
- `lib/music_library_web/telemetry/storage.ex:56-69``handle_cast/2` runs `insert_and_prune/4` synchronously
- `lib/music_library_web/telemetry/storage.ex:89-107` — two SQLite queries per event: `INSERT` + `DELETE`-preserving-last-N subquery
- `TelemetryRepo` pool is 2 per `docs/production-infrastructure.md`, but the GenServer writes serially so pool size is irrelevant.
- `lib/music_library_web/telemetry/storage.ex:108-109, 125-126` — bare `catch _, _ -> :ok` swallows every error class including EXIT signals.
## Relation to #105
Issue #105 was closed as NOT_PLANNED with the rationale that bare catches are "reasonable for telemetry resilience". New framing: the catches mask a more fundamental design: the mailbox + synchronous-write pattern itself.
## Fix (options)
1. **Buffer-and-flush**: accumulate datapoints in-memory, flush batch every N seconds in a single transaction.
2. **Task.Supervisor per cast**: drain mailbox immediately, do I/O in a supervised task.
3. **ETS ring buffer + periodic flusher**: read path hits ETS; single-writer flusher persists to SQLite at a low cadence.
Whichever option is chosen, replace the bare `catch _, _` with either a targeted `rescue` or `Logger.debug` so failures become observable.
## Acceptance Criteria
<!-- AC:BEGIN -->
- Telemetry write path does not block on the GenServer mailbox
- Error path surfaces at least once per distinct failure (not silently swallowed)
- Existing dashboard queries continue to work
<!-- SECTION:DESCRIPTION:END -->
- [x] #1 Telemetry write path does not block on the GenServer mailbox
- [x] #2 Error path surfaces at least once per distinct failure (not silently swallowed)
- [x] #3 Existing dashboard queries continue to work
<!-- AC:END -->