Files
minstrel/internal/db/queries/admin_status.sql
T
bvandeusenandClaude Opus 5.5 c1305a547d
release / govulncheck (push) Successful in 17s
release / web (push) Successful in 1m35s
release / go (push) Successful in 2m0s
release / integration (push) Successful in 5m40s
release / android (push) Successful in 6m15s
release / Build signed APK (releases and dev) (push) Successful in 6m30s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 25s
release / Verify release artifacts (tag releases only) (push) Skipped
feat: the admin Overview shows who is listening, downloads, the library and its disk, and the server's version, uptime and recent errors; a download waiting on you, a client not answering or a full disk count in its verdict (M504 #5627 #5628 #5629 #5630)
The version moves to internal/buildinfo, so /rest/ping reports the build
instead of "dev".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:51:41 -04:00

55 lines
2.6 KiB
SQL

-- The admin Overview's status sections (M504): who is listening, what is
-- downloading, what the library holds. Each is one cheap read.
-- name: ListListeningNow :many
-- Plays in progress: open play events still inside their track's length,
-- with a few minutes' grace for a pause. A client that never says a play
-- ended would otherwise read as listening until the 24-hour sweep closes it.
SELECT pe.started_at, pe.client_id, pe.device_class,
u.username,
t.id AS track_id, t.title AS track_title, t.duration_ms,
ar.name AS artist_name,
al.id AS album_id, al.title AS album_title
FROM play_events pe
JOIN users u ON u.id = pe.user_id
JOIN tracks t ON t.id = pe.track_id
JOIN albums al ON al.id = t.album_id
JOIN artists ar ON ar.id = t.artist_id
WHERE pe.ended_at IS NULL
AND pe.started_at > now() - INTERVAL '24 hours'
AND pe.started_at + make_interval(secs => t.duration_ms / 1000.0) + INTERVAL '5 minutes' > now()
ORDER BY pe.started_at DESC
LIMIT 20;
-- name: PlaysLastDay :one
-- The last day's listening, for the line under Listening now.
SELECT COUNT(*)::bigint AS plays,
COUNT(DISTINCT user_id)::bigint AS listeners,
MAX(started_at)::timestamptz AS last_at
FROM play_events
WHERE started_at > now() - INTERVAL '24 hours';
-- name: DownloadsStatus :one
-- Downloads at a glance: running, waiting on a person (and since when), and
-- the last day's imports and give-ups.
SELECT COUNT(*) FILTER (WHERE ended_at IS NULL AND import_state IN ('', 'downloading', 'waiting', 'importing'))::bigint AS running,
COUNT(*) FILTER (WHERE ended_at IS NULL AND import_state IN ('review', 'failed'))::bigint AS needs_you,
MIN(COALESCE(import_updated_at, grabbed_at)) FILTER (WHERE ended_at IS NULL AND import_state IN ('review', 'failed'))::timestamptz AS needs_you_since,
COUNT(*) FILTER (WHERE imported_at > now() - INTERVAL '24 hours')::bigint AS imported_day,
COUNT(*) FILTER (WHERE ended_at > now() - INTERVAL '24 hours'
AND end_reason IN ('stalled', 'failed', 'gone', 'abandoned'))::bigint AS given_up_day
FROM grabs
WHERE ended_at IS NULL
OR ended_at > now() - INTERVAL '24 hours'
OR imported_at > now() - INTERVAL '24 hours';
-- name: LibraryStatus :one
-- What the library holds on disk: tracks whose files are present, the
-- albums and artists they make, and their size.
SELECT COUNT(*)::bigint AS tracks,
COUNT(DISTINCT album_id)::bigint AS albums,
COUNT(DISTINCT artist_id)::bigint AS artists,
COALESCE(SUM(file_size), 0)::bigint AS bytes
FROM tracks
WHERE missing_since IS NULL;