lib/rhoconnect/async.rb in rhoconnect-3.4.5 vs lib/rhoconnect/async.rb in rhoconnect-4.0.0.beta.10

- old
+ new

@@ -7,12 +7,13 @@ def setup_sessions(builder) options = {} if settings.respond_to?(:fiberpool_size) options[:size] = settings.fiberpool_size end - options[:rescue_exception] = handle_exception + options[:rescue_exception] = handle_exception builder.use Rack::FiberPool, options unless test? + builder.use Rhoconnect::Middleware::Async, options super end def handle_exception Proc.new do |env, e| @@ -26,58 +27,94 @@ end end end end - module AsyncHelpers - def self.included(klass) - (klass.instance_methods & self.instance_methods).each do |method| - klass.instance_eval{remove_method method.to_sym} + module Middleware + class Async + def initialize(app, opts={}) + @app = app + yield self if block_given? end - end - - def catch_all - res = nil - begin - res = catch(:halt) { yield } - rescue ApiException => ae - res = [ae.error_code, ae.message] - rescue Exception => e - log e.message + e.backtrace.join("\n") - res = [500, e.message] - end - res - end - - def execute_api_call(client_call = false) + + def call(env) f = Fiber.current + # making a copy is crucial here + # otherwise 'env' will not be the same + # in the deferred execution + aenv = env.dup operation = proc { - self.request.env['REQUEST_THREAD'] = Thread.current - if(request.env['RHO_ABORT_PROCESS']) + res = nil + aenv['REQUEST_THREAD'] = Thread.current + if(aenv['RHO_ABORT_PROCESS']) res = [500, 'Request is aborted'] else - catch_all do - res = yield params, current_user, self - if params.has_key? :warning - Rhoconnect.log params[:warning] - response.headers['Warning'] = params[:warning] - end - res - end + res = @app.call(aenv) end + res } result = nil callback = proc { |proc_res| result = proc_res; f.resume } - + EventMachine.defer operation, callback Fiber.yield - # we can not throw exceptions across threads - # so we analyze it in the main thread after the - # request has been processed and if result - # has error code - then we throw :halt here - if Array === result and Fixnum === result.first - throw :halt, result - end result + end end end + +# module AsyncHelpers +# #def self.included(klass) +# # (klass.instance_methods & self.instance_methods).each do |method| +# # klass.instance_eval{remove_method method.to_sym} +# # end +# #end +# +# def catch_all +# res = nil +# begin +# res = catch(:halt) { yield } +# rescue ApiException => ae +# res = [ae.error_code, ae.message] +# rescue Exception => e +# log e.message + e.backtrace.join("\n") +# res = [500, e.message] +# end +# res +# end +# +# def execute_api_call(&block) +# f = Fiber.current +# operation = proc { +# catch_all do +# puts " we are processing the route #{self.inspect}" +# method = self.class.send(:generate_method, "calling_method", &block) +# #method = instance_method "calling_method" +# #remove_method "calling_method" +# +# #method = Sinatra::Base.generate_method("calling_method", &block) +# proc = method.bind(self) +# res = proc.call +# #res = yield +# if params.has_key? :warning +# Rhoconnect.log params[:warning] +# response.headers['Warning'] = params[:warning] +# end +# res +# end +# } +# result = nil +# callback = proc { |proc_res| result = proc_res; f.resume } +# +# EventMachine.defer operation, callback +# Fiber.yield +# # we can not throw exceptions across threads +# # so we analyze it in the main thread after the +# # request has been processed and if result +# # has error code - then we throw :halt here +# if Array === result and Fixnum === result.first +# throw :halt, result +# end +# result +# end +# end end \ No newline at end of file