Module: Abstractivator::FiberDefer
- Defined in:
- lib/abstractivator/fiber_defer.rb
Overview
Provides a pair of functions for handling long-running requests in a thread pool. Uses fibers to maintain a somewhat normal coding style (hides explicit continuations). with_fiber_defer defines the lexical scope of all work being done. fiber_defer defines the portion of the work to be done in the worker thread. Control passes from the calling thread, to the worker thread, and back to the calling thread. The code is capable of propagating thread variables (e.g., Mongoid::Threaded.database_override) across these thread/fiber transitions. See EventMachine::defer for more information.
Constant Summary collapse
- ROOT_FIBER =
Fiber.current
Instance Method Summary collapse
- #fiber_defer(thread_var_guard = nil, &action) ⇒ Object
- #mongoid_fiber_defer(&action) ⇒ Object
- #with_fiber_defer(thread_var_guard = nil, &block) ⇒ Object
Instance Method Details
#fiber_defer(thread_var_guard = nil, &action) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/abstractivator/fiber_defer.rb', line 40 def fiber_defer(thread_var_guard=nil, &action) # we start out in the caller thread inherited_guard_proc = Thread.current[:fiber_defer_guard_proc] raise 'fiber_defer cannot be nested within fiber_defer' if Thread.current[:inside_fiber_defer] raise 'fiber_defer must be called within a with_fiber_defer block' unless inherited_guard_proc raise 'fiber_defer must be passed an action to defer (the block)' unless action local_guard_proc = make_guard_proc(thread_var_guard) guard_proc = proc do inherited_guard_proc.call local_guard_proc.call end begin basic_fiber_defer do # in the background thread now begin Thread.current[:inside_fiber_defer] = true guard_proc.call action.call ensure Thread.current[:inside_fiber_defer] = false end end ensure # back in the caller thread guard_proc.call end end |
#mongoid_fiber_defer(&action) ⇒ Object
68 69 70 71 72 73 |
# File 'lib/abstractivator/fiber_defer.rb', line 68 def mongoid_fiber_defer(&action) thread_vars = { Mongoid::Threaded.database_override => proc { |db| Mongoid.override_database(db) } } fiber_defer(thread_vars, &action) end |
#with_fiber_defer(thread_var_guard = nil, &block) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/abstractivator/fiber_defer.rb', line 22 def with_fiber_defer(thread_var_guard=nil, &block) raise 'this method requires an eventmachine reactor to be running' unless EM.reactor_running? raise 'with_fiber_defer cannot be nested within with_fiber_defer' if Thread.current[:fiber_defer_guard_proc] raise 'with_fiber_defer cannot be nested within fiber_defer' if Thread.current[:inside_fiber_defer] return unless block guard_proc = make_guard_proc(thread_var_guard) f = Fiber.new do guard_proc.call begin Thread.current[:fiber_defer_guard_proc] = guard_proc # make available to fiber_defer calls block.call ensure Thread.current[:fiber_defer_guard_proc] = nil end end f.resume end |