Module: ChronoForge::Executor::Methods::Wait
- Included in:
- ChronoForge::Executor::Methods
- Defined in:
- lib/chrono_forge/executor/methods/wait.rb
Instance Method Summary collapse
-
#wait(duration, name) ⇒ nil
Pauses workflow execution for a specified duration.
Instance Method Details
#wait(duration, name) ⇒ nil
Pauses workflow execution for a specified duration.
This method provides durable waiting that persists across workflow restarts and system interruptions. The wait duration and completion state are tracked in execution logs, ensuring that workflows can resume properly after delays.
Behavior
Duration Handling
-
Accepts any ActiveSupport::Duration (seconds, minutes, hours, days, etc.)
-
Wait time is calculated from the first execution attempt
-
Completion is checked against the originally scheduled end time
Idempotency
-
Each wait step must have a unique name within the workflow
-
If workflow is replayed after the wait period has passed, the step is skipped
-
Wait periods are not recalculated on workflow restarts
Resumability
-
Wait state is persisted in execution logs with target end time
-
Workflows can be stopped and restarted without affecting wait behavior
-
System restarts don’t reset or extend wait periods
-
Scheduled execution resumes automatically when wait period completes
Scheduling
-
Uses background job scheduling to resume workflow after wait period
-
Halts current workflow execution until scheduled time
-
Automatically reschedules if workflow is replayed before wait completion
Execution Logs
Creates execution log with step name: ‘wait$#name`
-
Stores target end time in metadata as “wait_until”
-
Tracks attempt count and execution times
-
Marks as completed when wait period has elapsed
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/chrono_forge/executor/methods/wait.rb', line 75 def wait(duration, name) step_name = "wait$#{name}" # Find or create execution log execution_log = ExecutionLog.create_or_find_by!( workflow: @workflow, step_name: step_name ) do |log| log.started_at = Time.current log. = { wait_until: duration.from_now } end # Return if already completed return if execution_log.completed? # Check if wait period has passed if Time.current >= Time.parse(execution_log.["wait_until"]) execution_log.update!( attempts: execution_log.attempts + 1, state: :completed, completed_at: Time.current, last_executed_at: Time.current ) return end execution_log.update!( attempts: execution_log.attempts + 1, last_executed_at: Time.current ) # Reschedule the job self.class .set(wait: duration) .perform_later(@workflow.key) # Halt current execution halt_execution! end |