Class: RailsAiBridge::Introspector::ParallelRunner
- Inherits:
-
Object
- Object
- RailsAiBridge::Introspector::ParallelRunner
- Defined in:
- lib/rails_ai_bridge/introspector/parallel_runner.rb
Overview
Runs multiple introspectors concurrently using a fixed thread pool.
Requires +concurrent-ruby+ (already a transitive dependency of Rails). Falls back gracefully when the gem is unavailable — callers should check ParallelRunner.available? before using this runner.
Pool size and per-future timeout are driven by Configuration (+parallel_pool_size+ and +parallel_timeout_seconds+), so hosts can tune concurrency without touching this class.
Each introspector is executed in its own future. Errors — including per-future timeouts — are captured per-introspector and returned as +{ error: message }+ hashes, matching the convention used throughout #call.
Class Method Summary collapse
-
.available? ⇒ Boolean
Returns +true+ when parallel execution is safe to use.
-
.call(introspectors, app) ⇒ Hash{Symbol => Object}
Runs +introspectors+ concurrently and returns a Hash of results.
Class Method Details
.available? ⇒ Boolean
Returns +true+ when parallel execution is safe to use.
Parallel execution is considered unsafe when:
- +concurrent-ruby+ is not loaded (+Concurrent::Future+ is undefined)
- ActiveRecord's connection pool has only one slot (common in transactional tests or SQLite single-connection setups)
63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/rails_ai_bridge/introspector/parallel_runner.rb', line 63 def available? return false unless defined?(Concurrent::Future) == 'constant' if defined?(ActiveRecord::Base) pool_size = begin ActiveRecord::Base.connection_pool.size rescue StandardError nil end return false if pool_size && pool_size <= 1 end true end |
.call(introspectors, app) ⇒ Hash{Symbol => Object}
Runs +introspectors+ concurrently and returns a Hash of results.
The number of threads is +min(introspectors.size, parallel_pool_size)+. Each future is given +parallel_timeout_seconds+ to complete; if it exceeds the timeout the result is +{ error: "timed out after Ns" }+.
The thread pool is always shut down in an +ensure+ block, even if an unexpected exception escapes.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/rails_ai_bridge/introspector/parallel_runner.rb', line 39 def call(introspectors, app) return {} if introspectors.empty? cfg = RailsAiBridge.configuration size = [introspectors.size, cfg.parallel_pool_size].min timeout = cfg.parallel_timeout_seconds pool = Concurrent::FixedThreadPool.new(size) futures = schedule_futures(introspectors, app, pool) collect_results(futures, timeout) ensure if pool pool.shutdown pool.kill unless pool.wait_for_termination(timeout || 10) end end |