T-HUB/apps/api/migrations/044_assemble_claim.sql
glass beadian 10dfda3b7c feat: editor-v2 assemble lane — multi-clip/card timeline rendering in the worker
Per the adopted qwen38 plan §2 (+ glm53 amendments): video_processing_jobs
kind 'assemble' (claim widened via 044), EdlPlan mirror validation
(lenient-fail), the filter_complex builder (interleaved concat pairs, fit
cover/contain chains, absolute-timeline PNG overlays with enable windows,
VO adelay/sidechain duck, hard-breaking word wrap for card PNGs), and the
runner's assemble path with pre-spawn trim gates, attempt backoff and 15-min
cap. Sources open by magic (SPENC1 kek / SPENC2 direct key) so direct-to-R2
uploads assemble without the api ever seeing bytes. Tests: builder 18,
edl-plan 12, overlay-png 3, runner fakes extended.
2026-10-16 21:12:55 +00:00

54 lines
2.2 KiB
PL/PgSQL

-- 044: the produce worker claims ASSEMBLE jobs (editor-v2 L1, the worker assemble lane).
--
-- An assemble row is an editor-v2 timeline render: input_json carries
-- { edlProjectId, project: EdlProject } (the EDL shapes live in
-- apps/api/src/media-control/edl.ts), video_asset_id points at the project's
-- first source clip, and the produced output is a derived video_assets row
-- exactly like a compose/mix produce. 043 owns the intake half of the feature
-- (edl_projects + widening video_processing_jobs.kind's CHECK to admit
-- 'assemble'); THIS migration is only the worker's half — the claim's kind
-- filter widened so the lane can pick those rows up.
--
-- Same body as 042 with 'assemble' added to the kind list; 'transcoding'
-- remains the lease state and the stale-lease sweep is unchanged, so a worker
-- that dies mid-assembly still hands its row back through the same path a
-- dead compose/mix encode does today.
CREATE OR REPLACE FUNCTION produce_job_claim(p_lane text, p_stale_after interval)
RETURNS TABLE (
id uuid,
workspace_id uuid,
kind text,
input_json jsonb,
video_asset_id uuid
)
LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$
BEGIN
UPDATE video_processing_jobs stale
SET state = 'queued', progress_percent = 0, error = NULL, updated_at = now()
WHERE stale.state = 'transcoding'
AND stale.updated_at < now() - p_stale_after;
RETURN QUERY
UPDATE video_processing_jobs j
SET state = 'transcoding', progress_percent = 5, error = NULL, updated_at = now()
WHERE j.id IN (
SELECT c.id
FROM video_processing_jobs c
WHERE c.kind IN ('probe', 'compose', 'mix', 'assemble')
AND c.state = 'queued'
AND (
(p_lane = 'remote' AND c.input_json->>'lane' = 'remote')
OR (p_lane <> 'remote' AND c.input_json->>'lane' IS DISTINCT FROM 'remote')
)
ORDER BY c.created_at, c.id
FOR UPDATE SKIP LOCKED
LIMIT 1
)
RETURNING j.id, j.workspace_id, j.kind, j.input_json, j.video_asset_id;
END
$$;
-- Ownership unchanged from 040/042.
REVOKE ALL ON FUNCTION produce_job_claim(text, interval) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION produce_job_claim(text, interval) TO sp_app;