textmachine/platform/internal/pgstore/migrations/00013_book_intake.sql

39 lines
2.3 KiB
SQL

-- +goose Up
-- The intake half of a book: what `POST /books` needs to move a row through
-- `uploading → parsing → not_started | rejected` and what a backstop sweep needs to finish that
-- walk when the process doing it died halfway.
--
-- Until this pack the three intake statuses existed in the contract and in the DDL check and had no
-- writer at all: a book could only be registered by the dev CLI, already parsed, straight into
-- `not_started`.
alter table books
-- How many times parsing has been CLAIMED for this book. Parsing is one $0 call of the engine
-- (`tmctl manifest`), and it fails in two different ways: the source cannot be cut (the book's
-- own fault, terminal) or the engine could not be run at all (the deployment's fault, and the
-- next sweep may well succeed). Only the second is retried, and only this counter bounds that
-- retry — without it a misconfigured host would re-run the engine over every uploaded book
-- forever.
add column parse_attempts integer not null default 0,
-- When the current parse was claimed. It is the CLAIM, not a timestamp for display: a book in
-- `parsing` whose claim is older than the grace is a parse whose process is gone, and the sweep
-- may take it again. Null means no claim is outstanding.
add column parse_started_at timestamptz,
-- Why a book was rejected, in the platform's own closed vocabulary — never the engine's text,
-- which reads like pipeline internals and must not cross the seam (contract §Problem, PT-33).
-- ⚠ NOT on the wire: contract v0 gives a book a `rejected` status and no reason field, so this
-- is written for an operator and for whatever later pack adds one. Inventing the field here is
-- not this zone's right (the precedent is last_resync_at, register row PD-150).
add column reject_reason text not null default '';
-- The sweep asks one question — "which books are stuck in intake" — every few seconds, and the
-- answer is a handful of rows in a table that grows with every book of every account.
create index books_intake_idx on books (status, added_at) where status in ('uploading', 'parsing');
-- +goose Down
drop index books_intake_idx;
alter table books
drop column reject_reason,
drop column parse_started_at,
drop column parse_attempts;