Files
linearvoid/.github/instructions/DONE.md
T

2.7 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.go split into 8 packages (config, auth, db, handlers, ws, media, ratelimit, metrics); db.RedisClient + db.PubSub interfaces 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 -cover with a 50% coverage threshold; SQLite switched to pure-Go github.com/glebarez/sqlite (CGO-free, works on Windows).
  • Frontend coverage enforcement: vitest v8 provider, 40% statements/lines + 30% branches/functions thresholds, test:coverage script + 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 convention git.allucanget.biz/zwitschi/linearvoid/<service>:<tag>, secrets renamed GITEA_* → 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.tv remains infrastructure-only (Cloudflare R2 config, not code).

Bug fixes not in CHANGELOG

  • 2026-08-13 viewer crash: index.html was missing the #messages container, so addMessage threw Cannot read properties of null (reading 'appendChild') on WebSocket open/message. Restored the chat panel structure and made addMessage defensive.
  • 2026-08-15 chat reconnect loop: after a registered user logged in, the chat panel repeatedly filled with old messages. connectWebSocket left the replaced socket's onclose handler 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's onclose before closing and guarding the handler against stale sockets. Regression test added; npm --prefix frontend test → 58 tests passing.