Module: GenevaDrive
- Defined in:
- lib/geneva_drive.rb,
lib/geneva_drive/version.rb,
lib/generators/geneva_drive/install/install_generator.rb
Overview
GenevaDrive provides durable workflows for Rails applications.
It offers a clean DSL for defining multi-step workflows that execute asynchronously, with strong guarantees around idempotency, concurrency control, and state management.
Defined Under Namespace
Modules: FlowControl, Generators, MigrationHelpers, TestHelpers Classes: CombinedExceptionPolicy, Engine, ExceptionPolicy, Executor, FlowControlSignal, HousekeepingJob, InvalidStateError, InvalidStateTransition, PerformStepJob, PreconditionError, StepCollection, StepConfigurationError, StepDefinition, StepExecution, StepExecutionError, StepFailedError, StepNotDefinedError, Workflow
Constant Summary collapse
- VERSION =
"0.5.0"
Class Attribute Summary collapse
-
.delete_completed_workflows_after ⇒ ActiveSupport::Duration?
How long to keep completed workflows before cleanup.
-
.enqueue_after_commit ⇒ Boolean
Whether to defer job enqueueing to after the database transaction commits.
-
.housekeeping_batch_size ⇒ Integer
Maximum number of workflows to process in a single housekeeping run.
-
.stuck_in_progress_threshold ⇒ ActiveSupport::Duration
How long a step execution can be in "in_progress" state before being considered stuck and eligible for recovery.
-
.stuck_recovery_action ⇒ Symbol
Default recovery action for stuck step executions.
-
.stuck_scheduled_threshold ⇒ ActiveSupport::Duration
How long a step execution can be past its scheduled_for time while still in "scheduled" state before being considered stuck.
Class Method Summary collapse
-
.enqueues_deferred? ⇒ Boolean
private
Returns true if job enqueueing should be deferred to after transaction commit.
-
.with_inline_enqueue { ... } ⇒ Object
Temporarily enables inline job enqueueing for the duration of the block.
Class Attribute Details
.delete_completed_workflows_after ⇒ ActiveSupport::Duration?
How long to keep completed workflows before cleanup. Set to nil to disable automatic cleanup.
55 56 57 |
# File 'lib/geneva_drive.rb', line 55 def delete_completed_workflows_after @delete_completed_workflows_after end |
.enqueue_after_commit ⇒ Boolean
Whether to defer job enqueueing to after the database transaction commits.
When true (the default in non-test environments), jobs are enqueued inside
an after_all_transactions_commit callback to ensure the step execution
record is visible to the job worker.
When false (the default in test environments), jobs are enqueued immediately. This is necessary for transactional tests (especially with SQLite) where the outermost test transaction never commits, causing after_commit callbacks to misbehave or not fire at all.
88 89 90 |
# File 'lib/geneva_drive.rb', line 88 def enqueue_after_commit @enqueue_after_commit end |
.housekeeping_batch_size ⇒ Integer
Maximum number of workflows to process in a single housekeeping run. Prevents runaway processing if there's a large backlog.
70 71 72 |
# File 'lib/geneva_drive.rb', line 70 def housekeeping_batch_size @housekeeping_batch_size end |
.stuck_in_progress_threshold ⇒ ActiveSupport::Duration
How long a step execution can be in "in_progress" state before being considered stuck and eligible for recovery.
60 61 62 |
# File 'lib/geneva_drive.rb', line 60 def stuck_in_progress_threshold @stuck_in_progress_threshold end |
.stuck_recovery_action ⇒ Symbol
Default recovery action for stuck step executions. Can be :reattempt or :cancel
75 76 77 |
# File 'lib/geneva_drive.rb', line 75 def stuck_recovery_action @stuck_recovery_action end |
.stuck_scheduled_threshold ⇒ ActiveSupport::Duration
How long a step execution can be past its scheduled_for time while still in "scheduled" state before being considered stuck.
65 66 67 |
# File 'lib/geneva_drive.rb', line 65 def stuck_scheduled_threshold @stuck_scheduled_threshold end |
Class Method Details
.enqueues_deferred? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns true if job enqueueing should be deferred to after transaction commit.
151 152 153 154 |
# File 'lib/geneva_drive.rb', line 151 def enqueues_deferred? return false if Thread.current[:geneva_drive_inline_enqueue] enqueue_after_commit end |
.with_inline_enqueue { ... } ⇒ Object
Temporarily enables inline job enqueueing for the duration of the block. Jobs will be enqueued immediately instead of waiting for transaction commit.
When to use this
This method is useful when creating multiple workflows inside a bulk
enqueueing context (e.g., BulkEnqueue.in_bulk). Normally, GenevaDrive
defers job enqueueing to after_all_transactions_commit callbacks.
However, these callbacks fire after the bulk enqueue block ends and
clears its buffer, causing jobs to be enqueued individually instead of
in bulk.
Requirements
Only use this if you have a co-committing, database-backed ActiveJob
adapter (such as SolidQueue, GoodJob, or Gouda) running on the same
database as your application models. With such adapters, the job INSERT
and the workflow/step_execution records are written in the same database
transaction, guaranteeing atomicity without needing after_commit deferral.
If you use a non-transactional queue adapter (Redis-based Sidekiq, Resque, etc.), do NOT use this method in production — jobs may be enqueued before their associated records are visible, causing "record not found" errors.
Thread safety
Uses a thread-local flag that won't affect other threads or requests. Safe to use in multi-threaded web servers (Puma, etc.).
139 140 141 142 143 144 145 |
# File 'lib/geneva_drive.rb', line 139 def with_inline_enqueue previous = Thread.current[:geneva_drive_inline_enqueue] Thread.current[:geneva_drive_inline_enqueue] = true yield ensure Thread.current[:geneva_drive_inline_enqueue] = previous end |