1# frozen_string_literal: true
2
3require "em_promise"
4
5module Rack
6 class Fiber
7 def initialize(app)
8 @app = app
9 end
10
11 def call(env)
12 async_callback = env.delete("async.callback")
13 run_fiber(env, async_callback)
14 throw :async
15 end
16
17 protected
18
19 def run_fiber(env, async_callback)
20 # Use EMPromise to get a Fiber trampoline that can be shared by
21 # other EMPromise down the stack. Also works as a normal Fiber if
22 # no one uses EMPromise.
23 EMPromise.resolve(nil).then {
24 async_callback.call(@app.call(env))
25 }.catch { |e|
26 async_callback.call([500, {}, [e.to_s]])
27 }
28 end
29 end
30end