Every flow run goes through its queue, and a paused run lends its slot to the runs that unblock it #205
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "task/3998-every-flow-run-goes-through-its-queue-an"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Tracker: #3998
Step 1 of plan #3997.
What it delivers
begin_flow(db, id, lent_by, queued)has one caller,advance_queues.take_outanddispatch_stepare gone, and so isflow_run.from_queue: the column,FlowRun.from_queue, the API member and the web type.enqueue_flowand begins none; a blocker already queued stays where it is, andreevaluate_waitbegins none either. Run steps reads the step's latest flow run, begun or not: with none it queues one and holds, it holds while that run isqueued,runningorblocked, and it concludesa step needs youwhile the run waits on Agra or once it was stopped, begun or not. A blocker's or a step's run waits in its queue on what its task waits on, as every queued run does.src/store.sx: one SQL reading of done (done_sql, whichtask_donereads anddone_bygoes through); one recursive walk,unblocks, overblocks,followsandparent(parent only while the parent's live flow run is at Run steps), each kind of edge a recursive SELECT of its own that joinsrelationfrom the reached task by its primary key orrelation_other; going (begun and not ended,QUEUE_GOING_SQL); paused; and lent slots, a largest matching of a queue's going runs to the paused runs they unblock (queue_lending,augment).advance_queuestakes each queue in turn (begin_next): a queued run whose task waits on nothing begins on a lent slot when an augmenting path from it reaches a paused run lending to no going run, while the going runs that are not paused are fewer thanslots; with no such path, on a slot of its own while the going runs left unmatched are fewer. 0 slots begins nothing, and a queue whose going runs that are not paused fill its slots begins nothing before any walk (queue_going).dequeuedrecordslent_by: the paused run of its queue the run began on, else null.goingand answersbehind;done_todayholds every run of the queue that began and ended today;GET /api/queuesandGET /api/projects/:id/queueslist a plan's branch while a step's run is queued or going on it.blockersgive each blocker its live flow run, else its latest started one (BlockingTask.flow_run), so a blocker waiting its turn answers itsqueuedrun. The comments ofBlockingTask,blockers_json,web/src/lib/types.ts,web/src/lib/flow-runs.tsandweb/src/lib/FlowCard.sveltesay so.dequeuedevent to{"lent_by": …}(the flow run itsflow_run_idnamed when that one is of its run's project and base, else null) and dropsflow_run.from_queue.tests/support/schema.sxgainsBACK_TO_58, andback_to_57()andback_to_55()go through it.Regressions (fail on master, pass at the head)
The tests are in
tests/flow_queue.sxandtests/blockers.sx;beganintests/flow_queue.sxreadslent_by. Built against master'ssrc/,tests/flow_queue.sxendsFLOW QUEUE FAIL (38 checks)andtests/blockers.sxBLOCKERS FAIL (9 checks). Everybegancheck fails on master because master writes nolent_by, so the behaviour master shows for each regression was read with a probe that drives the same scenarios through the API, built against master'ssrc/and against the head:going [1], blockerbehind null,dequeued {"from_queue":false,"flow_run_id":1}going [1,2], holder and blockerbehind 0,dequeued {"lent_by":1}runningat oncerunning, fourqueued; each begins on the lent slot as the one before endsdone, and the holder resumes after the fifthblockersrunning, begun outside the slotsqueued,undispatchedfalse, the fifth its queued run and not its stopped onerunningas P1's Wait is reached, B2runningas P2's is;going [10,11]queuedwhile P2 runs, thenrunningon P1's lent slot once P2 is held, B2queueduntil P1 endsrunningwhile that queue's slot is held,dequeued {"from_queue":false,"flow_run_id":15}, absent fromgoing [14]queueduntil the slot frees, thendequeued {"lent_by":null}runningat once, absent fromgoing [17]queued, itswaits_onnaming the blocking task; stopped, the plan asks Agra; dispatched again, the plan holds; the task done, the step begins on the plan's lent slotGET /api/projects/:id/queueslistsmasteronlytask/19-the-planwith the step goingfrom_queuekept, eachdequeuedstill{"from_queue":…,"flow_run_id":…}from_queuegone, the run begun outside the slots going,pragma_foreign_key_checkempty,{"lent_by":1}for the Wait's blocker of its own queue and{"lent_by":null}for the blocker in another project, the step on its branch and a run its queue beganfrom_queuea going run answers … no from_queueFAILsThe other cases (the lent slot lent on by a blocker held at its own Wait, lending only to runs that unblock the paused run, the largest matching, 0 slots,
done_today, ablocksrelation made to a held run's task, a blocker whose task is itself blocked) fail on master as listed in the runs above and pass at the head.waitOfinweb/src/lib/flow-runs.test.tspins the Wait panel's reading of a blocker whoseflow_runisqueued: standingqueued, with its flow. The SPA's code does not change, so it passes on master too.The walk's cost
A probe database (4016 tasks, 2000 done by status; 12,018 relations:
blocksi→(7i mod 4000)+1,followsi→(13i mod 4000)+1,parenti→i/10+1, plus ablockschain of 8 and afollowschain of 8 crossing it; 3000 ended runs; a queue at 2 slots with oneblockedand onerunningrun and 50 queued runs that wait on nothing; arunningand aneeds_yourun at Run steps and ablockedone at a Wait on another base), timed throughstore.unblocksandstore.advance_queues:64f99701At
64f99701the plan readsrelationin full in each recursive step (aUNION ALLsubquery of every edge); at the head each arm SEARCHessqlite_autoindex_relation_1 (task_id=?)orrelation_other (other_task_id=?). The old and new walks give the same set for each of the 4016 tasks, reaches up to 16.Golden set
None. The diff under
web/e2etouches no snapshot.Gates at the head
sak-gate fastpassed while iterating.sak-gate full(run 2) passed atea298b03: the sx suite (73 tests), the release check, the deploy contract, vitest (474), Playwright (799) and the runner's Playwright config (10).