Last active
February 10, 2016 03:38
-
-
Save furkanmustafa/2d9edefcaa0336ed982b to your computer and use it in GitHub Desktop.
Sample Asynchronous action code for rails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# FROM: http://www.jonb.org/2013/01/25/async-rails.html @jbaudanza | |
# Modified to get it working. | |
module AsyncController | |
# This is the rack endpoint that will be invoked asyncronously. It will be | |
# wrapped in all the middleware that a normal Rails endpoint would have. | |
class RackEndpoint | |
attr_accessor :action | |
def call(env) | |
@action.call(env) | |
end | |
end | |
module ClassMethods | |
def prepareAsyncMiddleware! | |
@endpoint = RackEndpoint.new | |
# LocalCache isn't able to be instantiated twice, so it must be removed | |
# from the new middleware stack. | |
middlewares = Rails.application.middleware.middlewares.reject do |m| | |
reject = false | |
reject = true if m.klass.name == "ActiveSupport::Cache::Strategy::LocalCache" | |
reject | |
end | |
@wrapped_endpoint = middlewares.reverse.inject(@endpoint) do |a, e| | |
e.build(a) | |
end | |
end | |
def asyncMiddleware=(newM) | |
@wrapped_endpoint = newM | |
end | |
def asyncMiddleware | |
@wrapped_endpoint | |
end | |
def asyncActionEndpoint | |
@endpoint | |
end | |
def asyncActionEndpoint=(newAE) | |
@endpoint = newAE | |
end | |
end | |
def self.included(mod) | |
mod.extend(ClassMethods) | |
mod.prepareAsyncMiddleware! | |
end | |
# Called to finish an asynchronous request. Can be invoked with a block | |
# or with the symbol of an action name. | |
def finish_request(action_name=nil, &proc) | |
async_callback = request.env.delete('async.callback') | |
env = request.env.clone | |
if !action_name | |
env['async_controller.proc'] = proc | |
action_name = :_async_action | |
end | |
self.class.asyncActionEndpoint.action = self.class.action(action_name) | |
begin | |
async_callback.call(self.class.asyncMiddleware.call(env)) | |
rescue Exception => e | |
# TODO: Should return a crash response | |
puts "CRASHED!".white.on_red | |
puts e.inspect | |
end | |
end | |
def _async_action | |
instance_eval(&request.env['async_controller.proc']) | |
end | |
def async! | |
render :text => "", :status => -1 | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# FROM: http://www.jonb.org/2013/01/25/async-rails.html @jbaudanza | |
# Modified to get it working. | |
class TestController < ActionController::Base | |
include AsyncController | |
def bulkdata | |
_since = DateTime.strptime(params[:from], '%s') | |
_until = DateTime.strptime(params[:to], '%s') | |
Thread.new do | |
sleep 30 | |
finish_request do | |
render text: "This response has responded 30 seconds later, but the server doesn't get blocked." | |
end | |
end | |
async! | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment