Background workers see connection in rails application

Suppose I have an application for a blog with messages. After creating a message, a worker is created to handle some background operations. My thing is that after sending the message form, I want to display some kind of boot message (gif-loader or one), and when the worker finishes, I want to hide the downloaded message and display some data provided by the employee. My question is the best way to report that the worker has finished his work and displayed it on the user interface. The worker callback looks something like this.

def worker_finish #message the user end 
+6
source share
1 answer

I think you may not have noticed that you have background workers, basically what you are trying to do is defeat yourself. - If the user submits the form and you queue the task in your controller, only so that the user waits until the employee starts and finishes, you will not only achieve what the controller could do, but also make the process much more complicated (and this type of functionality does not built into neither resque nor sidekiq).

When unloading a task that will be processed in a queue, you want to immediately return a response to the client, i.e.

 class PostsController < ApplicationController def create @post = Post.create(params[:post]) BackgroundBlogOperation.enque(@post.id) respond_with(@post) end end 

The BackgroundBlogOperation class will then be queued for the worker to go through and work. If you need a working BackgroundBlogOperation to do something else after its completion, you can do it, but this must happen in the work itself so that the worker can be held responsible.

If you are just trying to display and hide the counter after creating the message, without reloading the page, just show the javascript counter before clicking the submit button and make sure the request type is js (add: remote => true to form). Then create a javascript-like response that looks like this:

 class PostsController < ApplicationController respond_to :js, :only => [:create] def create @post = Post.create(params[:post]) BackgroundBlogOperation.enque(@post.id) respond_with(@post) end end 

And create.js.erb can also add a message telling them that everything you do in the background is queued if it is more complex than creating a message or something else.

 $("#spinner").hide(); 

Now - although what you asked initially should serve some purpose (because to display and hide the counter when the task is completed, you will need to wait until the controller completes the action). There are situations when it is shown to the client that the work has completed processing.

First, let's define a scenario in which background processing is really useful. Suppose you have a button that, when clicked, will retrieve data from some external api, and after receiving data from an external site, a database operation based on the response is performed. This will be a good example of when to use the background process. Basically in the controller you would do something like:

 class ApiController < ApplicationController respond_to :js, :only => [:create] def sync_tweets TwitterApiJob.enque(current_user.twitter_username) respond_with(message: 'Syncing Tweets') end end 

Now, to tell the user when the tweets have completed the synchronization, it’s a little more complicated, and you have 3 main options:

1) Notify the user by email (usually the worst version of imo) 2) Use some kind of html5 or websocket server that can work with rails, and send the client through the websocket client, which, although very cool, in most cases is overloaded and goes beyond this answer. Google rails websocket click if you want to see your options. 3) The best IMO option for most cases. Create a notifcations model to handle all kinds of custom notifications and do something like

 Notification.create(:user_id => user.id, :message => 'Sync has finished', type => 'sync_complete') 

Then, on the next page that the user is requesting, in the header toolbar or elsewhere, I would notice that the user has unread notifications to alert the user to click on it.

--- I also think that in your post you mentioned that you are using resque. I tried resque, and it was worthy, but I found it difficult to debug in production, and it used crazy memory - I would advise you to check sidekiq, if you haven't done it already, it uses redis as well, but much faster since it uses topics:

https://github.com/mperham/sidekiq

It is much faster, cleaner and easy to get customization, imho.

+11
source

All Articles