-
Notifications
You must be signed in to change notification settings - Fork 69
/
run_status_validator.rb
87 lines (82 loc) · 3.87 KB
/
run_status_validator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# frozen_string_literal: true
module MaintenanceTasks
# Custom validator class responsible for ensuring that transitions between
# Run statuses are valid.
#
# @api private
class RunStatusValidator < ActiveModel::Validator
# Valid status transitions a Run can make.
VALID_STATUS_TRANSITIONS = {
# enqueued -> running occurs when the task starts performing.
# enqueued -> pausing occurs when the task is paused before starting.
# enqueued -> cancelling occurs when the task is cancelled
# before starting.
# enqueued -> errored occurs when the task job fails to be enqueued, or
# if the Task is deleted before is starts running.
"enqueued" => ["running", "pausing", "cancelling", "errored"],
# pausing -> paused occurs when the task actually halts performing and
# occupies a status of paused.
# pausing -> cancelling occurs when the user cancels a task immediately
# after it was paused, such that the task had not actually halted yet.
# pausing -> succeeded occurs when the task completes immediately after
# being paused. This can happen if the task is on its last iteration
# when it is paused, or if the task is paused after enqueue but has
# nothing in its collection to process.
# pausing -> errored occurs when the job raises an exception after the
# user has paused it.
"pausing" => ["paused", "cancelling", "succeeded", "errored"],
# cancelling -> cancelled occurs when the task actually halts performing
# and occupies a status of cancelled.
# cancelling -> succeeded occurs when the task completes immediately after
# being cancelled. See description for pausing -> succeeded.
# cancelling -> errored occurs when the job raises an exception after the
# user has cancelled it.
"cancelling" => ["cancelled", "succeeded", "errored"],
# running -> succeeded occurs when the task completes successfully.
# running -> pausing occurs when a user pauses the task as
# it's performing.
# running -> cancelling occurs when a user cancels the task as
# it's performing.
# running -> interrupted occurs when the job infra shuts down the task as
# it's performing.
# running -> errored occurs when the job raises an exception when running.
"running" => [
"succeeded",
"pausing",
"cancelling",
"interrupted",
"errored",
],
# paused -> enqueued occurs when the task is resumed after being paused.
# paused -> cancelled when the user cancels the task after it is paused.
"paused" => ["enqueued", "cancelled"],
# interrupted -> running occurs when the task is resumed after being
# interrupted by the job infrastructure.
# interrupted -> pausing occurs when the task is paused by the user while
# it is interrupted.
# interrupted -> cancelling occurs when the task is cancelled by the user
# while it is interrupted.
# interrupted -> errored occurs when the task is deleted while it is
# interrupted.
"interrupted" => ["running", "pausing", "cancelling", "errored"],
}
# Validate whether a transition from one Run status
# to another is acceptable.
#
# @param record [MaintenanceTasks::Run] the Run object being validated.
def validate(record)
return unless (previous_status, new_status = record.status_change)
valid_new_statuses = VALID_STATUS_TRANSITIONS.fetch(previous_status, [])
unless valid_new_statuses.include?(new_status)
add_invalid_status_error(record, previous_status, new_status)
end
end
private
def add_invalid_status_error(record, previous_status, new_status)
record.errors.add(
:status,
"Cannot transition run from status #{previous_status} to #{new_status}"
)
end
end
end