release / govulncheck (push) Successful in 17s
release / web (push) Failing after 17s
release / go (push) Successful in 1m11s
release / integration (push) Successful in 4m50s
release / android (push) Successful in 4m54s
release / Build signed APK (releases and dev) (push) Successful in 5m9s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Skipped
release / Verify release artifacts (tag releases only) (push) Skipped
Ported from Fabled Librarian's System 104. A new lifecycle poller, every ten minutes: - a download the client fails is given up at once; - one nobody shares, or still fetching its file list, past the stall setting (6 h) is asked for again three times, then given up; - giving up removes the download with its files, holds the release back for a week (release_blocks.expires_at), ends the grab and searches the album again, with no limit per album; - a running download the client stops listing for half an hour ends and is searched again, not held back; an empty list is not taken as gone; - an imported download seeds to ratio 2.0 or 14 days, then is removed; - a download the client would not remove is asked again every pass. Every condition and act is one open row per (client, download, condition) in download_interventions. Activity shows what is wrong with a download and how often it was retried, why one ended, its seeding, and a banner for a client that does not answer. A running download can be given up by hand (set aside for good). The seed ratio, seed days and stall hours are on the search settings card. The download client lookup moves to acquire.DownloadClientFor, shared by the importer and the lifecycle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
91 lines
5.3 KiB
SQL
91 lines
5.3 KiB
SQL
-- Download lifecycle (M502 #5523), ported from Fabled Librarian's System 104:
|
|
-- a download that stalls or fails is given up and its album searched again;
|
|
-- an imported download seeds, then is removed.
|
|
--
|
|
-- download_interventions what was seen wrong with a download or a client,
|
|
-- what Minstrel did about it, and whether it
|
|
-- cleared. One open row per (client, download,
|
|
-- condition), updated in place.
|
|
-- grabs (columns) a grab also ends by being given up (stalled,
|
|
-- failed), set aside by a person, or leaving the
|
|
-- client; an imported one records its seeding.
|
|
-- release_blocks a release given up on is held back for a while,
|
|
-- not for ever: expires_at.
|
|
-- acquisition_settings how long to seed, and how long a download may sit
|
|
-- with nobody sharing it.
|
|
CREATE TABLE download_interventions (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
-- The acquisition_services code of the download client.
|
|
client text NOT NULL,
|
|
-- The torrent, or '' for a condition of the client itself.
|
|
info_hash text NOT NULL DEFAULT '',
|
|
grab_id uuid REFERENCES grabs (id) ON DELETE SET NULL,
|
|
name text NOT NULL DEFAULT '',
|
|
-- no_peers nobody is sharing an unfinished download.
|
|
-- no_metadata still fetching the torrent's file list.
|
|
-- client_error the client gave up on it, in its own words.
|
|
-- client_unreachable the client does not answer, or its engine is down.
|
|
-- gone the client no longer lists a running download.
|
|
-- not_removed given up on, and the client would not remove it.
|
|
trigger text NOT NULL CONSTRAINT download_interventions_trigger_check CHECK (trigger IN (
|
|
'no_peers', 'no_metadata', 'client_error', 'client_unreachable', 'gone', 'not_removed')),
|
|
-- escalated seen and shown; nothing done yet.
|
|
-- retried asked the trackers again and re-read the files.
|
|
-- given_up the download was removed and its album searched again.
|
|
-- removed a download left behind was removed.
|
|
action text NOT NULL DEFAULT 'escalated'
|
|
CONSTRAINT download_interventions_action_check CHECK (action IN ('escalated', 'retried', 'given_up', 'removed')),
|
|
outcome text NOT NULL DEFAULT 'open'
|
|
CONSTRAINT download_interventions_outcome_check CHECK (outcome IN ('open', 'resolved')),
|
|
detail text NOT NULL DEFAULT '',
|
|
-- How many passes have seen it, and how many times Minstrel acted on it.
|
|
-- The second is the retry ladder's rung, kept here so a restart does not
|
|
-- hand a stuck download fresh retries.
|
|
observations integer NOT NULL DEFAULT 1,
|
|
remediations integer NOT NULL DEFAULT 0,
|
|
first_seen timestamptz NOT NULL DEFAULT now(),
|
|
last_seen timestamptz NOT NULL DEFAULT now(),
|
|
settled_at timestamptz,
|
|
CONSTRAINT download_interventions_settled_together CHECK ((outcome = 'open') = (settled_at IS NULL))
|
|
);
|
|
|
|
-- One open row per condition: a pass that sees it again lands on the same row.
|
|
CREATE UNIQUE INDEX download_interventions_one_open
|
|
ON download_interventions (client, info_hash, trigger) WHERE outcome = 'open';
|
|
CREATE INDEX download_interventions_grab_idx ON download_interventions (grab_id) WHERE grab_id IS NOT NULL;
|
|
|
|
ALTER TABLE grabs DROP CONSTRAINT grabs_end_reason_check;
|
|
ALTER TABLE grabs ADD CONSTRAINT grabs_end_reason_check
|
|
CHECK (end_reason IN ('', 'superseded', 'imported', 'refused', 'held', 'stalled', 'failed', 'abandoned', 'gone'));
|
|
|
|
-- An imported download goes on sharing (the files were copied) until its
|
|
-- ratio reaches the setting or its time is up; seed_released_at is when it
|
|
-- was removed, or found gone.
|
|
ALTER TABLE grabs
|
|
ADD COLUMN seeding boolean NOT NULL DEFAULT false,
|
|
ADD COLUMN ratio real NOT NULL DEFAULT 0,
|
|
ADD COLUMN seed_released_at timestamptz;
|
|
|
|
CREATE INDEX grabs_seeding_idx ON grabs (imported_at) WHERE seeding AND seed_released_at IS NULL;
|
|
|
|
-- stalled: given up on because it would not finish; held back until
|
|
-- expires_at. NULL is for good.
|
|
ALTER TABLE release_blocks DROP CONSTRAINT release_blocks_reason_check;
|
|
ALTER TABLE release_blocks ADD CONSTRAINT release_blocks_reason_check
|
|
CHECK (reason IN ('operator', 'files', 'import', 'stalled'));
|
|
ALTER TABLE release_blocks ADD COLUMN expires_at timestamptz;
|
|
|
|
-- FL's rulings: seed to ratio 2.0 or for 14 days at most; a download nobody
|
|
-- has shared for 6 hours is retried, then given up.
|
|
-- seed_ratio 0 the download is removed once imported.
|
|
-- seed_days 0 no time limit: only the ratio ends it.
|
|
-- stall_hours 0 never give up on a download for want of peers (a failed
|
|
-- one is still given up).
|
|
ALTER TABLE acquisition_settings
|
|
ADD COLUMN seed_ratio real NOT NULL DEFAULT 2.0
|
|
CONSTRAINT acquisition_settings_seed_ratio_check CHECK (seed_ratio BETWEEN 0 AND 100),
|
|
ADD COLUMN seed_days integer NOT NULL DEFAULT 14
|
|
CONSTRAINT acquisition_settings_seed_days_check CHECK (seed_days BETWEEN 0 AND 365),
|
|
ADD COLUMN stall_hours integer NOT NULL DEFAULT 6
|
|
CONSTRAINT acquisition_settings_stall_hours_check CHECK (stall_hours BETWEEN 0 AND 720);
|