3.2 KiB
3.2 KiB
DONE
Completed tasks from TODO. Product, feature, and release history lives in CHANGELOG; this file keeps only engineering and ops notes not captured there.
Test infrastructure & refactors (2026-08-07)
- Chat service
main.gosplit into 8 packages (config, auth, db, handlers, ws, media, ratelimit, metrics);db.RedisClient+db.PubSubinterfaces added for mocking. - 78 tests total (Go + frontend), all passing. Coverage: auth 97.8%, config 100%, metrics 100%, ratelimit 90.3%, ws 79.6%, handlers 47.2%, media 36.8%, db 14.3%.
- Playout: 12 tests. Frontend: vitest + jsdom, 6 user + 5 admin smoke tests.
- CI:
go test -race -coverwith a 50% coverage threshold; SQLite switched to pure-Gogithub.com/glebarez/sqlite(CGO-free, works on Windows). - Frontend coverage enforcement: vitest v8 provider, 40% statements/lines + 30% branches/functions thresholds,
test:coveragescript + CI step.
Backups
scripts/backup-db.sh(daily pg_dump → R2, 14-day retention),scripts/backup-weekly.sh(weekly full dump + integrity check, 8-week retention),scripts/verify-backups.sh(download → temp Postgres → restore + row counts).
Gitea self-hosting migration
- Migrated repo + CI/CD from GitHub to Gitea Actions (
git.allucanget.biz/zwitschi/linearvoid): self-hosted runner, Container Registry conventiongit.allucanget.biz/zwitschi/linearvoid/<service>:<tag>, secrets renamedGITEA_*→CI_*.
Streaming pipeline gaps (2026-08-10)
- Continuous R2 sync via
fsnotify(watchAndPublishSegments, ~7s delay); run-ID + monotonic segment naming (r-{ISOTIME}/seg-{seq}.m4s); atomic manifest publication (upload.tmp→CopyObject); enriched/health(run_id, active_item, playlist_revision, last_segment_seq, last_r2_pub, consecutive_failures); player error recovery (5 retries, 2s→32s exponential backoff, reconnecting overlay). - CORS on
media.linearvoid.tvremains infrastructure-only (Cloudflare R2 config, not code).
Bug fixes not in CHANGELOG
- 2026-08-13 viewer crash:
index.htmlwas missing the#messagescontainer, soaddMessagethrewCannot read properties of null (reading 'appendChild')on WebSocket open/message. Restored the chat panel structure and madeaddMessagedefensive. - 2026-08-15 chat reconnect loop: after a registered user logged in, the chat panel repeatedly filled with old messages.
connectWebSocketleft the replaced socket'sonclosehandler attached, so each intentional reconnect scheduled another reconnect and every connection re-pulled the room's 50-message history on a 3s loop. Fixed by detaching the old socket'sonclosebefore closing and guarding the handler against stale sockets. Regression test added;npm --prefix frontend test→ 58 tests passing.
Chat improvements
- Manual smoke: viewer join/leave shows a 3s flash (not a chat row); reconnect <5s shows no duplicate; admin chat-log table has no system rows
Playout improvements
- Test in Firefox: live playback, rebuffer/recovery, chat sync; record quirks in
docs/STREAMING.md - Rebuild + run playout; confirm
playlist.m3u8lists ~12 segments at 2s each - Manual: verify viewer latency and cache-hit behavior after the change