Class: ChronoForge::Dashboard::BranchPresenter
- Inherits:
-
Object
- Object
- ChronoForge::Dashboard::BranchPresenter
- Defined in:
- app/presenters/chrono_forge/dashboard/branch_presenter.rb
Overview
Health of a single branch (a branch$<name> execution log) for the parent’s detail page. Every child count is CAPPED and index-only on (parent_execution_log_id, state) — a branch can hold hundreds of thousands of children, so we never count the full set, only up to CAP (shown “CAP+”).
Constant Summary collapse
- CAP =
5000- BLOCKED_STATES =
%i[failed stalled].map { |s| ChronoForge::Workflow.states[s] }.freeze
- POLL_OVERDUE_GRACE =
A scheduled next poll this far past due means the BranchMergeJob poller likely never ran (queue latency aside) — a heuristic, hence “potential”.
120
Instance Attribute Summary collapse
-
#log ⇒ Object
readonly
Returns the value of attribute log.
-
#merge_state ⇒ Object
readonly
Returns the value of attribute merge_state.
Instance Method Summary collapse
- #blocked ⇒ Object
- #cap ⇒ Object
- #dispatched ⇒ Object
-
#initialize(log, merge_state = nil) ⇒ BranchPresenter
constructor
merge_state: :merged | :merging | nil (not yet merged).
- #last_polled_at ⇒ Object
- #name ⇒ Object
- #next_poll_at ⇒ Object
- #pending ⇒ Object
-
#poll_overdue? ⇒ Boolean
next_poll_at is nil once the merge completes, so a finished merge never looks overdue; a non-nil time well in the past = the poller is likely dead.
-
#polled? ⇒ Boolean
The BranchMergeJob stamps its poll state onto the branch log’s metadata (it can’t be queried from the backend; ActiveJob has no such API).
- #polls ⇒ Object
-
#sealed? ⇒ Boolean
The branch is “sealed” once its block closed (done dispatching children).
Constructor Details
#initialize(log, merge_state = nil) ⇒ BranchPresenter
merge_state: :merged | :merging | nil (not yet merged)
11 12 13 14 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 11 def initialize(log, merge_state = nil) @log = log @merge_state = merge_state end |
Instance Attribute Details
#log ⇒ Object (readonly)
Returns the value of attribute log.
16 17 18 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 16 def log @log end |
#merge_state ⇒ Object (readonly)
Returns the value of attribute merge_state.
16 17 18 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 16 def merge_state @merge_state end |
Instance Method Details
#blocked ⇒ Object
25 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 25 def blocked = capped(children.where(state: BLOCKED_STATES)) |
#cap ⇒ Object
27 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 27 def cap = CAP |
#dispatched ⇒ Object
23 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 23 def dispatched = capped(children) |
#last_polled_at ⇒ Object
38 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 38 def last_polled_at = parse_time(poll&.dig("last_polled_at")) |
#name ⇒ Object
18 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 18 def name = StepNameParser.parse(@log.step_name).name |
#next_poll_at ⇒ Object
39 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 39 def next_poll_at = parse_time(poll&.dig("next_poll_at")) |
#pending ⇒ Object
24 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 24 def pending = capped(children.where.not(state: ChronoForge::Workflow.states[:completed])) |
#poll_overdue? ⇒ Boolean
next_poll_at is nil once the merge completes, so a finished merge never looks overdue; a non-nil time well in the past = the poller is likely dead.
44 45 46 47 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 44 def poll_overdue? t = next_poll_at t.present? && t < Time.current - POLL_OVERDUE_GRACE end |
#polled? ⇒ Boolean
The BranchMergeJob stamps its poll state onto the branch log’s metadata (it can’t be queried from the backend; ActiveJob has no such API).
37 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 37 def polled? = poll.present? |
#polls ⇒ Object
40 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 40 def polls = poll&.dig("polls").to_i |
#sealed? ⇒ Boolean
The branch is “sealed” once its block closed (done dispatching children).
21 |
# File 'app/presenters/chrono_forge/dashboard/branch_presenter.rb', line 21 def sealed? = @log.completed? |