Created
April 7, 2024 23:44
-
-
Save RomanTurner/0208ebf4fcaae7a741f6e236e9382db1 to your computer and use it in GitHub Desktop.
Ruby Simple Event as State Machine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Event | |
class Base < ActiveRecord::Base | |
self.table_name = 'events' | |
# Callbacks to enforce state transitions logic | |
before_update :validate_status_transition | |
enum status: { | |
enqueued: 0, | |
processing: 1, | |
completed: 2, | |
failed: 3 | |
} | |
# Transactional work processing | |
def process | |
ActiveRecord::Base.transaction do | |
update!(status: :processing) | |
yield(self) | |
update!(status: :completed) | |
rescue StandardError => e | |
current_data = data || {} | |
update!(status: :failed, data: current_data.merge('error' => e.message)) | |
raise ActiveRecord::Rollback | |
end | |
end | |
def perform_async | |
EventJob.perform_async(id) | |
end | |
def perform_now | |
EventJob.perform_now(id) | |
end | |
def perform_later(...) | |
EventJob.perform_later(...) | |
end | |
private | |
def validate_status_transition | |
return if status_changed? && valid_transition? | |
errors.add(:status, 'transition is not allowed') | |
throw(:abort) | |
end | |
def valid_transition? | |
case status_was | |
when 'enqueued' | |
processing? | |
when 'processing' | |
completed? || failed? | |
when 'completed', 'failed' | |
false # No transitions allowed from completed or failed | |
else | |
true # for new records | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment