Returns a dinner with its recipe for the recipe detail screen and Kitchen reading mode: photo URLs at both cached sizes (400/1200) or null, ingredients and steps in recipe position order, the source page for a fetched recipe, grounding status and error, and why_picked, the reason of the suggestion that created the dinner (null when none). Unknown and archived dinners are 404. Read in one transaction. Adds the GetDinnerSuggestionReason query (sqlc regenerated). The dinners test env now serves photos from the grounder's own store and data directory so photo URLs can be fetched in tests. Maestro task 099e9952-7f98-4700-8369-241c589a1e9d. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
127 lines
4.3 KiB
SQL
127 lines
4.3 KiB
SQL
-- name: CreateSuggestionBatch :one
|
|
INSERT INTO suggestion_batches (id, trigger, status, created_at, updated_at)
|
|
VALUES (?, ?, 'pending', ?, ?)
|
|
RETURNING *;
|
|
|
|
-- name: GetActiveSuggestionBatch :one
|
|
-- The batch still pending or running, oldest first. Returns sql.ErrNoRows
|
|
-- when there is none.
|
|
SELECT * FROM suggestion_batches
|
|
WHERE status IN ('pending', 'running')
|
|
ORDER BY id
|
|
LIMIT 1;
|
|
|
|
-- name: GetLatestSuggestionBatch :one
|
|
-- The newest batch, whatever its status. Returns sql.ErrNoRows when there
|
|
-- is none.
|
|
SELECT * FROM suggestion_batches
|
|
ORDER BY id DESC
|
|
LIMIT 1;
|
|
|
|
-- name: GetSuggestionBatchJobID :one
|
|
-- The id of the job that runs batch batch_id.
|
|
SELECT id FROM jobs
|
|
WHERE kind = sqlc.arg(kind)
|
|
AND json_extract(payload, '$.batch_id') = sqlc.arg(batch_id)
|
|
ORDER BY id
|
|
LIMIT 1;
|
|
|
|
-- name: StartSuggestionBatch :execrows
|
|
-- Marks a pending batch running; a batch in any other status is left as
|
|
-- it is (0 rows).
|
|
UPDATE suggestion_batches
|
|
SET status = 'running', updated_at = ?
|
|
WHERE id = ? AND status = 'pending';
|
|
|
|
-- name: FinishSuggestionBatch :execrows
|
|
-- Records a pending or running batch as done or failed; a batch already
|
|
-- finished is left as it is (0 rows).
|
|
UPDATE suggestion_batches
|
|
SET status = ?, updated_at = ?
|
|
WHERE id = ? AND status IN ('pending', 'running');
|
|
|
|
-- name: FailOrphanedSuggestionBatches :execrows
|
|
-- Fails every batch still pending or running whose job is no longer queued
|
|
-- or running: the process stopped, or recording the batch's end failed,
|
|
-- before its handler recorded a result. Run before reading the active batch.
|
|
UPDATE suggestion_batches
|
|
SET status = 'failed', updated_at = sqlc.arg(updated_at)
|
|
WHERE status IN ('pending', 'running')
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM jobs
|
|
WHERE jobs.kind = sqlc.arg(kind)
|
|
AND jobs.status IN ('queued', 'running')
|
|
AND json_extract(jobs.payload, '$.batch_id') = suggestion_batches.id
|
|
);
|
|
|
|
-- name: CreateSuggestion :exec
|
|
-- name is the name the dish is suggested under, kept whatever its dinner is
|
|
-- later renamed.
|
|
INSERT INTO suggestions (
|
|
id, dinner_id, batch_id, name, reason, cited_regular_ids, status, created_at, updated_at
|
|
) VALUES (
|
|
?, ?, ?, ?, ?, ?, 'pending', ?, ?
|
|
);
|
|
|
|
-- name: GetSuggestion :one
|
|
-- A suggestion with its dinner. Returns sql.ErrNoRows for an unknown id.
|
|
SELECT sqlc.embed(suggestions), sqlc.embed(dinners)
|
|
FROM suggestions
|
|
JOIN dinners ON dinners.id = suggestions.dinner_id
|
|
WHERE suggestions.id = ?;
|
|
|
|
-- name: ListDeck :many
|
|
-- The pending suggestions whose dinner is still suggested, oldest first,
|
|
-- with their dinners.
|
|
SELECT sqlc.embed(suggestions), sqlc.embed(dinners)
|
|
FROM suggestions
|
|
JOIN dinners ON dinners.id = suggestions.dinner_id
|
|
WHERE suggestions.status = 'pending' AND dinners.status = 'suggested'
|
|
ORDER BY suggestions.created_at, suggestions.id;
|
|
|
|
-- name: CountDeck :one
|
|
-- How many suggestions ListDeck returns.
|
|
SELECT COUNT(*)
|
|
FROM suggestions
|
|
JOIN dinners ON dinners.id = suggestions.dinner_id
|
|
WHERE suggestions.status = 'pending' AND dinners.status = 'suggested';
|
|
|
|
-- name: ListPassedNames :many
|
|
-- Every name the household turned down, oldest decision first: the name
|
|
-- each declined suggestion was suggested under, which renaming its dinner
|
|
-- does not change, and the name each dinner a Rotation check dropped
|
|
-- ("Not for us") had when dropped, which renaming it does not change.
|
|
SELECT name FROM (
|
|
SELECT name, decided_at, id
|
|
FROM suggestions
|
|
WHERE status = 'declined'
|
|
UNION ALL
|
|
SELECT name, decided_at, id
|
|
FROM rotation_reviews
|
|
WHERE decision = 'drop'
|
|
)
|
|
ORDER BY decided_at, id;
|
|
|
|
-- name: DecideSuggestion :execrows
|
|
-- Records the household's decision on a pending suggestion; one already
|
|
-- decided is left as it is (0 rows).
|
|
UPDATE suggestions
|
|
SET status = sqlc.arg(status), decided_at = sqlc.arg(now), updated_at = sqlc.arg(now)
|
|
WHERE id = sqlc.arg(id) AND status = 'pending';
|
|
|
|
-- name: MoveSuggestedDinner :execrows
|
|
-- Moves a dinner still suggested to status (quest_log or archived),
|
|
-- recording updated_by; a dinner no longer suggested is left as it is
|
|
-- (0 rows).
|
|
UPDATE dinners
|
|
SET status = sqlc.arg(status), updated_by = sqlc.arg(updated_by), updated_at = sqlc.arg(updated_at)
|
|
WHERE id = sqlc.arg(id) AND status = 'suggested';
|
|
|
|
-- name: GetDinnerSuggestionReason :one
|
|
-- The reason of the suggestion that created dinner_id, its earliest.
|
|
-- Returns sql.ErrNoRows for a dinner no suggestion created.
|
|
SELECT reason FROM suggestions
|
|
WHERE dinner_id = ?
|
|
ORDER BY created_at, id
|
|
LIMIT 1;
|