9d324ab2d0424bb7eb59a1946b58699e5afc0a1c
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9d324ab2d0 |
feat: Minstrel backs itself up nightly to a folder or an S3 bucket, off until an admin switches it on (#6773)
release / integration (push) Failing after 3m29s
release / web (push) Failing after 15s
release / govulncheck (push) Successful in 16s
release / go (push) Failing after 41s
release / android (push) Successful in 4m7s
release / Attach APK to the Release (tag releases only) (push) Canceled after 0s
release / Build + push container image (push) Canceled after 0s
release / Verify release artifacts (tag releases only) (push) Canceled after 0s
release / Build signed APK (push) Canceled after 5m34s
Admin › Backups shows a verdict first (off, not set up, waiting, backed up, overdue, failing since when), Back up now, Test destination and the latest runs, with the settings beside them. - backup.Service: one run at a time, bounded at 30 minutes; the schedule ticks every 5 minutes, catches up a slot missed while the server was down, and retries a failure after an hour and then after as long as it has been failing. Runs are recorded in backup_runs, pruned after 90 days; a run cut off by a shutdown is marked failed at the next start. - A folder destination writes database/minstrel-<UTC stamp>.tar and refuses a folder that isn't there. An S3 destination stages the file, hashes it, and uploads it under database/ through a throttled reader (4 MiB/s by default, 0 for no limit). - Test destination checks the form as typed and only lists. - The bucket secret is sealed like every stored credential; backup_settings and backup_runs are left out of the backup itself. - The panel polls only while a run is going, capped at the run limit plus five minutes. The music switch named in the task is left to #6774, so no control ships that does nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
a67897a6cd |
feat: Minstrel can read its irreplaceable data out as JSON Lines and load it back into an empty instance (#6770)
release / web (push) Successful in 1m17s
release / android (push) Successful in 4m41s
release / Build signed APK (push) Successful in 4m52s
release / govulncheck (push) Successful in 15s
release / go (push) Successful in 1m29s
release / integration (push) Successful in 5m3s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 14s
release / Verify release artifacts (tag releases only) (push) Skipped
internal/backup names every table a backup holds, in parent-first order, and every table it leaves out with the reason: what the server computes from the music files, provider caches it fetches again, sign-ins and one-time links, and logs of past runs. The library's identity rows travel because every like, play and playlist entry hangs off a track id, and the sync change feed travels because the apps' first sync reads it. Sealed credentials are left out of the file, and so are the markers that say tag and art enrichment are done, so a restored server asks for the credentials again and redoes that work rather than believing it has it. Snapshot reads one REPEATABLE READ, read-only transaction, each table in primary-key order, keys sorted. Restore refuses an instance with accounts or tracks and a backup from a newer schema, replaces seeded settings, inserts by column intersection in batches, skips generated columns, and carries serial sequences on past the restored ids. Guards: every schema table is backed up or excluded; every backed-up table comes after what it references and references nothing excluded; every omitted column exists; a restore gives back the backup byte for byte. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |