Class: Tasker::StateMachine::TaskStateMachine

Inherits:
Object
  • Object
show all
Extended by:
Concerns::EventPublisher
Includes:
Statesman::Machine
Defined in:
lib/tasker/state_machine/task_state_machine.rb

Overview

TaskStateMachine defines state transitions for tasks using Statesman

This state machine manages task lifecycle states and integrates with the existing event system to provide declarative state management.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Concerns::EventPublisher

infer_step_event_type_from_state, publish_custom_event, publish_no_viable_steps, publish_step_backoff, publish_step_before_handle, publish_step_cancelled, publish_step_completed, publish_step_event_for_context, publish_step_failed, publish_step_retry_requested, publish_step_started, publish_steps_execution_completed, publish_steps_execution_started, publish_task_completed, publish_task_enqueue, publish_task_failed, publish_task_finalization_completed, publish_task_finalization_started, publish_task_pending_transition, publish_task_reenqueue_delayed, publish_task_reenqueue_failed, publish_task_reenqueue_requested, publish_task_reenqueue_started, publish_task_retry_requested, publish_task_started, publish_viable_steps_discovered, publish_workflow_state_unclear, publish_workflow_step_completed, publish_workflow_task_started

Class Method Details

.determine_transition_event_name(from_state, to_state) ⇒ String?

Determine the transition event name based on states using hashmap lookup

Parameters:

  • from_state (String)

    The from state

  • to_state (String)

    The to state

Returns:

  • (String, nil)

    The event name or nil if no mapping exists



156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/tasker/state_machine/task_state_machine.rb', line 156

def determine_transition_event_name(from_state, to_state)
  transition_key = [from_state, to_state]
  event_name = Constants::TASK_TRANSITION_EVENT_MAP[transition_key]

  if event_name.nil?
    Rails.logger.warn do
      "Unexpected task state transition: #{from_state || 'initial'}#{to_state}. " \
        'No event will be fired for this transition.'
    end
  end

  event_name
end

.effective_current_state(task) ⇒ String

Get the effective current state, handling blank/empty states

Parameters:

  • task (Task)

    The task to check

Returns:

  • (String)

    The effective current state (blank states become PENDING)



137
138
139
140
# File 'lib/tasker/state_machine/task_state_machine.rb', line 137

def effective_current_state(task)
  current_state = task.state_machine.current_state
  current_state.presence || Constants::TaskStatuses::PENDING
end

.idempotent_transition?(task, target_state) ⇒ Boolean

Check if a transition is idempotent (current state == target state)

Parameters:

  • task (Task)

    The task to check

  • target_state (String)

    The target state

Returns:

  • (Boolean)

    True if this is an idempotent transition



129
130
131
# File 'lib/tasker/state_machine/task_state_machine.rb', line 129

def idempotent_transition?(task, target_state)
  task.state_machine.current_state == target_state
end

.safe_fire_event(event_name, context = {}) ⇒ void

This method returns an undefined value.

Safely fire a lifecycle event using dry-events bus

Parameters:

  • event_name (String)

    The event name

  • context (Hash) (defaults to: {})

    The event context



147
148
149
# File 'lib/tasker/state_machine/task_state_machine.rb', line 147

def safe_fire_event(event_name, context = {})
  publish_event(event_name, context)
end

Instance Method Details

#current_stateObject

Override current_state to work with custom transition model Since TaskTransition doesn’t include Statesman::Adapters::ActiveRecordTransition, we need to implement our own current_state logic using the most_recent column



111
112
113
114
115
116
117
118
119
120
# File 'lib/tasker/state_machine/task_state_machine.rb', line 111

def current_state
  most_recent_transition = object.task_transitions.where(most_recent: true).first

  if most_recent_transition
    most_recent_transition.to_state
  else
    # Return initial state if no transitions exist
    Constants::TaskStatuses::PENDING
  end
end