Skip to content

Commit

Permalink
Add support for a new ParallelManager#execute method.
Browse files Browse the repository at this point in the history
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 #1583
  • Loading branch information
iMacTia committed Aug 21, 2024
1 parent 3efc0a8 commit 67dea51
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
30 changes: 23 additions & 7 deletions docs/adapters/custom/parallel-requests.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
14 changes: 11 additions & 3 deletions lib/faraday/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 67dea51

Please sign in to comment.