lib/circuitry/concerns/async.rb
require 'circuitry/processors/batcher'
require 'circuitry/processors/forker'
require 'circuitry/processors/threader'
module Circuitry
class NotSupportedError < StandardError; end
module Concerns
module Async
attr_reader :async
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def async_strategies
[:fork, :thread, :batch]
end
def default_async_strategy
raise NotImplementedError, "#{name} must implement class method `default_async_strategy`"
end
end
def process_asynchronously(&block)
send(:"process_via_#{async}", &block)
end
def async=(value)
value = case value
when false, nil then false
when true then self.class.default_async_strategy
when *self.class.async_strategies then value
else raise ArgumentError, async_value_error(value)
end
if value == :fork && !platform_supports_forking?
raise NotSupportedError, 'Your platform does not support forking'
end
@async = value
end
def async?
![nil, false].include?(async)
end
private
def async_value_error(value)
options = [true, false].concat(self.class.async_strategies).inspect
"Invalid value `#{value.inspect}`, must be one of #{options}"
end
def platform_supports_forking?
Process.respond_to?(:fork)
end
def process_via_fork(&block)
Processors::Forker.process(&block)
end
def process_via_thread(&block)
Processors::Threader.process(&block)
end
def process_via_batch(&block)
Processors::Batcher.process(&block)
end
end
end
end