release / govulncheck (push) Successful in 17s
release / web (push) Successful in 1m33s
release / go (push) Successful in 1m49s
release / integration (push) Successful in 5m42s
release / android (push) Successful in 5m59s
release / Build signed APK (releases and dev) (push) Successful in 6m9s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 16s
release / Verify release artifacts (tag releases only) (push) Skipped
Applies rule 32's migration exception: each header still says what the schema was, what changes and what it prevents, but task, milestone, decision and rule ids are replaced by the practice they stood for, the operator quotes by the decision, single-install counts are dropped, and pointers to a deleted package and an external design doc are gone. golang-migrate keeps no checksum, so editing applied migrations' comments is safe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
27 lines
1.2 KiB
SQL
27 lines
1.2 KiB
SQL
-- Outbound ListenBrainz scrobble worker.
|
|
-- Per-user LB config (plaintext token; users rotate via /settings if leaked).
|
|
-- scrobble_queue is a work list, not a log: successfully-sent rows are
|
|
-- DELETEd by the worker (the canonical record stays in
|
|
-- play_events.scrobbled_at). Only `pending` and `failed` states exist.
|
|
|
|
ALTER TABLE users
|
|
ADD COLUMN listenbrainz_token TEXT NULL,
|
|
ADD COLUMN listenbrainz_enabled BOOLEAN NOT NULL DEFAULT FALSE;
|
|
|
|
CREATE TABLE scrobble_queue (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
play_event_id uuid NOT NULL REFERENCES play_events(id) ON DELETE CASCADE,
|
|
status TEXT NOT NULL CHECK (status IN ('pending', 'failed')),
|
|
attempts INTEGER NOT NULL DEFAULT 0,
|
|
next_attempt_at timestamptz NOT NULL DEFAULT now(),
|
|
last_error TEXT NULL,
|
|
enqueued_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE (play_event_id)
|
|
);
|
|
|
|
-- Hot path for the worker's per-tick query.
|
|
CREATE INDEX scrobble_queue_pending_idx
|
|
ON scrobble_queue (next_attempt_at)
|
|
WHERE status = 'pending';
|