Guard plan drafts against swaps and keep confirm on single-flight
Return the draft job id as jobId, as the plan API contract specifies. Add a week_plans revision (migration 0013) that every swap and stored draft raises. A draft_week job reads the revision before draft_week runs and stores its week only while the plan still has it; a plan edited while the AI ran is left as it is and the job fails plan_changed, so a draft never erases the household's swap. A confirmed draft now joins only a confirmed queued or running job, so a job asked for without confirm can no longer fail it with confirm_required after the plan was synced. Test simultaneous drafts, a swap during a draft, a confirmed draft while an unconfirmed one runs, impossible calendar dates and start_by across the end of daylight saving time. Maestro task ea48e650-d510-49cc-8485-0f07174ee731. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
-- 0013_week_plan_revision: every edit of a week's plan — a swap or a
|
||||
-- stored draft — raises its revision. A draft_week job reads the revision
|
||||
-- before draft_week runs and stores its week only while the plan still
|
||||
-- has it, so a draft never overwrites an edit made while the AI ran.
|
||||
|
||||
ALTER TABLE week_plans ADD COLUMN revision INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -18,9 +18,10 @@ INSERT INTO week_plans (id, week_start, status, ai_note, created_at, updated_at)
|
||||
VALUES (?, ?, 'draft', ?, ?, ?);
|
||||
|
||||
-- name: RedraftWeekPlan :exec
|
||||
-- Records a new draft over plan id: its status and note.
|
||||
-- Records a new draft over plan id: its status and note, raising its
|
||||
-- revision.
|
||||
UPDATE week_plans
|
||||
SET status = ?, ai_note = ?, updated_at = ?
|
||||
SET status = ?, ai_note = ?, revision = revision + 1, updated_at = ?
|
||||
WHERE id = ?;
|
||||
|
||||
-- name: PutPlanDay :exec
|
||||
@@ -39,10 +40,11 @@ SET dinner_id = ?, is_new = ?, updated_at = ?
|
||||
WHERE plan_id = ? AND date = ?;
|
||||
|
||||
-- name: MarkWeekPlanEdited :exec
|
||||
-- Records an edit of plan id: a synced plan becomes changed, any other
|
||||
-- keeps its status.
|
||||
-- Records an edit of plan id, raising its revision: a synced plan becomes
|
||||
-- changed, any other keeps its status.
|
||||
UPDATE week_plans
|
||||
SET status = CASE WHEN status = 'synced' THEN 'changed' ELSE status END,
|
||||
revision = revision + 1,
|
||||
updated_at = ?
|
||||
WHERE id = ?;
|
||||
|
||||
@@ -72,10 +74,12 @@ ORDER BY plan_days.date;
|
||||
|
||||
-- name: GetActiveDraftJobID :one
|
||||
-- The id of the job of kind queued or running for the week starting
|
||||
-- week_start. Returns sql.ErrNoRows when there is none.
|
||||
-- week_start, one whose payload has confirm when confirmed is 1. Returns
|
||||
-- sql.ErrNoRows when there is none.
|
||||
SELECT id FROM jobs
|
||||
WHERE kind = sqlc.arg(kind)
|
||||
AND status IN ('queued', 'running')
|
||||
AND json_extract(payload, '$.week_start') = sqlc.arg(week_start)
|
||||
AND (CAST(sqlc.arg(confirmed) AS INTEGER) = 0 OR json_extract(payload, '$.confirm') = 1)
|
||||
ORDER BY id
|
||||
LIMIT 1;
|
||||
|
||||
Reference in New Issue
Block a user