feat(db/m7-recurring-scans): migration 0019 + sqlc queries
Adds the singleton scan_schedule table holding the operator's recurring-scan config. mode is the discriminator (off/interval/ daily/weekly); CHECK constraints enforce per-mode field validity (interval_hours required for interval; time_of_day for daily and weekly; weekly_day 1..7 for weekly). Seed row is mode='off'. Two new queries: GetScanSchedule (read singleton; used by scheduler boot + admin GET) and UpdateScanSchedule (admin PATCH; application normalizes per-mode fields to NULL when mode='off').
This commit is contained in:
@@ -393,6 +393,15 @@ type ScanRun struct {
|
|||||||
ArtistArtEnrich []byte
|
ArtistArtEnrich []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ScanSchedule struct {
|
||||||
|
ID bool
|
||||||
|
Mode string
|
||||||
|
IntervalHours *int32
|
||||||
|
TimeOfDay *string
|
||||||
|
WeeklyDay *int32
|
||||||
|
UpdatedAt pgtype.Timestamptz
|
||||||
|
}
|
||||||
|
|
||||||
type ScrobbleQueue struct {
|
type ScrobbleQueue struct {
|
||||||
ID pgtype.UUID
|
ID pgtype.UUID
|
||||||
UserID pgtype.UUID
|
UserID pgtype.UUID
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// sqlc v1.31.1
|
||||||
|
// source: scan_schedule.sql
|
||||||
|
|
||||||
|
package dbq
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
|
)
|
||||||
|
|
||||||
|
const getScanSchedule = `-- name: GetScanSchedule :one
|
||||||
|
SELECT mode, interval_hours, time_of_day, weekly_day, updated_at
|
||||||
|
FROM scan_schedule WHERE id = true
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetScanScheduleRow struct {
|
||||||
|
Mode string
|
||||||
|
IntervalHours *int32
|
||||||
|
TimeOfDay *string
|
||||||
|
WeeklyDay *int32
|
||||||
|
UpdatedAt pgtype.Timestamptz
|
||||||
|
}
|
||||||
|
|
||||||
|
// M7 recurring-scans: returns the singleton schedule row. Used by the
|
||||||
|
// scheduler goroutine on boot and config-refresh, and by the admin GET
|
||||||
|
// handler.
|
||||||
|
func (q *Queries) GetScanSchedule(ctx context.Context) (GetScanScheduleRow, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getScanSchedule)
|
||||||
|
var i GetScanScheduleRow
|
||||||
|
err := row.Scan(
|
||||||
|
&i.Mode,
|
||||||
|
&i.IntervalHours,
|
||||||
|
&i.TimeOfDay,
|
||||||
|
&i.WeeklyDay,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateScanSchedule = `-- name: UpdateScanSchedule :exec
|
||||||
|
UPDATE scan_schedule
|
||||||
|
SET mode = $1,
|
||||||
|
interval_hours = $2,
|
||||||
|
time_of_day = $3,
|
||||||
|
weekly_day = $4,
|
||||||
|
updated_at = now()
|
||||||
|
WHERE id = true
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpdateScanScheduleParams struct {
|
||||||
|
Mode string
|
||||||
|
IntervalHours *int32
|
||||||
|
TimeOfDay *string
|
||||||
|
WeeklyDay *int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Admin PATCH replaces the whole row; CHECK constraints enforce validity.
|
||||||
|
// The application normalizes mode='off' to NULL the per-mode fields
|
||||||
|
// before calling this.
|
||||||
|
func (q *Queries) UpdateScanSchedule(ctx context.Context, arg UpdateScanScheduleParams) error {
|
||||||
|
_, err := q.db.Exec(ctx, updateScanSchedule,
|
||||||
|
arg.Mode,
|
||||||
|
arg.IntervalHours,
|
||||||
|
arg.TimeOfDay,
|
||||||
|
arg.WeeklyDay,
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP TABLE IF EXISTS scan_schedule;
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
-- M7 recurring-scans: singleton table holding the operator's schedule
|
||||||
|
-- config. mode is the discriminator: 'off' / 'interval' / 'daily' / 'weekly'.
|
||||||
|
-- Per-mode fields are populated only when their mode is selected; others
|
||||||
|
-- stay NULL. weekly_day uses ISO 8601: 1=Monday … 7=Sunday.
|
||||||
|
CREATE TABLE scan_schedule (
|
||||||
|
id boolean PRIMARY KEY DEFAULT true,
|
||||||
|
mode text NOT NULL DEFAULT 'off',
|
||||||
|
interval_hours int,
|
||||||
|
time_of_day text,
|
||||||
|
weekly_day int,
|
||||||
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||||
|
CONSTRAINT scan_schedule_singleton CHECK (id = true),
|
||||||
|
CONSTRAINT scan_schedule_mode_check
|
||||||
|
CHECK (mode IN ('off', 'interval', 'daily', 'weekly')),
|
||||||
|
CONSTRAINT scan_schedule_interval_check
|
||||||
|
CHECK (mode != 'interval' OR (interval_hours IS NOT NULL AND interval_hours > 0)),
|
||||||
|
CONSTRAINT scan_schedule_daily_check
|
||||||
|
CHECK (mode != 'daily' OR time_of_day IS NOT NULL),
|
||||||
|
CONSTRAINT scan_schedule_weekly_check
|
||||||
|
CHECK (mode != 'weekly' OR (time_of_day IS NOT NULL AND weekly_day IS NOT NULL AND weekly_day BETWEEN 1 AND 7))
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO scan_schedule (id) VALUES (true);
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
-- name: GetScanSchedule :one
|
||||||
|
-- M7 recurring-scans: returns the singleton schedule row. Used by the
|
||||||
|
-- scheduler goroutine on boot and config-refresh, and by the admin GET
|
||||||
|
-- handler.
|
||||||
|
SELECT mode, interval_hours, time_of_day, weekly_day, updated_at
|
||||||
|
FROM scan_schedule WHERE id = true;
|
||||||
|
|
||||||
|
-- name: UpdateScanSchedule :exec
|
||||||
|
-- Admin PATCH replaces the whole row; CHECK constraints enforce validity.
|
||||||
|
-- The application normalizes mode='off' to NULL the per-mode fields
|
||||||
|
-- before calling this.
|
||||||
|
UPDATE scan_schedule
|
||||||
|
SET mode = $1,
|
||||||
|
interval_hours = $2,
|
||||||
|
time_of_day = $3,
|
||||||
|
weekly_day = $4,
|
||||||
|
updated_at = now()
|
||||||
|
WHERE id = true;
|
||||||
Reference in New Issue
Block a user