Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4515 +/- ##
==========================================
+ Coverage 89.54% 89.56% +0.01%
==========================================
Files 425 425
Lines 20307 20325 +18
==========================================
+ Hits 18184 18204 +20
+ Misses 2123 2121 -2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
* feat: add queue column to runs table for Fast Lanes support (#4500) Add a `queue` VARCHAR column to the `runs` table (NOT NULL, default "default") with a composite partial index on (state, queue, inserted_at) for active runs. Queue assignment rules: - Webhook triggers with webhook_reply: :after_completion → "fast_lane" - All other triggers (webhook/cron/kafka) → "default" - Manual runs and retries → "manual" * refactor: split migration, move queue routing to WorkOrders Split the combined add-column + concurrent-index migration into two separate migrations (transactional and non-transactional). Move queue determination logic from Run.for(%Trigger{}) into WorkOrders.build_for where all other routing decisions live. Unify both Run.for/2 clauses to use put_if_provided/3. Add tests for invalid queue rejection.
* feat: add queue column to runs table for Fast Lanes support (#4500) Add a `queue` VARCHAR column to the `runs` table (NOT NULL, default "default") with a composite partial index on (state, queue, inserted_at) for active runs. Queue assignment rules: - Webhook triggers with webhook_reply: :after_completion → "fast_lane" - All other triggers (webhook/cron/kafka) → "default" - Manual runs and retries → "manual" * refactor: split migration, move queue routing to WorkOrders Split the combined add-column + concurrent-index migration into two separate migrations (transactional and non-transactional). Move queue determination logic from Run.for(%Trigger{}) into WorkOrders.build_for where all other routing decisions live. Unify both Run.for/2 clauses to use put_if_provided/3. Add tests for invalid queue rejection. * feat: thread queue preferences through the claim path (#4501) Workers can now pass a `queues` parameter in their claim request to filter or prioritize runs by queue. Filter mode (no wildcard) returns only runs from named queues. Preference mode (with `*`) orders named queues first while still returning all runs. Defaults to ["manual", "*"] for backward compatibility. * test: add queue filtering and preference tests for claim path Cover filter mode, preference mode, default behavior, and malformed input fallback across Queue, FifoRunQueue, Runs, Services.RunQueue, and WorkerChannel. Update existing claim tests to new 3-arity signatures. * chore: fix worker_name typespec and remove dead test code
Runs on the fast_lane queue now bypass project concurrency checks in the claim query, ensuring sync webhook responses are never blocked by in-progress cron/async runs.
Queue.claim was stripping all ORDER BY clauses before applying queue preference ordering. This broke Thunderbolt's round-robin scheduler which relies on project_id ordering in the base query. Now saves and restores the caller's ordering after queue preference.
Map priority 0 (immediate) to "manual" and priority 1 (normal) to "default" instead of setting all rows to "default".
….22.1 Update @openfn/ws-worker from 1.17.0 to 1.22.1, which includes the --workloops CLI option for splitting worker capacity into independent slot groups with queue preferences (e.g., "fast_lane:1 manual>*:4"). RuntimeManager changes: - Add workloops field to Config struct, passed as --workloops flag - Remove default capacity (nil instead of 5) so the worker uses its own defaults unless explicitly configured - Add WORKER_WORKLOOPS env var to bootstrap config - capacity and workloops guards only emit when set; if both are configured the worker itself reports the conflict
Replace case expression with function clause pattern matching to bring complexity under Credo's threshold.
What changed in lib/lightning/work_orders.ex:
- retry/3 → passes Keyword.get(opts, :queue, "manual") to enqueue_retry, so single retries default to "manual"
- retry_many([%RunStep{}], opts) → injects queue: "default" into opts before calling individual retry() calls (bulk retry from a specific job)
- retry_many([%WorkOrder{}], opts) → unchanged; it enqueues Oban jobs which call enqueue_many_for_retry with default "default"
- enqueue_many_for_retry/3 → accepts optional queue param (default "default") for bulk retries from start
- enqueue_retry/3 and new_retry_run/8 — now accept and thread through the queue value
Result:
┌────────────────────────┬───────────┐
│ Path │ Queue │
├────────────────────────┼───────────┤
│ Manual run (click Run) │ "manual" │
├────────────────────────┼───────────┤
│ Single retry │ "manual" │
├────────────────────────┼───────────┤
│ Bulk retry from start │ "default" │
├────────────────────────┼───────────┤
│ Bulk retry from job │ "default" │
└────────────────────────┴───────────┘
taylordowns2000
approved these changes
Mar 18, 2026
Member
taylordowns2000
left a comment
There was a problem hiding this comment.
it's great. thank you. i've made a small change (bulk retries shouldn't get same priority as manual runs) which you're welcome to revert if it's more complicated than i thought. otherwise please merge at your leisure. i'm now moving on to the TB review.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR adds Fast Lanes support to Lightning — dedicated worker capacity for
named queues, guaranteeing low-latency execution for sync workloads.
Closes #4498
This is a tracking PR that collects the Lightning-side implementation:
runs.queuecolumn and set queue at run creation #4500 — Addruns.queuecolumn and set queue at run creation (PR Add runs queue column for Fast Lanes support #4514)Related worker-side issues:
--queuesoption and slot group configuration parsing kit#1288 — Add--queuesCLI option and slot group configuration parsingWhat's included
Data model (#4500)
runs.queuestring column (NOT NULL, default"default")(state, queue, inserted_at)for active runswebhook_reply: :after_completion) →"fast_lane""default""manual"default,fast_lane, ormanualClaim path (#4501)
claimmessage gains aqueuesparameter (ordered preference chain)*): strict pinning, only named queues returned*): all queues eligible, named ones prioritizedqueuesdefaults to["manual", "*"]Queue.claim/4benefits both FifoRunQueue and RoundRobinQueuesanitise_queues/1validates input and falls back to defaults for malformed payloadsValidation steps
mix ecto.resetto apply the split migrations cleanlymix test— all tests passqueue: "fast_lane"queue: "default"queue: "manual"["fast_lane"]only receives fast_lane runs["manual", "*"]gets manual runs first, then FIFOqueuesgets the default["manual", "*"]behaviorAdditional notes for the reviewer
prioritycolumn, Removeprioritycolumn from runs table #4502) is out of scopeand will happen after Fast Lanes is deployed and stable
prioritycolumn is kept and still written for manual/retry runs(
:immediate) as a backward-compat safety net during rolloutCOALESCE(array_position(...), wildcard_pos)insteadof
CASE WHENfor queue preference ordering — semantically equivalent butcleaner for variable-length preference chains
which this PR unblocks
AI Usage
Pre-submission checklist
/reviewwith Claude Code)
(e.g.,
:owner,:admin,:editor,:viewer)