Skip to content

Commit

Permalink
Merge pull request #654 from davishmcclurg/davishmcclurg/promise-zip
Browse files Browse the repository at this point in the history
Promise.zip execution changes
  • Loading branch information
pitr-ch committed Feb 24, 2018
2 parents 50ed4a5 + 0559cba commit 705325e
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 3 deletions.
26 changes: 23 additions & 3 deletions lib/concurrent/promise.rb
Expand Up @@ -383,11 +383,24 @@ def flat_map(&block)
# Builds a promise that produces the result of promises in an Array
# and fails if any of them fails.
#
# @param [Array<Promise>] promises
# @overload zip(*promises)
# @param [Array<Promise>] promises
#
# @overload zip(*promises, opts)
# @param [Array<Promise>] promises
# @param [Hash] opts the configuration options
# @option opts [Executor] :executor (ImmediateExecutor.new) when set use the given `Executor` instance.
# @option opts [Boolean] :execute (true) execute promise before returning
#
# @return [Promise<Array>]
def self.zip(*promises)
zero = fulfill([], executor: ImmediateExecutor.new)
opts = promises.last.is_a?(::Hash) ? promises.pop.dup : {}
opts[:executor] ||= ImmediateExecutor.new
zero = if !opts.key?(:execute) || opts.delete(:execute)
fulfill([], opts)
else
Promise.new(opts) { [] }
end

promises.reduce(zero) do |p1, p2|
p1.flat_map do |results|
Expand All @@ -401,7 +414,14 @@ def self.zip(*promises)
# Builds a promise that produces the result of self and others in an Array
# and fails if any of them fails.
#
# @param [Array<Promise>] others
# @overload zip(*promises)
# @param [Array<Promise>] others
#
# @overload zip(*promises, opts)
# @param [Array<Promise>] others
# @param [Hash] opts the configuration options
# @option opts [Executor] :executor (ImmediateExecutor.new) when set use the given `Executor` instance.
# @option opts [Boolean] :execute (true) execute promise before returning
#
# @return [Promise<Array>]
def zip(*others)
Expand Down
52 changes: 52 additions & 0 deletions spec/concurrent/promise_spec.rb
Expand Up @@ -357,6 +357,32 @@ def get_ivar_from_args(opts)
let(:promise2) { Promise.new(executor: :immediate) { 2 } }
let(:promise3) { Promise.new(executor: :immediate) { [3] } }

it 'executes the returned Promise by default' do
composite = promise1.zip(promise2, promise3)

expect(composite).to be_fulfilled
end

it 'executes the returned Promise when execute is true' do
composite = promise1.zip(promise2, promise3, execute: true)

expect(composite).to be_fulfilled
end

it 'does not execute the returned Promise when execute is false' do
composite = promise1.zip(promise2, promise3, execute: false)

expect(composite).to be_unscheduled
end

it 'allows setting executor for Promise chain' do
new_executor = Concurrent::SingleThreadExecutor.new
promise = promise1.zip(promise2, promise3, executor: new_executor)

promise = promise.instance_variable_get(:@parent) until promise.send(:root?)
expect(promise.instance_variable_get(:@executor)).to be(new_executor)
end

it 'yields the results as an array' do
composite = promise1.zip(promise2, promise3).execute.wait

Expand All @@ -375,6 +401,32 @@ def get_ivar_from_args(opts)
let(:promise2) { Promise.new(executor: :immediate) { 2 } }
let(:promise3) { Promise.new(executor: :immediate) { [3] } }

it 'executes the returned Promise by default' do
composite = Promise.zip(promise1, promise2, promise3)

expect(composite).to be_fulfilled
end

it 'executes the returned Promise when execute is true' do
composite = Promise.zip(promise1, promise2, promise3, execute: true)

expect(composite).to be_fulfilled
end

it 'does not execute the returned Promise when execute is false' do
composite = Promise.zip(promise1, promise2, promise3, execute: false)

expect(composite).to be_unscheduled
end

it 'allows setting executor for Promise chain' do
new_executor = Concurrent::SingleThreadExecutor.new
promise = Promise.zip(promise1, promise2, promise3, executor: new_executor)

promise = promise.instance_variable_get(:@parent) until promise.send(:root?)
expect(promise.instance_variable_get(:@executor)).to be(new_executor)
end

it 'yields the results as an array' do
composite = Promise.zip(promise1, promise2, promise3).execute.wait

Expand Down

0 comments on commit 705325e

Please sign in to comment.