From 67dea5196813ea4a3c04d7143c45556bd7281dc7 Mon Sep 17 00:00:00 2001 From: Mattia Giuffrida Date: Wed, 21 Aug 2024 13:38:56 +0100 Subject: [PATCH] Add support for a new `ParallelManager#execute` method. The new interface passes the parallel block with all the requests to the ParallelManager, instead of running it beforehand. This allows for better, stateless ParallelManager implementations. Fixes https://github.com/lostisland/faraday/issues/1583 --- .rubocop_todo.yml | 2 +- docs/adapters/custom/parallel-requests.md | 30 +++++++++++++++++------ lib/faraday/connection.rb | 14 ++++++++--- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 9b7e255db..f3d0f2e80 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -31,7 +31,7 @@ Metrics/AbcSize: # Offense count: 3 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 225 + Max: 230 # Offense count: 9 # Configuration parameters: AllowedMethods, AllowedPatterns. diff --git a/docs/adapters/custom/parallel-requests.md b/docs/adapters/custom/parallel-requests.md index 8431dc3f0..b7d64b31e 100644 --- a/docs/adapters/custom/parallel-requests.md +++ b/docs/adapters/custom/parallel-requests.md @@ -42,18 +42,34 @@ class FlorpHttp < ::Faraday::Adapter def self.setup_parallel_manager(_options = nil) FlorpParallelManager.new # NB: we will need to define this end -end -class FlorpParallelManager - def add(request, method, *args, &block) - # Collect the requests + def call(env) + # NB: you can call `in_parallel?` here to check if the current request + # is part of a parallel batch. Useful if you need to collect all requests + # into the ParallelManager before running them. end +end - def run - # Process the requests +class FlorpParallelManager + # The execute method will be passed the same block as `in_parallel`, + # so you can either collect the requests or just wrap them into a wrapper, + # depending on how your adapter works. + def execute(&block) + run_async(&block) end end ``` -Compare to the finished example [em-synchrony](https://github.com/lostisland/faraday-em_synchrony/blob/main/lib/faraday/adapter/em_synchrony.rb) +### A note on the old, deprecated interface + +Prior to the introduction of the `execute` method, the `ParallelManager` was expected to implement a `run` method +and the execution of the block was done by the Faraday connection BEFORE calling that method. + +This approach made the `ParallelManager` implementation harder and keeping the state required. +The new `execute` implementation allows to avoid this shortfall and support different flows. + +As of Faraday 2.0, `run` is still supported in case `execute` is not implemented by the `ParallelManager`, +but this method should be considered deprecated. + +For reference, please see an example using `run` from [em-synchrony](https://github.com/lostisland/faraday-em_synchrony/blob/main/lib/faraday/adapter/em_synchrony.rb) and its [ParallelManager implementation](https://github.com/lostisland/faraday-em_synchrony/blob/main/lib/faraday/adapter/em_synchrony/parallel_manager.rb). diff --git a/lib/faraday/connection.rb b/lib/faraday/connection.rb index e979e8282..543cd4bb0 100644 --- a/lib/faraday/connection.rb +++ b/lib/faraday/connection.rb @@ -314,15 +314,23 @@ def in_parallel? # # @yield a block to execute multiple requests. # @return [void] - def in_parallel(manager = nil) + def in_parallel(manager = nil, &block) @parallel_manager = manager || default_parallel_manager do warn 'Warning: `in_parallel` called but no parallel-capable adapter ' \ 'on Faraday stack' warn caller[2, 10].join("\n") nil end - yield - @parallel_manager&.run + return yield unless @parallel_manager + + if @parallel_manager.respond_to?(:execute) + # Execute is the new method that is responsible for executing the block. + @parallel_manager.execute(&block) + else + # TODO: Old behaviour, deprecate and remove in 3.0 + yield + @parallel_manager.run + end ensure @parallel_manager = nil end