Module: Sinatra::Async::Helpers

Defined in:
lib/sinatra/async.rb

Instance Method Summary collapse

Instance Method Details

#ahalt(*args) ⇒ Object

Asynchronous halt must be used when the halt is occuring outside of the original call stack.



145
146
147
148
149
# File 'lib/sinatra/async.rb', line 145

def ahalt(*args)
  invoke { halt(*args) }
  invoke { error_block! response.status }
  body response.body
end

#async_catch_execute(&b) ⇒ Object



118
119
120
121
122
123
124
125
126
127
# File 'lib/sinatra/async.rb', line 118

def async_catch_execute(&b)
  @async_running = true
  async_handle_exception do
    if h = catch(:halt, &b)
      invoke { halt h }
      invoke { error_block! response.status }
      body(response.body)
    end
  end
end

#async_handle_exceptionObject



129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/sinatra/async.rb', line 129

def async_handle_exception
  yield
rescue ::Exception => boom
  if settings.show_exceptions?
    printer = Sinatra::ShowExceptions.new(proc{ raise boom })
    s, h, b = printer.call(request.env)
    response.status = s
    response.headers.replace(h)
    response.body = b
  else
    body(handle_exception!(boom))
  end
end

#async_responseObject

Defaults to throw async as that is most commonly used by servers.



110
111
112
# File 'lib/sinatra/async.rb', line 110

def async_response
  throw :async
end

#async_runner(method, *bargs) ⇒ Object



114
115
116
# File 'lib/sinatra/async.rb', line 114

def async_runner(method, *bargs)
  async_schedule { __send__(method, *bargs); nil }
end

#async_schedule(&b) ⇒ Object

async_schedule is used to schedule work in a future context, the block is wrapped up so that exceptions and halts (redirect, etc) are handled correctly.



93
94
95
96
97
98
99
100
# File 'lib/sinatra/async.rb', line 93

def async_schedule(&b)
  if settings.environment == :test
    settings.set :async_schedules, [] unless settings.respond_to? :async_schedules
    settings.async_schedules << lambda { async_catch_execute(&b) }
  else
    native_async_schedule { async_catch_execute(&b) }
  end
end

#body(*args) ⇒ Object

Send the given body or block as the final response to the asynchronous request.



76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/sinatra/async.rb', line 76

def body(*args)
  if @async_running
    block_given? ? async_handle_exception { super(yield) } : super
    if response.body.respond_to?(:call)
      response.body = Array(async_handle_exception {response.body.call})
    end
    request.env['async.callback'][
      [response.status, response.headers, response.body]
    ]
  else
    super
  end
end

#native_async_schedule(&b) ⇒ Object

By default native_async_schedule calls EventMachine#next_tick, if you’re using threads or some other scheduling mechanism, it must take the block passed here and schedule it for running in the future.



105
106
107
# File 'lib/sinatra/async.rb', line 105

def native_async_schedule(&b)
  EM.next_tick(&b)
end

#on_close(&blk) ⇒ Object

The given block will be executed if the user closes the connection prematurely (before we’ve sent a response). This is good for deregistering callbacks that would otherwise send the body (for example channel subscriptions).



155
156
157
# File 'lib/sinatra/async.rb', line 155

def on_close(&blk)
  env['async.close'].callback(&blk)
end