简体   繁体   中英

How to make parallel requests in Ruby

My question basically is... how can I make a list of requests in parallel.

Imagine that I have a list of carriers and for each carrier I need to make a quotation through an API, but in parallel.

So if I have an array of N carriers I want to make N requests and once all of them are done I want to make an action or render something.

Today what I'm doing is using Concurrent::Future but didn't manage to make it fire in parallel and after it finishes all carriers only then return the function:

    quotations = []
    carriers.each do |carrier|
        quotationOperation = Concurrent::Future.execute { 
            quote(product, carrier) #quote makes an http request and returns the JSON
        }
        quotations.push(quotationOperation.value)
    end
    puts "🚩🚩🚩🚩 FINISHED JOB WITH #{quotations.count}"

This solutions is firing the requests sequentially

What I actually did is

        operations = []
        carriers.each do |carrier|
            quotationOperation = Concurrent::Future.new { 
                quote(product, carrier) #quote makes an http request and returns the JSON
            }
            operations.push(quotationOperation)
        end

        operations.map(&:execute)
        quotations = operations.map(&:value)

and problem solved! All requests are being fired in parallel and only once all of them finished the function continues what it's doing

The issue to me seems that you call value during iteration. This makes the whole thing sequential again.

The documentation says the following:

Retrieving the value of a Future is done through the #value (alias: #deref ) method. Obtaining the value of a Future is a potentially blocking operation. When a Future is :rejected a call to #value will return nil immediately. When a Future is :fulfilled a call to #value will immediately return the current value. When a Future is :pending a call to #value will block until the Future is either :rejected or :fulfilled . A timeout value can be passed to #value to limit how long the call will block. If nil the call will block indefinitely. If 0 the call will not block. Any other integer or float value will indicate the maximum number of seconds to block.

Moving the value call outside the initial iteration should fix your issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM