Skip to content

Commit 1f514b8

Browse files
refactor: consolidate run and work order state definitions (#4600)
* refactor: consolidate run and work order state definitions Hardcoded run and work order state lists were scattered across multiple files (dashboard_stats.ex, query.ex, impeded_project_helper.ex, dashboard_components.ex, search_params.ex, and tests), creating a maintenance burden where any state change required manual updates in multiple locations that the compiler cannot catch. Add Run.active_states/0 for [:available, :claimed, :started], WorkOrder.states/0 for all valid states, and WorkOrder.active_states/0 for [:pending, :running]. Replace all hardcoded state lists across the codebase with references to these canonical functions. Derive SearchParams.@statuses from WorkOrder.states/0 to keep the filter UI in sync automatically. Closes #4589 Signed-off-by: Asish Kumar <officialasishkumar@gmail.com> * style: fix formatting in search_params.ex Align pipe operator to satisfy mix format --check-formatted. Signed-off-by: Asish Kumar <officialasishkumar@gmail.com> * refactor: use single source of truth for state definitions Derived excluded_states in dashboard_stats from WorkOrder.active_states instead of hardcoding. Introduced @active_states module attribute in Run to share between the function and Ecto.Enum definition. Signed-off-by: Asish Kumar <officialasishkumar@gmail.com> * refactor: use WorkOrder.active_states in workorder_component The retry-button visibility check used a hardcoded [:pending, :running] list introduced after this branch was opened (#4578). Route it through WorkOrder.active_states/0 to keep the single-source-of-truth invariant from #4589 intact. * refactor: tighten state-list reuse after code review - Run.@States now reuses @active_states instead of re-listing the active states inline (single source of truth within the schema module). - dashboard_stats batch helper uses the @wo_active module attribute, matching its sibling helper instead of calling WorkOrder.active_states/0 inline. --------- Signed-off-by: Asish Kumar <officialasishkumar@gmail.com> Co-authored-by: Stuart Corbishley <corbish@gmail.com>
1 parent 962b6cd commit 1f514b8

11 files changed

Lines changed: 44 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ and this project adheres to
1919

2020
### Changed
2121

22+
- Consolidated run and work order state definitions into single source of truth
23+
by adding `Run.active_states/0`, `WorkOrder.states/0`, and
24+
`WorkOrder.active_states/0` and replacing all hardcoded state lists across the
25+
codebase
26+
[#4589](https://github.com/OpenFn/lightning/issues/4589)
27+
2228
### Fixed
2329

2430
## [2.16.7] - 2026-06-04

lib/lightning/dashboard_stats.ex

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ defmodule Lightning.DashboardStats do
1111
alias Lightning.Workflows.Workflow
1212
alias Lightning.WorkOrder
1313

14+
@wo_active WorkOrder.active_states()
15+
@run_active Run.active_states()
1416
@days_back 30
1517

1618
defmodule WorkflowStats do
@@ -58,7 +60,7 @@ defmodule Lightning.DashboardStats do
5860
last_workorders = batch_get_last_workorders(workflow_ids)
5961

6062
last_failed_workorders =
61-
batch_get_last_workorders(workflow_ids, [:pending, :running, :success])
63+
batch_get_last_workorders(workflow_ids, @wo_active ++ [:success])
6264

6365
Enum.map(workflows, fn workflow ->
6466
wf_id = workflow.id
@@ -201,7 +203,7 @@ defmodule Lightning.DashboardStats do
201203
end
202204

203205
defp get_last_failed_workorder(workflow, %{state: :success}) do
204-
excluded_states = [:pending, :running, :success]
206+
excluded_states = @wo_active ++ [:success]
205207
get_last_workorder(workflow, excluded_states)
206208
end
207209

@@ -238,7 +240,7 @@ defmodule Lightning.DashboardStats do
238240
{:success, cnt}, acc ->
239241
%{acc | success: cnt}
240242

241-
{state, cnt}, acc when state in [:pending, :running] ->
243+
{state, cnt}, acc when state in @wo_active ->
242244
Map.update!(acc, :pending, &(&1 + cnt))
243245

244246
{_other, cnt}, acc ->
@@ -260,7 +262,7 @@ defmodule Lightning.DashboardStats do
260262
{:success, cnt}, acc ->
261263
%{acc | success: cnt}
262264

263-
{state, cnt}, acc when state in [:available, :claimed, :started] ->
265+
{state, cnt}, acc when state in @run_active ->
264266
Map.update!(acc, :pending, &(&1 + cnt))
265267

266268
{_other, cnt}, acc ->
@@ -342,7 +344,7 @@ defmodule Lightning.DashboardStats do
342344
:success ->
343345
%{current | success: cnt}
344346

345-
s when s in [:pending, :running] ->
347+
s when s in @wo_active ->
346348
Map.update!(current, :pending, &(&1 + cnt))
347349

348350
_ ->
@@ -370,7 +372,7 @@ defmodule Lightning.DashboardStats do
370372
:success ->
371373
%{current | success: cnt}
372374

373-
s when s in [:available, :claimed, :started] ->
375+
s when s in @run_active ->
374376
Map.update!(current, :pending, &(&1 + cnt))
375377

376378
_ ->

lib/lightning/runs/prom_ex_plugin/impeded_project_helper.ex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ defmodule Lightning.Runs.PromExPlugin.ImpededProjectHelper do
2525
select: w.workflow_id,
2626
distinct: true
2727

28+
in_progress = Lightning.Run.active_states() -- [:available]
29+
2830
in_progress_runs_query =
2931
from r in Lightning.Run,
30-
where: r.state in [:claimed, :started],
32+
where: r.state in ^in_progress,
3133
join: w in assoc(r, :work_order),
3234
group_by: w.workflow_id,
3335
select: %{workflow_id: w.workflow_id, count: count(r.id)}

lib/lightning/runs/query.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ defmodule Lightning.Runs.Query do
231231
# Step 1: Rank runs within each workflow by priority and insertion time
232232
ranked_runs_query =
233233
from(r in Run,
234-
where: r.state in [:available, :claimed, :started],
234+
where: r.state in ^Run.active_states(),
235235
join: wo in assoc(r, :work_order),
236236
join: w in assoc(wo, :workflow),
237237
join: p in assoc(w, :project)

lib/lightning/runs/run.ex

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ defmodule Lightning.Run do
4141
:final_dataclip_id
4242
]}
4343

44+
@active_states [:available, :claimed, :started]
45+
4446
@final_states [
4547
:success,
4648
:failed,
@@ -51,7 +53,7 @@ defmodule Lightning.Run do
5153
:lost
5254
]
5355

54-
@states [:available, :claimed, :started] ++ @final_states
56+
@states @active_states ++ @final_states
5557

5658
@doc """
5759
Returns all possible states for a run.
@@ -63,6 +65,13 @@ defmodule Lightning.Run do
6365
"""
6466
def final_states, do: @final_states
6567

68+
@doc """
69+
Returns the list of active (in-progress) states for a run.
70+
71+
These are all non-final states: available, claimed, and started.
72+
"""
73+
def active_states, do: @active_states
74+
6675
@doc """
6776
Returns the list of failure states for a run.
6877

lib/lightning/workorders/search_params.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ defmodule Lightning.WorkOrders.SearchParams do
2121
:sort_direction
2222
]}
2323

24-
@statuses ~w(pending running success failed crashed killed cancelled lost exception rejected)
24+
@statuses Lightning.WorkOrder.states()
25+
|> Enum.map(&Atom.to_string/1)
2526
@statuses_set MapSet.new(@statuses)
2627
@search_fields ~w(id body log dataclip_name)
2728

lib/lightning/workorders/workorder.ex

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ defmodule Lightning.WorkOrder do
2121
workflow: Workflow.t() | Ecto.Association.NotLoaded.t()
2222
}
2323

24+
@active_states [:pending, :running]
25+
2426
@state_values Enum.concat(
25-
[:rejected, :pending, :running],
27+
[:rejected | @active_states],
2628
Run.final_states()
2729
)
2830

@@ -31,6 +33,11 @@ defmodule Lightning.WorkOrder do
3133
"""
3234
def states, do: @state_values
3335

36+
@doc """
37+
Returns the list of active (in-progress) work order states.
38+
"""
39+
def active_states, do: @active_states
40+
3441
@derive {Jason.Encoder,
3542
only: [
3643
:id,

lib/lightning_web/live/run_live/workorder_component.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ defmodule LightningWeb.RunLive.WorkOrderComponent do
55
use LightningWeb, :live_component
66

77
import LightningWeb.RunLive.Components
8+
alias Lightning.WorkOrder
89
alias Phoenix.LiveView.JS
910

1011
@impl true
@@ -261,7 +262,7 @@ defmodule LightningWeb.RunLive.WorkOrderComponent do
261262
<.icon name="hero-x-mark-mini" class="h-4 w-4" />
262263
</button>
263264
<% end %>
264-
<%= if @work_order.state not in [:pending, :running] do %>
265+
<%= if @work_order.state not in WorkOrder.active_states() do %>
265266
<%= if wo_dataclip_available?(@work_order) and @can_run_workflow do %>
266267
<button
267268
type="button"

lib/lightning_web/live/workflow_live/dashboard_components.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ defmodule LightningWeb.WorkflowLive.DashboardComponents do
44

55
alias Lightning.DashboardStats.ProjectMetrics
66
alias Lightning.Projects.Project
7+
alias Lightning.WorkOrder
78
alias Lightning.WorkOrders.SearchParams
89
alias LightningWeb.Components.Common
910
alias LightningWeb.WorkflowLive.Helpers
@@ -455,7 +456,7 @@ defmodule LightningWeb.WorkflowLive.DashboardComponents do
455456
<div>
456457
<div class="flex items-center gap-x-2">
457458
<span class="relative inline-flex h-2 w-2">
458-
<%= if @state in [:pending, :running] do %>
459+
<%= if @state in WorkOrder.active_states() do %>
459460
<span class={[
460461
"animate-ping absolute inline-flex h-full w-full rounded-full opacity-75",
461462
@dot_color

test/lightning/digest_email_worker_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ defmodule Lightning.DigestEmailWorkerTest do
153153
workflow = insert(:simple_workflow, project: project)
154154

155155
# Create workorders in non-final states (these should not be counted as failed)
156-
create_runs(workflow, [:pending, :running])
156+
create_runs(workflow, Lightning.WorkOrder.active_states())
157157

158158
# Create one actual failed run for comparison
159159
create_runs(workflow, [:failed])

0 commit comments

Comments
 (0)