class Dry::Effects::Frame
Stack
frame
@api private
Public Class Methods
spawn_fiber(stack) { || ... }
click to toggle source
Spawn a new fiber with a stack of effect handlers
@param [Stack] stack @api private
# File lib/dry/effects/frame.rb, line 36 def spawn_fiber(stack) fiber = ::Fiber.new do self.stack = stack yield end result = fiber.resume loop do error = false break result unless fiber.alive? provided = stack.(result) do ::Dry::Effects.yield(result) do |_, e| error = true e end end result = if error raise_in_fiber(fiber, provided) else fiber.resume(provided) end end end
stack()
click to toggle source
Accessing current stack of effect handlers. It is inherently thread/fiber-local.
@return [Stack] @api private
# File lib/dry/effects/frame.rb, line 22 def stack ::Thread.current[:dry_effects_stack] ||= Stack.new end
stack=(stack)
click to toggle source
@param [Stack] stack @api private
# File lib/dry/effects/frame.rb, line 28 def stack=(stack) ::Thread.current[:dry_effects_stack] = stack end
Private Class Methods
raise_in_fiber(fiber, error)
click to toggle source
@api private
# File lib/dry/effects/frame.rb, line 67 def raise_in_fiber(fiber, error) fiber.raise(error) end
Public Instance Methods
call(*args, &block)
click to toggle source
Add new handler to the current stack and run the given block
@param [Array<Object>] args Handler
arguments @param [Proc] block Program to run @api private
# File lib/dry/effects/frame.rb, line 90 def call(*args, &block) stack = Frame.stack prov = provider.dup was_empty = stack.empty? prov.(*args) do if was_empty stack.push(prov) do Frame.spawn_fiber(stack, &block) end else stack.push(prov, &block) end end end