Class: RubyReactor::Configuration

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/ruby_reactor/configuration.rb

Overview

Configuration class for RubyReactor settings

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#async_routerObject



106
107
108
# File 'lib/ruby_reactor/configuration.rb', line 106

def async_router
  @async_router ||= RubyReactor::SidekiqAdapter
end

#checkpoint_min_intervalObject

Minimum wall-clock seconds between two PER-STEP durable checkpoints within a single worker run. The save-per-step checkpoint (‘on_step_complete`) bounds crash re-execution to one step, but re-serializes and re-writes the WHOLE root blob after every Success — O(steps × context_size) writes for a long, large reactor. This throttle coalesces the mid-run intermediate checkpoints: a checkpoint is written only if at least this many seconds have elapsed since the last one. The final terminal/handoff state is ALWAYS persisted (by the run’s ensure-save and the pre-enqueue checkpoint), so throttling only affects mid-run granularity. Tradeoff: with interval > 0, a crash may re-run every step completed inside the last interval — safe only when those steps are idempotent or side-effect-free.

Default 0 -> checkpoint after EVERY step (strongest guarantee, no coalescing).



39
40
41
# File 'lib/ruby_reactor/configuration.rb', line 39

def checkpoint_min_interval
  @checkpoint_min_interval ||= 0
end

#context_lock_ttlObject

TTL (seconds) for the per-context liveness lock (‘async:<id>`). Short by design — it is a liveness signal, not retention. A live worker auto-extends it (every ttl/3 s, from a background thread); its absence is the sweeper’s “worker died” signal.

SAFETY CONSTRAINT: this MUST exceed the longest a single step can run WITHOUT letting the auto-extend thread make progress. Under MRI the extender shares the GIL, so a step that holds the GIL continuously for longer than this TTL (a long CPU-bound pure-Ruby loop, a C extension that never releases the GIL, or a stop-the-world GC pause) lets the lock lapse. A lapsed lock looks “dead” to the sweeper, which may re-enqueue a duplicate that runs CONCURRENTLY with the still-live original — a double-run. I/O-bound steps release the GIL and keep the lock fresh, so the default 60s suits typical workloads; raise it if you run long synchronous CPU-bound steps.



78
79
80
# File 'lib/ruby_reactor/configuration.rb', line 78

def context_lock_ttl
  @context_lock_ttl ||= 60
end

#context_ttlObject

Retention TTL (seconds) for a stored reactor context. Storage is load-bearing for resume, so this must comfortably exceed the worst-case snooze/retry window. Refreshed on every checkpoint write.



22
23
24
# File 'lib/ruby_reactor/configuration.rb', line 22

def context_ttl
  @context_ttl ||= 86_400
end

#lock_snooze_base_delayObject

Base seconds the Sidekiq worker waits before re-checking a contended lock.



87
88
89
# File 'lib/ruby_reactor/configuration.rb', line 87

def lock_snooze_base_delay
  @lock_snooze_base_delay ||= 5
end

#lock_snooze_jitterObject

Extra random seconds added to the base delay to avoid thundering herd.



92
93
94
# File 'lib/ruby_reactor/configuration.rb', line 92

def lock_snooze_jitter
  @lock_snooze_jitter ||= 5
end

#lock_snooze_max_attemptsObject

How many times a single job can snooze on lock contention before it is marked as failed. Set to :infinity to never escalate.



98
99
100
# File 'lib/ruby_reactor/configuration.rb', line 98

def lock_snooze_max_attempts
  @lock_snooze_max_attempts ||= 20
end

#loggerObject



102
103
104
# File 'lib/ruby_reactor/configuration.rb', line 102

def logger
  @logger ||= Logger.new($stdout)
end

#middlewaresObject



123
124
125
# File 'lib/ruby_reactor/configuration.rb', line 123

def middlewares
  @middlewares ||= []
end

#sidekiq_queueObject



15
16
17
# File 'lib/ruby_reactor/configuration.rb', line 15

def sidekiq_queue
  @sidekiq_queue ||= :default
end

#sidekiq_retry_countObject



82
83
84
# File 'lib/ruby_reactor/configuration.rb', line 82

def sidekiq_retry_count
  @sidekiq_retry_count ||= 3
end

#sweeper_enabledObject

Whether the recovery sweepers run. The host kicks the self-rescheduling chain once (‘RubyReactor.start_sweeper!`, e.g. from an initializer); each tick re-checks this flag, so flipping it to false stops the chain at the next tick. Default on: durability is inert without a running sweeper, so recovery must work out of the box.



48
49
50
51
# File 'lib/ruby_reactor/configuration.rb', line 48

def sweeper_enabled
  @sweeper_enabled = true if @sweeper_enabled.nil?
  @sweeper_enabled
end

#sweeper_intervalObject

Seconds between sweeps. This is the upper bound on recovery latency for a dead worker — lower it for faster recovery, raise it to cut scan load.



55
56
57
# File 'lib/ruby_reactor/configuration.rb', line 55

def sweeper_interval
  @sweeper_interval ||= 30
end

#sweeper_limitObject

Max contexts/maps inspected per sweep (passed to each sweeper’s run_once).



60
61
62
# File 'lib/ruby_reactor/configuration.rb', line 60

def sweeper_limit
  @sweeper_limit ||= 1000
end

Instance Method Details

#rate_limitsObject

Registry of named rate limits shared across reactors. Configure entries with ‘config.rate_limits.register(:name, …)` and reference them from a reactor via `with_rate_limit(:name)`.



130
131
132
# File 'lib/ruby_reactor/configuration.rb', line 130

def rate_limits
  @rate_limits ||= RubyReactor::RateLimitRegistry.new
end

#storageObject



110
111
112
# File 'lib/ruby_reactor/configuration.rb', line 110

def storage
  @storage ||= RubyReactor::Storage::Configuration.new
end

#storage_adapterObject



114
115
116
117
118
119
120
121
# File 'lib/ruby_reactor/configuration.rb', line 114

def storage_adapter
  @storage_adapter ||= case storage.adapter
                       when :redis
                         RubyReactor::Storage::RedisAdapter.new(url: storage.redis_url, **storage.redis_options)
                       else
                         raise "Unknown storage adapter: #{storage.adapter}"
                       end
end