veza/veza-backend-api/migrations/985_tracks_storage_backend.sql

44 lines
2 KiB
MySQL
Raw Normal View History

feat(storage): add track storage_backend column + config prep (v1.0.8 P0) Phase 0 of the MinIO upload migration (FUNCTIONAL_AUDIT §4 item 2). Schema + config only — Phase 1 will wire TrackService.UploadTrack() to actually route writes to S3 when the flag is flipped. Schema (migration 985): - tracks.storage_backend VARCHAR(16) NOT NULL DEFAULT 'local' CHECK in ('local', 's3') - tracks.storage_key VARCHAR(512) NULL (S3 object key when backend=s3) - Partial index on storage_backend = 's3' (migration progress queries) - Rollback drops both columns + index; safe only while all rows are still 'local' (guard query in the rollback comment) Go model (internal/models/track.go): - StorageBackend string (default 'local', not null) - StorageKey *string (nullable) - Both tagged json:"-" — internal plumbing, never exposed publicly Config (internal/config/config.go): - New field Config.TrackStorageBackend - Read from TRACK_STORAGE_BACKEND env var (default 'local') - Production validation rule #11 (ValidateForEnvironment): - Must be 'local' or 's3' (reject typos like 'S3' or 'minio') - If 's3', requires AWS_S3_ENABLED=true (fail fast, do not boot with TrackStorageBackend=s3 while S3StorageService is nil) - Dev/staging warns and falls back to 'local' instead of fail — keeps iteration fast while still flagging misconfig. Docs: - docs/ENV_VARIABLES.md §13 restructured as "HLS + track storage backend" with a migration playbook (local → s3 → migrate-storage CLI) - docs/ENV_VARIABLES.md §28 validation rules: +2 entries for new rules - docs/ENV_VARIABLES.md §29 drift findings: TRACK_STORAGE_BACKEND added to "missing from template" list before it was fixed - veza-backend-api/.env.template: TRACK_STORAGE_BACKEND=local with comment pointing at Phase 1/2/3 plans No behavior change yet — TrackService.UploadTrack() still hardcodes the local path via copyFileAsync(). Phase 1 wires it. Refs: - AUDIT_REPORT.md §9 item (deferrals v1.0.8) - FUNCTIONAL_AUDIT.md §4 item 2 "Stockage local disque only" - /home/senke/.claude/plans/audit-fonctionnel-wild-hickey.md Item 3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:54:28 +00:00
-- 985_tracks_storage_backend.sql
-- v1.0.8 Phase 0 (MinIO upload migration) — prepare tracks schema for
-- multi-backend storage (local FS vs S3/MinIO). Schema-only change; Phase 1
-- will wire TrackService.UploadTrack() to actually route writes via the
-- storage_backend column.
--
-- Context: FUNCTIONAL_AUDIT §4 item 2 flagged "stockage local disque only"
-- as a multi-pod prod blocker. The S3 client exists but is never called on
-- the upload path. This migration makes it possible to gradually migrate
-- uploads without a big-bang switchover.
--
-- Columns added:
-- storage_backend — VARCHAR(16) NOT NULL DEFAULT 'local'
-- Which storage impl wrote this track. 'local' = file_path points at
-- veza-backend-api/uploads/tracks/... . 's3' = storage_key holds the
-- S3 object key inside config.S3Bucket. Check constraint limits values.
--
-- storage_key — VARCHAR(512) NULL
-- When storage_backend='s3', this is the S3 object key (e.g.
-- "tracks/<userID>/<uuid>.<ext>"). NULL when storage_backend='local'
-- (file_path carries the info in that case — kept for back-compat).
--
-- Index:
-- idx_tracks_storage_backend_s3 — partial index on s3-backed rows only.
-- Useful for the migration script (Phase 3) which sweeps local→s3 and
-- for monitoring queries (what % of tracks already migrated).
ALTER TABLE public.tracks
ADD COLUMN storage_backend VARCHAR(16) NOT NULL DEFAULT 'local'
CHECK (storage_backend IN ('local', 's3')),
ADD COLUMN storage_key VARCHAR(512);
-- Partial index: only indexes s3-backed rows (majority stay 'local' during
-- migration, so full index would be wasteful).
CREATE INDEX idx_tracks_storage_backend_s3
ON public.tracks(storage_backend)
WHERE storage_backend = 's3';
COMMENT ON COLUMN public.tracks.storage_backend IS
'Storage impl that owns the file: local (disk) or s3 (MinIO/S3). v1.0.8 multi-backend prep.';
COMMENT ON COLUMN public.tracks.storage_key IS
'S3 object key when storage_backend=s3. NULL when storage_backend=local (file_path carries the info).';