Class: Stepped::Action
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Stepped::Action
- Defined in:
- app/models/stepped/action.rb
Defined Under Namespace
Classes: Deadlock
Constant Summary collapse
- STATUSES =
%w[ pending performing succeeded superseded cancelled failed timed_out deadlocked ].freeze
- KEYS_JOINER =
"/"
Instance Method Summary collapse
- #accomplished(step) ⇒ Object
- #achieves?(action) ⇒ Boolean
- #actor_becomes_base ⇒ Object
- #apply_definition ⇒ Object
- #cancel ⇒ Object
- #cancellable? ⇒ Boolean
- #complete ⇒ Object
- #complete!(status = :succeeded) ⇒ Object
- #completed? ⇒ Boolean
- #compute_checksum_key ⇒ Object
- #compute_concurrency_key ⇒ Object
- #compute_timeout ⇒ Object
- #copy_parent_steps_to(action) ⇒ Object
- #deadlock! ⇒ Object
- #definition ⇒ Object
- #descendant_of?(action) ⇒ Boolean
- #finalize_complete(status) ⇒ Object
- #obtain_lock_and_perform ⇒ Object
- #outbound_complete_key ⇒ Object
- #perform ⇒ Object
- #perform_current_step ⇒ Object
- #propagate_completion_to_parent_steps ⇒ Object
- #propagated_touch ⇒ Object
- #safe_actor ⇒ Object
- #short_checksum ⇒ Object
- #succeeded_including_callbacks? ⇒ Boolean
- #supersede_with(action) ⇒ Object
- #timeout ⇒ Object
- #timeout? ⇒ Boolean
- #update_performance(performance) ⇒ Object
Instance Method Details
#accomplished(step) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 |
# File 'app/models/stepped/action.rb', line 123 def accomplished(step) if step.failed? complete! :failed elsif more_steps_to_do? increment :current_step_index save! perform_current_step elsif !outbound? complete! end end |
#achieves?(action) ⇒ Boolean
87 88 89 |
# File 'app/models/stepped/action.rb', line 87 def achieves?(action) checksum_key == action.checksum_key && checksum == action.checksum end |
#actor_becomes_base ⇒ Object
140 141 142 |
# File 'app/models/stepped/action.rb', line 140 def actor_becomes_base safe_actor&.becomes actor_type.constantize end |
#apply_definition ⇒ Object
203 204 205 206 207 208 209 210 |
# File 'app/models/stepped/action.rb', line 203 def apply_definition return if definition.nil? self.outbound = definition.outbound self.concurrency_key = compute_concurrency_key self.checksum_key = compute_checksum_key self.job = definition.job self.timeout_seconds = compute_timeout end |
#cancel ⇒ Object
74 75 76 |
# File 'app/models/stepped/action.rb', line 74 def cancel self.status = :cancelled end |
#cancellable? ⇒ Boolean
160 161 162 |
# File 'app/models/stepped/action.rb', line 160 def cancellable? pending? || performing? end |
#complete ⇒ Object
78 79 80 |
# File 'app/models/stepped/action.rb', line 78 def complete self.status = :succeeded end |
#complete!(status = :succeeded) ⇒ Object
164 165 166 |
# File 'app/models/stepped/action.rb', line 164 def complete!(status = :succeeded) Stepped::Performance.complete_action self, status end |
#completed? ⇒ Boolean
194 195 196 |
# File 'app/models/stepped/action.rb', line 194 def completed? cancelled? || succeeded? || superseded? || failed? || timed_out? || deadlocked? end |
#compute_checksum_key ⇒ Object
115 116 117 |
# File 'app/models/stepped/action.rb', line 115 def compute_checksum_key run_definition_block :checksum_key_block end |
#compute_concurrency_key ⇒ Object
111 112 113 |
# File 'app/models/stepped/action.rb', line 111 def compute_concurrency_key run_definition_block :concurrency_key_block end |
#compute_timeout ⇒ Object
152 153 154 155 156 157 158 |
# File 'app/models/stepped/action.rb', line 152 def compute_timeout if definition.timeout.is_a?(Symbol) actor.send(definition.timeout) else definition.timeout end end |
#copy_parent_steps_to(action) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 |
# File 'app/models/stepped/action.rb', line 91 def copy_parent_steps_to(action) raise ArgumentError, "Can't copy_parent_steps_to self" if action == self parent_steps.each do |step| transaction(requires_new: true) do action.parent_steps << step end rescue ActiveRecord::RecordNotUnique action.reload end end |
#deadlock! ⇒ Object
177 178 179 180 181 182 183 184 185 |
# File 'app/models/stepped/action.rb', line 177 def deadlock! e = Deadlock.new "#{name} on #{actor.class.name}/#{actor.id}" handled = Stepped.handled_exception_classes.any? { e.class <= _1 } raise e unless handled Rails.error.report(e, handled:) self.status = :deadlocked propagate_completion_to_parent_steps end |
#definition ⇒ Object
70 71 72 |
# File 'app/models/stepped/action.rb', line 70 def definition @definition = Stepped::Registry.find_or_add actor.class, name end |
#descendant_of?(action) ⇒ Boolean
187 188 189 190 191 192 |
# File 'app/models/stepped/action.rb', line 187 def descendant_of?(action) parent_steps.any? do |step| return true if step.action_id == action.id step.action.descendant_of?(action) end end |
#finalize_complete(status) ⇒ Object
168 169 170 171 172 173 174 175 |
# File 'app/models/stepped/action.rb', line 168 def finalize_complete(status) self.status = status execute_after_complete_callbacks update!(completed_at: Time.zone.now, performance: nil) Stepped::Achievement.grand_to(self) if succeeded_including_callbacks? && checksum.present? propagate_completion_to_parent_steps end |
#obtain_lock_and_perform ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'app/models/stepped/action.rb', line 34 def obtain_lock_and_perform apply_definition run_before_chain if completed? propagate_completion_to_parent_steps return self end set_checksum Stepped::Achievement.raise_if_exists_for?(self) Stepped::Performance.obtain_for(self) rescue Stepped::Achievement::ExistsError self.status = :succeeded propagate_completion_to_parent_steps self end |
#outbound_complete_key ⇒ Object
119 120 121 |
# File 'app/models/stepped/action.rb', line 119 def outbound_complete_key outbound? ? tenancy_key : nil end |
#perform ⇒ Object
59 60 61 62 63 64 65 66 67 68 |
# File 'app/models/stepped/action.rb', line 59 def perform update! status: :performing, started_at: Time.zone.now Stepped::Achievement.erase_of self ActiveRecord.after_all_transactions_commit do perform_current_step Stepped::TimeoutJob.set(wait: timeout).perform_later(self) if timeout? end end |
#perform_current_step ⇒ Object
103 104 105 106 107 108 109 |
# File 'app/models/stepped/action.rb', line 103 def perform_current_step steps.create!( definition_index: current_step_index, started_at: Time.zone.now, status: :performing ).perform end |
#propagate_completion_to_parent_steps ⇒ Object
216 217 218 219 220 221 222 |
# File 'app/models/stepped/action.rb', line 216 def propagate_completion_to_parent_steps ActiveRecord.after_all_transactions_commit do parent_steps.each do |step| step.conclude_job(succeeded_including_callbacks?) end end end |
#propagated_touch ⇒ Object
198 199 200 201 |
# File 'app/models/stepped/action.rb', line 198 def propagated_touch touch parent_steps.each { _1.action.propagated_touch } end |
#safe_actor ⇒ Object
135 136 137 138 |
# File 'app/models/stepped/action.rb', line 135 def safe_actor actor rescue ActiveRecord::SubclassNotFound end |
#short_checksum ⇒ Object
144 145 146 |
# File 'app/models/stepped/action.rb', line 144 def short_checksum checksum.to_s[0..7] end |
#succeeded_including_callbacks? ⇒ Boolean
224 225 226 |
# File 'app/models/stepped/action.rb', line 224 def succeeded_including_callbacks? succeeded? && after_callbacks_failed_count.nil? end |
#supersede_with(action) ⇒ Object
82 83 84 85 |
# File 'app/models/stepped/action.rb', line 82 def supersede_with(action) update! completed_at: Time.zone.now, status: :superseded copy_parent_steps_to action end |
#timeout ⇒ Object
212 213 214 |
# File 'app/models/stepped/action.rb', line 212 def timeout timeout_seconds.seconds end |
#timeout? ⇒ Boolean
148 149 150 |
# File 'app/models/stepped/action.rb', line 148 def timeout? timeout_seconds.present? end |
#update_performance(performance) ⇒ Object
53 54 55 56 57 |
# File 'app/models/stepped/action.rb', line 53 def update_performance(performance) self.performance = performance perform if pending? && (performance.action == self) save! end |