Add video as a media kind in photos: streaming upload with per-kind limits, ffprobe metadata, poster frame reusing the image variant pipeline, and a playback object (remux when web-compatible, else h264/yuv420p/aac transcode). Video jobs run on a separate pool with a long lease. Frontend gains a video viewer, grid badge/duration and video upload.
74 lines
1.7 KiB
Go
74 lines
1.7 KiB
Go
package db
|
|
|
|
import (
|
|
"database/sql"
|
|
"io/fs"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
assets "galo"
|
|
)
|
|
|
|
func TestMigrateSQLite(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "meta.db")
|
|
migFS, err := fs.Sub(assets.Migrations, "migrations/sqlite")
|
|
if err != nil {
|
|
t.Fatalf("migrations fs: %v", err)
|
|
}
|
|
if err := MigrateSQLite(path, migFS); err != nil {
|
|
t.Fatalf("migrate: %v", err)
|
|
}
|
|
if err := MigrateSQLite(path, migFS); err != nil {
|
|
t.Fatalf("migrate again: %v", err)
|
|
}
|
|
|
|
db, err := OpenSQLite(path)
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
var n int
|
|
if err := db.QueryRow(`SELECT count(*) FROM sqlite_master WHERE type='table' AND name='objects'`).Scan(&n); err != nil {
|
|
t.Fatalf("query: %v", err)
|
|
}
|
|
if n != 1 {
|
|
t.Fatalf("objects table missing after migration")
|
|
}
|
|
|
|
assertColumn(t, db, "photos", "kind")
|
|
assertColumn(t, db, "photos", "duration_ms")
|
|
assertColumn(t, db, "variant_jobs", "kind")
|
|
|
|
var ddl string
|
|
if err := db.QueryRow(`SELECT sql FROM sqlite_master WHERE type='table' AND name='photo_objects'`).Scan(&ddl); err != nil {
|
|
t.Fatalf("photo_objects ddl: %v", err)
|
|
}
|
|
if !strings.Contains(ddl, "playback") {
|
|
t.Fatalf("photo_objects role constraint missing playback: %s", ddl)
|
|
}
|
|
}
|
|
|
|
func assertColumn(t *testing.T, db *sql.DB, table, column string) {
|
|
t.Helper()
|
|
rows, err := db.Query(`PRAGMA table_info(` + table + `)`)
|
|
if err != nil {
|
|
t.Fatalf("table_info %s: %v", table, err)
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var cid int
|
|
var name, typ string
|
|
var notNull, pk int
|
|
var dflt any
|
|
if err := rows.Scan(&cid, &name, &typ, ¬Null, &dflt, &pk); err != nil {
|
|
t.Fatalf("scan table_info %s: %v", table, err)
|
|
}
|
|
if name == column {
|
|
return
|
|
}
|
|
}
|
|
t.Fatalf("column %s.%s missing", table, column)
|
|
}
|