// Code generated by sqlc. DO NOT EDIT. // versions: // sqlc v1.31.1 // source: lifecycle.sql package dbq import ( "context" "github.com/jackc/pgx/v5/pgtype" ) const countRemediation = `-- name: CountRemediation :one UPDATE download_interventions SET remediations = remediations + 1, action = $1, last_seen = now(), outcome = CASE WHEN $1::text IN ('given_up', 'removed') THEN 'resolved' ELSE outcome END, settled_at = CASE WHEN $1::text IN ('given_up', 'removed') THEN now() ELSE settled_at END WHERE client = $2 AND info_hash = $3 AND trigger = $4 AND outcome = 'open' RETURNING remediations ` type CountRemediationParams struct { Action string Client string InfoHash string Trigger string } // Minstrel acted on an open condition. A retry climbs the ladder; giving up // or removing ends the condition, since what it was about is gone. Written // before the act, so a retry that happened is never uncounted. func (q *Queries) CountRemediation(ctx context.Context, arg CountRemediationParams) (int32, error) { row := q.db.QueryRow(ctx, countRemediation, arg.Action, arg.Client, arg.InfoHash, arg.Trigger, ) var remediations int32 err := row.Scan(&remediations) return remediations, err } const deleteExpiredBlocks = `-- name: DeleteExpiredBlocks :execrows DELETE FROM release_blocks WHERE expires_at IS NOT NULL AND expires_at <= now() ` // A release given up on is held back for a while; after that the search may // take it again. func (q *Queries) DeleteExpiredBlocks(ctx context.Context) (int64, error) { result, err := q.db.Exec(ctx, deleteExpiredBlocks) if err != nil { return 0, err } return result.RowsAffected(), nil } const giveUpGrab = `-- name: GiveUpGrab :one UPDATE grabs SET ended_at = now(), end_reason = $1, end_detail = $2, import_updated_at = now() WHERE id = $3 AND ended_at IS NULL AND import_state = ANY($4::text[]) RETURNING id, want_id, info_hash, name, key, indexer, source, client, save_path, quality, origin, forced, grabbed_by, grabbed_at, ended_at, end_reason, end_detail, progress, import_state, import_reason, import_detail, import_forced, import_attempts, import_updated_at, imported_at, imported_files, destination, seeding, ratio, seed_released_at ` type GiveUpGrabParams struct { EndReason string EndDetail string ID pgtype.UUID States []string } // Ends a running grab, given up on. Only from the states named: the update // is the lock against an import that claimed the download meanwhile. func (q *Queries) GiveUpGrab(ctx context.Context, arg GiveUpGrabParams) (Grab, error) { row := q.db.QueryRow(ctx, giveUpGrab, arg.EndReason, arg.EndDetail, arg.ID, arg.States, ) var i Grab err := row.Scan( &i.ID, &i.WantID, &i.InfoHash, &i.Name, &i.Key, &i.Indexer, &i.Source, &i.Client, &i.SavePath, &i.Quality, &i.Origin, &i.Forced, &i.GrabbedBy, &i.GrabbedAt, &i.EndedAt, &i.EndReason, &i.EndDetail, &i.Progress, &i.ImportState, &i.ImportReason, &i.ImportDetail, &i.ImportForced, &i.ImportAttempts, &i.ImportUpdatedAt, &i.ImportedAt, &i.ImportedFiles, &i.Destination, &i.Seeding, &i.Ratio, &i.SeedReleasedAt, ) return i, err } const listClientsDown = `-- name: ListClientsDown :many SELECT client, detail, first_seen FROM download_interventions WHERE trigger = 'client_unreachable' AND outcome = 'open' ORDER BY client ` type ListClientsDownRow struct { Client string Detail string FirstSeen pgtype.Timestamptz } // Download clients not answering now, for the Activity tab. func (q *Queries) ListClientsDown(ctx context.Context) ([]ListClientsDownRow, error) { rows, err := q.db.Query(ctx, listClientsDown) if err != nil { return nil, err } defer rows.Close() var items []ListClientsDownRow for rows.Next() { var i ListClientsDownRow if err := rows.Scan(&i.Client, &i.Detail, &i.FirstSeen); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listLeftovers = `-- name: ListLeftovers :many SELECT id, client, info_hash, grab_id, name, trigger, action, outcome, detail, observations, remediations, first_seen, last_seen, settled_at FROM download_interventions WHERE trigger = 'not_removed' AND outcome = 'open' AND info_hash <> '' ORDER BY first_seen ` // Downloads given up on that the client would not remove; each pass asks // again. func (q *Queries) ListLeftovers(ctx context.Context) ([]DownloadIntervention, error) { rows, err := q.db.Query(ctx, listLeftovers) if err != nil { return nil, err } defer rows.Close() var items []DownloadIntervention for rows.Next() { var i DownloadIntervention if err := rows.Scan( &i.ID, &i.Client, &i.InfoHash, &i.GrabID, &i.Name, &i.Trigger, &i.Action, &i.Outcome, &i.Detail, &i.Observations, &i.Remediations, &i.FirstSeen, &i.LastSeen, &i.SettledAt, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listSeedingGrabs = `-- name: ListSeedingGrabs :many SELECT id, client, info_hash, name, imported_at FROM grabs WHERE seeding AND seed_released_at IS NULL ORDER BY imported_at, id ` type ListSeedingGrabsRow struct { ID pgtype.UUID Client string InfoHash string Name string ImportedAt pgtype.Timestamptz } // Imported downloads still sharing, oldest import first. func (q *Queries) ListSeedingGrabs(ctx context.Context) ([]ListSeedingGrabsRow, error) { rows, err := q.db.Query(ctx, listSeedingGrabs) if err != nil { return nil, err } defer rows.Close() var items []ListSeedingGrabsRow for rows.Next() { var i ListSeedingGrabsRow if err := rows.Scan( &i.ID, &i.Client, &i.InfoHash, &i.Name, &i.ImportedAt, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const liveGrabOnHash = `-- name: LiveGrabOnHash :one SELECT EXISTS (SELECT 1 FROM grabs WHERE info_hash = $1 AND ended_at IS NULL)::bool ` func (q *Queries) LiveGrabOnHash(ctx context.Context, infoHash string) (bool, error) { row := q.db.QueryRow(ctx, liveGrabOnHash, infoHash) var column_1 bool err := row.Scan(&column_1) return column_1, err } const raiseIntervention = `-- name: RaiseIntervention :one INSERT INTO download_interventions (client, info_hash, grab_id, name, trigger, detail) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (client, info_hash, trigger) WHERE outcome = 'open' DO UPDATE SET observations = download_interventions.observations + 1, last_seen = now(), detail = EXCLUDED.detail, grab_id = COALESCE(EXCLUDED.grab_id, download_interventions.grab_id), name = CASE WHEN EXCLUDED.name <> '' THEN EXCLUDED.name ELSE download_interventions.name END RETURNING id, client, info_hash, grab_id, name, trigger, action, outcome, detail, observations, remediations, first_seen, last_seen, settled_at ` type RaiseInterventionParams struct { Client string InfoHash string GrabID pgtype.UUID Name string Trigger string Detail string } // The download lifecycle (M502 #5523): the intervention ledger, giving a // download up, and seeding after import. // A condition seen, or seen again: a second pass lands on the open row, so // a download stuck for a week is one row that says how long. The name only // improves, and the detail is the latest word. func (q *Queries) RaiseIntervention(ctx context.Context, arg RaiseInterventionParams) (DownloadIntervention, error) { row := q.db.QueryRow(ctx, raiseIntervention, arg.Client, arg.InfoHash, arg.GrabID, arg.Name, arg.Trigger, arg.Detail, ) var i DownloadIntervention err := row.Scan( &i.ID, &i.Client, &i.InfoHash, &i.GrabID, &i.Name, &i.Trigger, &i.Action, &i.Outcome, &i.Detail, &i.Observations, &i.Remediations, &i.FirstSeen, &i.LastSeen, &i.SettledAt, ) return i, err } const releaseSeed = `-- name: ReleaseSeed :exec UPDATE grabs SET seed_released_at = now() WHERE id = $1 AND seed_released_at IS NULL ` // The seeding download was removed, or found gone. func (q *Queries) ReleaseSeed(ctx context.Context, id pgtype.UUID) error { _, err := q.db.Exec(ctx, releaseSeed, id) return err } const setGrabRatio = `-- name: SetGrabRatio :exec UPDATE grabs SET ratio = $1 WHERE id = $2 ` type SetGrabRatioParams struct { Ratio float32 ID pgtype.UUID } func (q *Queries) SetGrabRatio(ctx context.Context, arg SetGrabRatioParams) error { _, err := q.db.Exec(ctx, setGrabRatio, arg.Ratio, arg.ID) return err } const settleEndedGrabs = `-- name: SettleEndedGrabs :execrows UPDATE download_interventions di SET outcome = 'resolved', settled_at = now(), last_seen = now() FROM grabs g WHERE g.id = di.grab_id AND g.ended_at IS NOT NULL AND di.outcome = 'open' AND di.trigger <> 'not_removed' ` // What was wrong with a download whose grab has ended (imported, refused, // given up) is over, except a download left in the client to remove. func (q *Queries) SettleEndedGrabs(ctx context.Context) (int64, error) { result, err := q.db.Exec(ctx, settleEndedGrabs) if err != nil { return 0, err } return result.RowsAffected(), nil } const settleIntervention = `-- name: SettleIntervention :execrows UPDATE download_interventions SET outcome = 'resolved', settled_at = now(), last_seen = now() WHERE client = $1 AND info_hash = $2 AND trigger = $3 AND outcome = 'open' ` type SettleInterventionParams struct { Client string InfoHash string Trigger string } // The condition cleared. func (q *Queries) SettleIntervention(ctx context.Context, arg SettleInterventionParams) (int64, error) { result, err := q.db.Exec(ctx, settleIntervention, arg.Client, arg.InfoHash, arg.Trigger) if err != nil { return 0, err } return result.RowsAffected(), nil } const settleInterventionsFor = `-- name: SettleInterventionsFor :execrows UPDATE download_interventions SET outcome = 'resolved', settled_at = now(), last_seen = now() WHERE client = $1 AND info_hash = $2 AND outcome = 'open' ` type SettleInterventionsForParams struct { Client string InfoHash string } // Everything open about one download is over: it is gone from the client. func (q *Queries) SettleInterventionsFor(ctx context.Context, arg SettleInterventionsForParams) (int64, error) { result, err := q.db.Exec(ctx, settleInterventionsFor, arg.Client, arg.InfoHash) if err != nil { return 0, err } return result.RowsAffected(), nil }