feat: implement resumable chunked media upload with progress indicators in admin UI
This commit is contained in:
1 parent
930cdfdff9
commit
2c06265d11
6 files changed
+926
-14
No files matched your search
+193
-2
@@ -315,11 +315,96 @@ All source assets must be pre-normalized (H.264/AVC, AAC-LC, constant 30 fps, 2s
|
||||
|
||||
### Monitoring & Resilience
|
||||
|
||||
Alert on no new segment (>30–60s), low cache hits, high R2 ops, WebSocket errors. Maintain emergency slate, auto-restart, weekly backups, incident runbook.
|
||||
Linear Void uses a two-layer monitoring model:
|
||||
|
||||
1. **Application layer (chat + platform health)** via Prometheus metrics and a lightweight Grafana dashboard.
|
||||
2. **Infrastructure/runtime layer (Prometheus self-observability, TSDB, query engine, Go runtime)** via a detailed Grafana dashboard.
|
||||
|
||||
#### Prometheus Baseline
|
||||
|
||||
- Config file: `monitoring/prometheus/prometheus.yml`
|
||||
- Default scrape interval: `15s`
|
||||
- Current scrape jobs: `chat` -> `chat:3000`, `prometheus` -> `prometheus:9090`.
|
||||
|
||||
Recommended next-step scrape targets (if/when exporters are introduced):
|
||||
|
||||
- `nginx` (via nginx-exporter)
|
||||
- `redis` (via redis-exporter)
|
||||
- `postgres` (via postgres-exporter)
|
||||
- `node` (via node-exporter)
|
||||
|
||||
#### Grafana Dashboards
|
||||
|
||||
- `monitoring/grafana/dashboard.json` (Linear Void app metrics: connected clients, messages, moderation actions, Redis reachability, admin sessions, scrape health).
|
||||
- `monitoring/grafana/dashboards/dashboard.json` (Prometheus operational visibility: status, uptime, CPU/memory, TSDB ingestion/churn/errors, HTTP latencies, query load, GC/scheduler).
|
||||
|
||||
Use the app dashboard for service-level behavior and the Prometheus overview dashboard for platform diagnostics and capacity planning.
|
||||
|
||||
#### Alerting Rules (Prometheus Rule Groups)
|
||||
|
||||
Define alert rules as grouped policies (for example in `monitoring/prometheus/alerts.yml`) and include them from `prometheus.yml`.
|
||||
|
||||
Minimum recommended alert set:
|
||||
|
||||
- **Availability**
|
||||
`up{job="chat"} == 0` for `2m`; `up{job="prometheus"} == 0` for `2m`.
|
||||
- **Chat service health**
|
||||
`linearvoid_chat_redis_up == 0` for `2m`; sudden disconnect spike / connected clients collapse.
|
||||
- **Playout continuity**
|
||||
No HLS segment progression for `30-60s` (from playout-specific metric when available).
|
||||
- **Prometheus capacity and ingestion health**
|
||||
Sustained growth in `prometheus_tsdb_wal_writes_failed_total` or `prometheus_tsdb_compactions_failed_total`, abnormal jump in `prometheus_tsdb_out_of_order_samples_total`, and high `prometheus_engine_queries` near concurrent limit.
|
||||
- **Latency and user-impact**
|
||||
Elevated p99 handler latency from `prometheus_http_request_duration_seconds_bucket` and elevated p99 query execution latency from `prometheus_engine_query_duration_histogram_seconds_bucket`.
|
||||
|
||||
Route warning/critical severities to the team channel and keep runbook links attached to each alert definition.
|
||||
|
||||
Operational resilience baseline:
|
||||
|
||||
- Emergency slate fallback for playout failure.
|
||||
- Auto-restart policies for playout/chat/nginx containers.
|
||||
- Weekly backup and restore drills for stateful data (`data/chat`, playlist metadata, Postgres).
|
||||
- Incident runbook with triage order: edge reachability -> origin health -> playout progression -> chat connectivity -> data-plane dependencies.
|
||||
|
||||
### Security & Moderation
|
||||
|
||||
HTTPS/WSS only, strict CORS, Cloudflare WAF, authenticated admin paths, rate limiting, immutable moderation log. Private DMs not E2EE by default.
|
||||
Security is split between edge controls (Cloudflare), reverse proxy controls (nginx), and application controls (chat/admin backend).
|
||||
|
||||
#### Transport and Edge Protection
|
||||
|
||||
- Public traffic uses HTTPS/WSS at the edge.
|
||||
- Cloudflare WAF and rate limiting are part of the baseline (see `infrastructure/cloudflare/cache-rules.md`).
|
||||
- Cloudflare Worker can enforce immutable cache headers for segment paths (`infrastructure/cloudflare/worker.js`).
|
||||
|
||||
#### Reverse Proxy Enforcement (nginx)
|
||||
|
||||
- Admin UI and admin API paths are protected by `auth_request` before reaching backend handlers (`/admin/`, `/api/admin/`).
|
||||
- Unauthorized admin UI requests are redirected to `/admin/login/`.
|
||||
- Unauthorized admin API requests return JSON `401` from a dedicated location handler.
|
||||
- WebSocket upgrade headers are explicitly forwarded for `/ws`.
|
||||
|
||||
#### Admin Authentication and Session Security
|
||||
|
||||
- Admin authentication is cookie-session based (`linearvoid_admin_session`).
|
||||
- Session cookie controls in backend include `HttpOnly`, `SameSite=Strict`, and `Secure` when request is HTTPS (derived from TLS or `X-Forwarded-Proto`).
|
||||
- Session expiration is enforced server-side.
|
||||
|
||||
#### Rate Limiting and Abuse Controls
|
||||
|
||||
- Chat message rate limiting uses Redis `INCR + EXPIRE` windowing.
|
||||
- Current baseline in chat handler: `>10` messages within `10s` triggers a user-facing throttle response.
|
||||
- If Redis is unavailable, presence/rate-limit features degrade gracefully (warning logged; core chat remains available).
|
||||
|
||||
#### CORS and Cross-Origin Behavior
|
||||
|
||||
- HLS endpoints exposed by nginx include explicit `Access-Control-Allow-Origin: *` for player compatibility.
|
||||
- Admin/authenticated routes are expected to run same-origin behind nginx auth gates.
|
||||
|
||||
#### Moderation and Privacy
|
||||
|
||||
- Moderation commands (`/mod`, `/mute`, `/ban`) are handled in backend chat flow and persisted through chat storage paths.
|
||||
- Private DMs are application-level private channels, not end-to-end encrypted in current architecture.
|
||||
- Moderation and audit retention policies should be formalized in runbook/ops docs as part of production hardening.
|
||||
|
||||
### Chat
|
||||
|
||||
@@ -354,6 +439,112 @@ These ADRs together form the canonical decision log.
|
||||
|
||||
See **Quality Goals** table in the Introduction section. Primary scenarios focus on cost (near-zero egress), availability (auto-restart + fallback), scalability (edge caching), and usability (synchronized player + responsive chat).
|
||||
|
||||
### Performance Benchmarks and Capacity Planning
|
||||
|
||||
#### Baseline SLO Targets (v1)
|
||||
|
||||
- Playback startup: target < 4s after first manifest request on warm cache.
|
||||
- Steady-state playback: no segment starvation during normal operation.
|
||||
- End-to-end HLS latency: expected 15-35s (standard HLS trade-off).
|
||||
- Chat delivery latency: p95 < 500ms inside same region under normal load.
|
||||
- Admin page responsiveness: p95 API response < 1s for common read operations.
|
||||
|
||||
#### Workload Assumptions
|
||||
|
||||
- Primary audience in US; origin in US-East.
|
||||
- Edge cache serves most segment traffic; origin handles manifest churn and cache misses.
|
||||
- Chat traffic scales with concurrent viewers but remains low-bandwidth compared to video.
|
||||
|
||||
#### Initial Capacity Model
|
||||
|
||||
- Video bitrate envelopes (from ADR-001):
|
||||
- 720p30: ~2.6-4.2 Mbps total with audio.
|
||||
- 1080p30: ~5.1-8.2 Mbps total with audio.
|
||||
- Storage planning for 48h rolling library:
|
||||
- 720p30: ~57-90 GB raw (allocate ~80-110 GB with headroom).
|
||||
- 1080p30: ~110-175 GB raw (allocate ~130-180 GB with headroom).
|
||||
- Cost behavior:
|
||||
- Viewer scale is mostly constrained by cache efficiency and request volume, not by direct origin egress.
|
||||
|
||||
#### Benchmark Plan
|
||||
|
||||
- Playback path:
|
||||
- Measure time-to-first-frame and rebuffer events from multiple US regions.
|
||||
- Track manifest freshness and segment availability at edge.
|
||||
- Chat path:
|
||||
- Load-test concurrent websocket connections and message fan-out.
|
||||
- Measure p50/p95 send-to-receive latency and Redis fallback behavior.
|
||||
- Admin/API path:
|
||||
- Benchmark playlist/system endpoints for p95 latency and error rate.
|
||||
- Platform path:
|
||||
- Observe TSDB ingestion, query p99, and GC pause behavior in Grafana.
|
||||
|
||||
#### Capacity Triggers and Actions
|
||||
|
||||
- Trigger: sustained viewer growth with rising cache-miss ratio.
|
||||
- Action: tighten cache policy, enable/verify Tiered Cache, review manifest TTL.
|
||||
- Trigger: chat p95 latency drift or websocket error growth.
|
||||
- Action: scale chat service, tune Redis, separate noisy moderation workloads.
|
||||
- Trigger: Prometheus WAL/compaction failures or query saturation.
|
||||
- Action: tune retention/cardinality, increase resources, split dashboards/queries.
|
||||
- Trigger: origin CPU/memory pressure on playout host.
|
||||
- Action: optimize FFmpeg profile, isolate services, add secondary origin.
|
||||
|
||||
### Disaster Recovery and Backup Procedures
|
||||
|
||||
#### Recovery Targets
|
||||
|
||||
- RPO target: <= 24h for chat/moderation/admin metadata.
|
||||
- RTO target: <= 60 minutes for restoring baseline streaming + chat operations.
|
||||
|
||||
#### Backup Scope
|
||||
|
||||
- Persistent service volumes:
|
||||
- Postgres data (`postgres-data` volume).
|
||||
- Redis append-only persistence (`redis-data` volume) where enabled.
|
||||
- Prometheus long-term TSDB (`prometheus-data` volume) if historical metrics retention is required.
|
||||
- Grafana state (`grafana-data` volume) if dashboards/users are managed in-instance.
|
||||
- Host-mounted state directories:
|
||||
- `data/chat`
|
||||
- `data/playlist`
|
||||
- `data/media` (authoritative source may be R2/object storage)
|
||||
- `data/hls` (optional; can be regenerated by playout)
|
||||
- Configuration and infra source of truth:
|
||||
- Compose files, nginx config, monitoring configs, and environment template.
|
||||
|
||||
#### Backup Cadence
|
||||
|
||||
- Daily logical Postgres backups (plus weekly full snapshot).
|
||||
- Daily sync of chat/playlist state directories.
|
||||
- Weekly integrity check by restoring backups into an isolated environment.
|
||||
- Retention policy baseline:
|
||||
- Daily backups: 14 days
|
||||
- Weekly backups: 8 weeks
|
||||
- Monthly backups: 6 months
|
||||
|
||||
#### Recovery Runbook (Minimum)
|
||||
|
||||
1. Restore infrastructure configuration (compose, nginx, env, monitoring config).
|
||||
2. Restore Postgres and Redis persisted state.
|
||||
3. Restore `data/playlist` and chat persistence directories.
|
||||
4. Rehydrate media from authoritative object storage if local media is missing.
|
||||
5. Start stack and validate in order:
|
||||
- `playout` health endpoint
|
||||
- `chat` health endpoint
|
||||
- nginx `/health`
|
||||
- HLS playlist availability
|
||||
- websocket chat connectivity
|
||||
6. Verify admin authentication and moderation audit visibility.
|
||||
7. Announce recovery and continue elevated monitoring for at least one playlist cycle.
|
||||
|
||||
#### Failure Modes and Strategy
|
||||
|
||||
- Single-host loss: redeploy stack on standby host, restore data backups, repoint DNS/edge origin.
|
||||
- Storage corruption: restore last known-good snapshot and replay latest logical backups.
|
||||
- Partial service failure: replace only impacted service and restore scoped data (for example Postgres only).
|
||||
|
||||
Document and rehearse this runbook quarterly; recovery that is not exercised is not reliable.
|
||||
|
||||
## Risks and Technical Debts
|
||||
|
||||
- Cloudflare ToS risk for heavy video on free tier (use R2 path; fallback to BunnyCDN if challenged).
|
||||
|
||||
Reference in new issue
Block a user