I have a method like this that goes through an array to find different APIs and launch a delayed_job instance for every API found like this.
def refresh_users_list
apis_array.each do |api|
api.myclass.new.delay.get_and_create_or_update_users
end
end
I have an after_filter on users#index controller to trigger this method. This is creating many jobs to be triggered that will eventually cause too many connections problems on Heroku.
I’m wondering if there’s a way I can check for the presence of a Job in the database by each of the API that the array iterates. This would be very helpful so I can only trigger a particular refresh if that api wasn’t updated on a given time.
Any idea how to do this?
In
config/application.rb, add the followingCreate a new directory at
app/jobs/.Create a file at
app/jobs/api_job.rbthat looks likeNote: You will replace
attr1,attr2, andattr3with whatever number of attributes you need (if any) to pass to theApiJobto perform the queued task. More on how to call this in a momentFor each of your API’s that you queue some
get_and_create_or_update_usersmethod for you’ll create anotherJob. For example, if I have someFacebookapi model, I might have a class atapp/jobs/facebook_api_job.rbthat looks likeNote: In your Question you did not pass any attributes to
get_and_create_or_update_users. I am just showing you where you would do this if you need the job to have attributes passed to it.Finally, wherever your
refresh_users_listis defined, define something like thisjob_exists?methodNow, within your
refresh_users_listand loop, you can build new tokens and calljob_exists?to check if you have queued jobs for the API. For exampleNote: Again I want to point out, you won’t be able to just drop in the code above and have it work. You must tailor it to your application and the job’s you’re running.
Why is this so complicated?
From my research, there’s no way to “tag” or uniquely identify a queued job through what
delayed_jobprovides. Sure, each job has a unique:idattribute. You could store the ID values for each created job in some hash somewhereand then check corresponding hash key for an ID, but I find this limiting, and not always sufficient for the problem When you need to identify a specific job by multiple attributes like above, we must create a way to find these jobs (without loading every job into memory and looping over them to see if one matches our criteria).
How is this working?
The
Structthat theApiJobextends has a:tokenattribute. This token is based on the attributes passed (attr1,attr2,attr3) and is built when a new class extendingApiJobis instantiated.The
find_by_tokenclass method simply searches the string representation of the job in thedelayed_jobqueue for a match based on a token built using the sametokenclass method.