Module: ChronoForge::BranchProbe
- Defined in:
- lib/chrono_forge/branch_probe.rb
Overview
Single source of truth for "is this branch done?" — used by both merge_branches (boolean) and BranchMergeJob (which needs the sealed flag and pending count separately for its adaptive poll cadence). Option A: only :completed counts as done, so a failed/stalled child keeps the branch pending until recovered.
Class Method Summary collapse
- .done?(branch_log_id) ⇒ Boolean
-
.incomplete(branch_log_id) ⇒ Object
Relation of this branch's children that are not yet completed.
-
.never_started(branch_log_id) ⇒ Object
Children dispatched but not yet started (idle, started_at nil) — the queue of never-started work for this branch.
-
.never_started?(branch_log_id) ⇒ Boolean
A child was dispatched but no worker has started it yet.
-
.progressing(branch_log_id) ⇒ Object
Relation of children that can advance on their own — actively running, or dispatched-but-not-yet-started (started_at nil).
-
.running?(branch_log_id) ⇒ Boolean
A child of this branch is actively executing — a live worker will complete it, so the poller can hold its responsive floor rather than backing off.
-
.sealed?(branch_log_id) ⇒ Boolean
The branch's coordination log is sealed (fully dispatched).
-
.spawned(branch_log_id) ⇒ Object
All children spawned into this branch (every state) — the dispatch total.
Class Method Details
.done?(branch_log_id) ⇒ Boolean
66 67 68 |
# File 'lib/chrono_forge/branch_probe.rb', line 66 def done?(branch_log_id) sealed?(branch_log_id) && !incomplete(branch_log_id).exists? end |
.incomplete(branch_log_id) ⇒ Object
Relation of this branch's children that are not yet completed.
17 18 19 20 |
# File 'lib/chrono_forge/branch_probe.rb', line 17 def incomplete(branch_log_id) Workflow.where(parent_execution_log_id: branch_log_id) .where.not(state: Workflow.states[:completed]) end |
.never_started(branch_log_id) ⇒ Object
Children dispatched but not yet started (idle, started_at nil) — the queue of never-started work for this branch. A DROP in this count between polls means workers are actively pulling it off the queue (so a still-queued child is in line, not dropped); the rekick gate keys off that. Distinct from total pending, which a wait/wait_until child completing would drop without any never-started child moving. (Not to be confused with the dashboard's "Dispatched" column, which is the TOTAL children spawned.)
48 49 50 51 |
# File 'lib/chrono_forge/branch_probe.rb', line 48 def never_started(branch_log_id) Workflow.where(parent_execution_log_id: branch_log_id, state: Workflow.states[:idle], started_at: nil) end |
.never_started?(branch_log_id) ⇒ Boolean
A child was dispatched but no worker has started it yet. If this is the only motion left, it's a queued/rekicked-but-unpicked straggler (which may never be picked up), NOT active work — so the poller backs off.
56 |
# File 'lib/chrono_forge/branch_probe.rb', line 56 def never_started?(branch_log_id) = never_started(branch_log_id).exists? |
.progressing(branch_log_id) ⇒ Object
Relation of children that can advance on their own — actively running, or
dispatched-but-not-yet-started (started_at nil). This drives the adaptive
poll cadence. Deliberately EXCLUDES waiting children (idle with started_at
SET — parked on a wait/wait_until) and blocked children (failed/stalled —
awaiting operator recovery): polling can't make either progress, so they
must not pin the cadence at the responsive floor. They still count as
incomplete (the branch stays open), they just don't accelerate polling.
29 30 31 32 33 |
# File 'lib/chrono_forge/branch_probe.rb', line 29 def progressing(branch_log_id) base = Workflow.where(parent_execution_log_id: branch_log_id) base.where(state: Workflow.states[:running]) .or(base.where(state: Workflow.states[:idle], started_at: nil)) end |
.running?(branch_log_id) ⇒ Boolean
A child of this branch is actively executing — a live worker will complete it, so the poller can hold its responsive floor rather than backing off.
37 38 39 |
# File 'lib/chrono_forge/branch_probe.rb', line 37 def running?(branch_log_id) Workflow.where(parent_execution_log_id: branch_log_id, state: Workflow.states[:running]).exists? end |
.sealed?(branch_log_id) ⇒ Boolean
The branch's coordination log is sealed (fully dispatched).
12 13 14 |
# File 'lib/chrono_forge/branch_probe.rb', line 12 def sealed?(branch_log_id) ExecutionLog.where(id: branch_log_id, state: ExecutionLog.states[:completed]).exists? end |
.spawned(branch_log_id) ⇒ Object
All children spawned into this branch (every state) — the dispatch total. Fixed once the branch is sealed, so the poller counts it exactly once and caches it on the branch-log metadata. This is the dashboard's "Spawned" column. Distinct from #never_started, which is only the idle-and-unstarted subset.
62 63 64 |
# File 'lib/chrono_forge/branch_probe.rb', line 62 def spawned(branch_log_id) Workflow.where(parent_execution_log_id: branch_log_id) end |