class MakeRequest
include HTTParty
include Dry::Monads[:result, :try]
include Dry::Effects.Timeout(:http)
def call(url)
if timed_out?
Failure(:timeout)
else
Try[Net::ReadTimeout, Net::OpenTimeout, Net::WriteTimeout] {
self.class.get(url, timeout: timeout)
}.to_result.discard
end
end
end
request = MakeRequest.new
with_timeout = Object.new.extend(Dry::Effects::Handler.Timeout(:http, as: :call))
with_timeout.(1.0) { Array.new(5) { make_request.('http://httpstat.us/200?sleep=300') } }
# => => [Success(), Failure(#<Net::ReadTimeout: Net::ReadTimeout>), Failure(:timeout), Failure(:timeout), Failure(:timeout)]
It's already cool since it decouples time-to-process of your application from the intermediate code you have. But we can make even cooler by running it in parallel:
with_parallel = Object.new.extend(Dry::Effects::Handler.Parallel(as: :call))
extend Dry::Effects.Parallel
with_timeout.(1.0) do
with_parallel.() do
join(Array.new(5) { par { make_request.('http://httpstat.us/200?sleep=300') } } )
end
end
# => [Success(), Success(), Success(), Success(), Success()]
đŸ‘† You can see how timeout is shared across different "threads". It requires 0 glue code on the dry-effects side.
Another perfect example of using effects:
It's already cool since it decouples time-to-process of your application from the intermediate code you have. But we can make even cooler by running it in parallel:
đŸ‘† You can see how timeout is shared across different "threads". It requires 0 glue code on the dry-effects side.