module DeferrableGratification::Combinators::ClassMethods
Combinators
which don’t make sense as methods on Deferrable
.
{DeferrableGratification} extends this module, and thus the methods here are accessible via the {DG} alias.
Public Instance Methods
Execute a sequence of asynchronous operations that may each depend on the result of the previous operation.
@see bind! more detail on the semantics.
@param [*Proc] *actions procs that will perform an operation and
return a Deferrable.
@return [Deferrable] Deferrable that will succeed if all of the
chained operations succeeded, and callback with the result of the last operation.
# File lib/deferrable_gratification/combinators.rb, line 241 def chain(*actions) actions.inject(DG.const(nil), &:>>) end
Combinator that waits for any of the supplied asynchronous operations to succeed, and succeeds with the result of the first (chronologically) to do so.
This Deferrable will fail if all the operations fail. It may never succeed or fail, if one of the operations also does not.
@param (see join_successes
)
@return [Deferrable] a deferred status that will succeed as soon as any
of the +operations+ succeeds; its callbacks will be passed the result of that operation.
# File lib/deferrable_gratification/combinators.rb, line 279 def join_first_success(*operations) Join::FirstSuccess.setup!(*operations) end
Combinator that waits for all of the supplied asynchronous operations to succeed or fail, then succeeds with the results of all those operations that were successful.
This Deferrable will never fail. It may also never succeed, if any of the supplied operations does not either succeed or fail.
The successful results are guaranteed to be in the same order as the operations were passed in (which may not be the same as the chronological order in which they succeeded).
@param [*Deferrable] *operations deferred statuses of asynchronous
operations to wait for.
@return [Deferrable] a deferred status that will succeed after all the
+operations+ have either succeeded or failed; its callbacks will be passed an +Enumerable+ containing the results of those operations that succeeded.
# File lib/deferrable_gratification/combinators.rb, line 263 def join_successes(*operations) Join::Successes.setup!(*operations) end
Combinator that repeatedly executes the supplied block until it succeeds, then succeeds itself with the eventual result.
This Deferrable may never succeed, if the operation never succeeds. It will fail if an iteration raises an exception.
@note this combinator is intended for use inside EventMachine. It will
still work outside of EventMachine, _provided_ that the operation is synchronous (although a simple +while+ loop might be preferable in this case!).
@param loop_deferrable for internal use only, always omit this. @param &block operation to execute until it succeeds.
@yieldreturn [Deferrable] deferred status of the operation. If it
fails, the operation will be retried. If it succeeds, the combinator will succeed with the result.
@return [Deferrable] a deferred status that will succeed once the
supplied operation eventually succeeds.
# File lib/deferrable_gratification/combinators.rb, line 303 def loop_until_success(loop_deferrable = DefaultDeferrable.new, &block) if EM.reactor_running? EM.next_tick do begin attempt = yield rescue => e loop_deferrable.fail(e) else attempt.callback(&loop_deferrable.method(:succeed)) attempt.errback { loop_until_success(loop_deferrable, &block) } end end else # In the synchronous case, we could simply use the same # implementation as in EM, but without the next_tick; unfortunately # that means direct recursion, so risks stack overflow. Instead we # just reimplement as a loop. results = [] begin yield.callback {|*values| results << values } while results.empty? rescue => e loop_deferrable.fail(e) else loop_deferrable.succeed(*results[0]) end end loop_deferrable end