Files
linearvoid/.github/instructions/DONE.md
T
zwitschi c2f9f9ed62
CI / test (push) Successful in 1m52s
CI / docker (push) Successful in 55s
perf(playout): parallelize playlist validation with dedup and worker pool
2026-08-16 10:30:15 +02:00

3.8 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.

Playout startup performance (2026-08-16)

  • Parallelized playlist validation: dedup repeated paths, probe unique files concurrently (PLAYOUT_VALIDATE_WORKERS default runtime.NumCPU()), run the two ffprobe probes concurrently, and validate once in main() (removed the redundant -validate pre-step in start-playout.sh). See CHANGELOG.

Cloudflare Workers frontend URLs (2026-08-16)

  • Viewer main.ts uses VITE_PUBLIC_APP_URL for all API requests and VITE_PUBLIC_WS_URL for WebSocket connections so the Workers-served SPA reaches the app origin cross-origin. See CHANGELOG.

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.

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.m3u8 lists ~12 segments at 2s each
  • Manual: verify viewer latency and cache-hit behavior after the change