Как сделать параллельные запросы в Ruby - PullRequest
0 голосов
/ 15 марта 2020

Мой вопрос в основном таков: как я могу составить список запросов параллельно.

Представьте, что у меня есть список перевозчиков, и для каждого перевозчика мне нужно составить предложение через API, но параллельно.

Так что, если у меня есть массив из N носителей, я хочу сделать N запросов, и как только все они будут выполнены, я хочу выполнить действие или сделать что-то.

Сегодня то, что я я использую Concurrent :: Future , но ему не удалось запустить его параллельно, и только после того, как он завершит работу всех операторов, верните функцию:

    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}"

Это решение запускает запросы последовательно

Ответы [ 2 ]

0 голосов
/ 16 марта 2020

Мне кажется, проблема в том, что вы вызываете value во время итерации. Это снова делает все последовательно.

Документация гласит следующее:

Получение значения Future выполняется через #value (псевдоним: #deref) метод. Получение значения Future является потенциально блокирующей операцией. Если Future равно : отклонено , вызов #value немедленно вернет nil. Когда Future равен : выполнено , вызов #value немедленно вернет текущее значение. Когда Future равно : в ожидании , вызов #value будет блокироваться, пока Future не будет либо : отклонено или : выполнено . Значение timeout может быть передано в #value для ограничения продолжительности блокировки вызова. Если nil, звонок будет заблокирован на неопределенный срок. Если 0, звонок не будет блокироваться. Любое другое целочисленное значение или значение с плавающей точкой будет указывать максимальное количество секунд для блокировки.

Перемещение вызова value за пределы начальной итерации должно решить вашу проблему.

0 голосов
/ 15 марта 2020

Что я на самом деле сделал, это

        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)

и проблема решена! Все запросы выполняются параллельно, и только после того, как все они завершены, функция продолжает выполнять свои действия

...