feat: enhance media management with CRUD operations and runtime tracking in admin UI
This commit is contained in:
1 parent
47740e3f4a
commit
7cfddfc7ef
6 files changed
+535
-103
No files matched your search
@@ -1,7 +1,7 @@
|
||||
# ADR-006: Data Storage Strategy (SQLite vs PostgreSQL)
|
||||
|
||||
**Status:** Proposed
|
||||
**Date:** 2026-08-02
|
||||
**Status:** Accepted
|
||||
**Date:** 2026-08-04
|
||||
**Author:** AI Assistant (following AGENTS.md, ADR-002, ADR-003, ADR-004, ADR-005)
|
||||
**Related ADRs:** [ADR-001](./ADR-001.md), [ADR-003](./ADR-003-tech-stack.md), [ADR-005](./ADR-005-admin-moderation-analytics.md), [ADR-007](./ADR-007-redis-usage.md)
|
||||
|
||||
@@ -12,89 +12,78 @@ The system needs persistent storage for:
|
||||
- Chat messages and history (public rooms and private DMs).
|
||||
- User accounts, roles, and ban lists.
|
||||
- Moderation audit log (immutable record of admin and moderator actions).
|
||||
- Playlist metadata and schedule overrides.
|
||||
- System configuration (including Redis settings adjustable via admin UI per ADR-005/ADR-007).
|
||||
- Playlist and media metadata used by admin flows.
|
||||
- System configuration visibility in admin APIs.
|
||||
|
||||
From ADR-003 we prefer operational simplicity. ADR-005 requires a robust audit trail. We must decide between **SQLite** (embedded, zero-config) and **PostgreSQL** (full-featured, scalable) and document how the admin interface can view and adjust storage-related configuration.
|
||||
The codebase now ships with a PostgreSQL service in Docker Compose (`db`) and chat is configured with a PostgreSQL `DATABASE_URL` by default. The backend still supports SQLite for optional local fallback, but the deployed and compose-default path is PostgreSQL.
|
||||
|
||||
## Decision Drivers
|
||||
|
||||
1. **Operational Simplicity** – Minimize infrastructure (no separate DB server for SQLite).
|
||||
2. **Performance & Concurrency** – Chat and moderation may have high write volume.
|
||||
3. **Backup and Recovery** – Easy point-in-time recovery and replication.
|
||||
4. **Admin Capabilities** – Admin UI must be able to view storage stats, run vacuum/analyze, and switch between SQLite and PostgreSQL (with migration path).
|
||||
5. **Auditability** – Moderation log must be immutable and queryable.
|
||||
6. **Cost** – Avoid managed database costs during early stages.
|
||||
1. **Implemented Reality** - Docker Compose already provisions PostgreSQL and chat depends on it.
|
||||
2. **Concurrency & Throughput** - Chat, moderation, and media metadata writes require stronger concurrent write behavior.
|
||||
3. **Operational Traceability** - Structured backups, service health checks, and persistent volume management are already in place for PostgreSQL.
|
||||
4. **Admin Growth** - Upcoming admin features (media CRUD, analytics, moderation tooling) benefit from relational querying and indexing.
|
||||
5. **Fallback Simplicity** - Keep SQLite support for lightweight local or recovery scenarios without blocking developer workflows.
|
||||
|
||||
## Decision
|
||||
|
||||
**Primary storage for v1: SQLite** (embedded in the chat and admin services).
|
||||
**Primary storage for current implementation: PostgreSQL (Docker Compose `db` service).**
|
||||
|
||||
**Migration Path**: Provide a clear upgrade path to PostgreSQL when concurrency or replication needs exceed SQLite capabilities (target v2 or when concurrent users > 500).
|
||||
**Secondary/Fallback mode:** SQLite remains supported via `DATABASE_URL=sqlite://...` for local-only scenarios.
|
||||
|
||||
**Admin Interface Capabilities** (extension of ADR-005):
|
||||
**Current Backend Behavior**:
|
||||
|
||||
- "System Configuration" tab showing current storage engine, database size, connection stats, and vacuum status.
|
||||
- Buttons to run `VACUUM`, `ANALYZE`, or trigger a backup.
|
||||
- Configuration form to switch connection string (SQLite file path vs PostgreSQL URL) and restart services gracefully.
|
||||
- Audit log of all configuration changes.
|
||||
- Chat backend (`backend/chat/src/main.go`) resolves `DATABASE_URL` at startup.
|
||||
- `postgres://` or `postgresql://` selects PostgreSQL driver.
|
||||
- `sqlite://` selects SQLite driver.
|
||||
- Empty `DATABASE_URL` falls back to local `chat.db` for developer convenience.
|
||||
- GORM AutoMigrate is used for chat/admin data models.
|
||||
|
||||
**Technical Details**:
|
||||
**Media Model Decision (Admin UI Feature Track)**:
|
||||
|
||||
- Use SQLite with WAL mode for better concurrency.
|
||||
- Use GORM or sqlx (Go) or Prisma (if Node.js fallback) for ORM/migrations.
|
||||
- Store large chat history in a separate table with retention policy (e.g., 30 days).
|
||||
- Moderation log as an append-only table with triggers for immutability.
|
||||
|
||||
**Folder Placement** (per ADR-002):
|
||||
|
||||
- Database models and migrations in `backend/shared/db/` or `backend/chat/internal/db/`.
|
||||
- Admin UI pages for storage management in `frontend/admin/system/`.
|
||||
- Media metadata is persisted in the same database as messages and moderation logs.
|
||||
- Physical media files remain on the shared filesystem (`/app/media`, mapped from `data/media`).
|
||||
- The database is the source of truth for media library metadata and future runtime analytics.
|
||||
|
||||
## Rationale
|
||||
|
||||
- SQLite aligns with ADR-003's emphasis on operational simplicity and low resource usage for the initial deployment on a single Hetzner VPS.
|
||||
- It eliminates the need for a separate database container in `docker-compose.yml` during early development.
|
||||
- The admin interface can provide visibility and basic maintenance operations, fulfilling the requirement from the previous TODO plan.
|
||||
- PostgreSQL can be introduced later with a migration script when scale demands it (replication, advanced querying, full-text search on chat).
|
||||
- The repository already operationalizes PostgreSQL in both `docker-compose.yml` and `docker-compose.prod.yml` with persistent storage.
|
||||
- Default environment documentation (`.env.example`, setup docs) already points to PostgreSQL.
|
||||
- This aligns architecture documentation with implemented behavior and avoids drift.
|
||||
- Keeping SQLite support preserves local flexibility while avoiding a hard breaking change.
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive**:
|
||||
|
||||
- Zero-config database for quick local development and small-scale production.
|
||||
- Simple backups (just copy the `.db` file).
|
||||
- Admin UI can directly manage and monitor storage without external tools.
|
||||
- Better write concurrency and query flexibility for chat + admin workloads.
|
||||
- Clear operational model for containerized deployments (health checks, named volume, service dependency).
|
||||
- Easier extension for admin analytics and media metadata features.
|
||||
|
||||
**Negative / Risks**:
|
||||
|
||||
- SQLite has limited concurrency compared to PostgreSQL (WAL mode helps but is not a full replacement).
|
||||
- Large chat history or analytics queries may become slow – plan retention policy and archiving.
|
||||
- Migration to PostgreSQL will require downtime or dual-write strategy (documented in this ADR).
|
||||
- Additional service to operate versus embedded-only SQLite.
|
||||
- Misconfigured `DATABASE_URL` can still route to SQLite fallback unintentionally if left empty outside compose.
|
||||
- Requires backup/restore procedures for PostgreSQL volume in production runbooks.
|
||||
|
||||
**Alternatives Considered**:
|
||||
## Alternatives Considered
|
||||
|
||||
- PostgreSQL from day one – rejected for added operational complexity (separate service, connection pooling, managed service cost).
|
||||
- Pure key-value store (e.g., BoltDB) – rejected because SQL is better for audit logs and complex moderation queries.
|
||||
- Managed database (Neon, Supabase) – rejected to maintain full self-hosted independence per ADR-001.
|
||||
- SQLite-first in production: rejected for current implementation because compose and deployment already run PostgreSQL.
|
||||
- PostgreSQL-only with no fallback: rejected to preserve local dev and troubleshooting flexibility.
|
||||
- Managed external PostgreSQL: deferred; self-hosted compose remains the preferred operational model.
|
||||
|
||||
## Implementation Plan
|
||||
## Implementation Status
|
||||
|
||||
1. Create this ADR-006 (done).
|
||||
2. Add SQLite support in `backend/shared/db/` with GORM migrations.
|
||||
3. Implement admin UI pages for storage monitoring and configuration (linked to ADR-005).
|
||||
4. Add configuration reload capability without full restart where possible.
|
||||
5. Write migration script from SQLite to PostgreSQL.
|
||||
6. Update `docker-compose.yml` to optionally include PostgreSQL.
|
||||
7. Add tests for data access patterns and admin configuration changes.
|
||||
|
||||
**Next ADR**: ADR-007 (Redis usage and admin configuration capabilities).
|
||||
1. ADR updated to match implemented state. Done.
|
||||
2. Compose includes PostgreSQL service and persistent volume. Done.
|
||||
3. Chat backend supports PostgreSQL and SQLite based on `DATABASE_URL`. Done.
|
||||
4. Media metadata persistence model documented here for Admin UI track. In progress (implementation ongoing).
|
||||
5. Admin storage observability and operations UI (vacuum/analyze/backup flows). Planned.
|
||||
|
||||
## References
|
||||
|
||||
- ADR-001: Chat persistence, moderation log, monitoring requirements.
|
||||
- ADR-003: Preference for operational simplicity and Go backend.
|
||||
- ADR-005: Admin interface for user management, moderation, and analytics – this ADR extends it with storage and Redis config capabilities.
|
||||
- arc42 documentation: Cross-cutting Concepts (data management, monitoring) and Risks & Technical Debts.
|
||||
|
||||
This ADR ensures all data storage decisions are documented before code is written, maintaining full traceability.
|
||||
- ADR-005: Admin interface for user management, moderation, and analytics.
|
||||
- ADR-007: Redis usage for presence, rate limiting, pub/sub.
|
||||
- `docker-compose.yml` and `docker-compose.prod.yml` database service definitions.
|
||||
Reference in new issue
Block a user