Delayed searchable jobs in Rails - ruby-on-rails

Is there some background processor in ruby which would allow to find an existing not started delayed jobs by custom key?
I'm trying to solve a task with e-mail notifications, when there could be multiple changes in my model and I want to collect them in batches before sending.
So, I don't want to create another notification job when there is already an existing job, I'd rather append notification info to the existing job.
Any hint?
Thanks,
KIR

I suppose you will need an engine app
https://github.com/trevorturk/delayed_job_admin
Tested and working fine, but requires rails 3.

I think I'm trying to mix concepts here.
Delayed Job's work is to run long tasks.
What I'm looking for is a list of active notifications, which I can easily implement with a custom table.

Related

Which Ruby / Rails Background Job Framework should I use (that works on Heroku) for dynamically adding future jobs in Rails

So I created a client-server (Rails for both client and server) system that will have many clients with one server, that interact using REST.
The clients can send / update / delete their own "Jobs" on the server, which is right now simply a table named Jobs. The Jobs belongs_to a table named Apps, which ofcourse has_many jobs (each App entry represents a client, so the client can only add / delete / update / read their jobs on the server).
The purpose of this, is so the client can add entries to the Jobs table and specify a Time of Day (in the future), that they can run a Job. The Job that gets run is a call to a 3rd party email-service to send an email.
So I need a Jobs framework, that can easily run on Heroku, and iterate through my Jobs table (say, every half-hour.. Or even every 5 minutes maybe..), and see if there are any Jobs it needs to run based on a datetime column (check if the datetime entry is equal-to, or less-than the current-time the Worker is running)
Which is the best Rails / Heroku Job framework I should use for this?
I prefer simplicity, so I was looking at:
https://devcenter.heroku.com/articles/scheduler
But, I cannot use this because it warns:
Scheduler is a “best effort” service, meaning that execution is expected but not guaranteed. Scheduler is known to occasionally (but rarely) miss the execution of scheduled jobs"
So next I looked at at https://devcenter.heroku.com/articles/scheduled-jobs-custom-clock-processes - which can be implemented using Gems like Resque or Delayed Job.. Which I am currently researching now..
Ideally, I wanted to be able to find a Job Framework that would compliment (or replace) my jobs table (So, Whenever I add something to my Jobs table or delete it, each of my Job entries would have a 1:1 relation with an actual Job in the Job framework, that I would also be adding / updating / deleting when I add / update / delete an entry on my Jobs table and / or the Jobs entry in the Job Framework). Ofcourse I would be writing the logic for all the CRUD operations on the server (once it receives a REST call from the client) - But the client needs to be able to delete and re-add all it's jobs on the server at any-moment; and I did not see any Job frameworks that would allow me to dynamically add and remove future jobs at any given time, dynamically. All the existing frameworks seem like they are created for scheduled jobs to run at specific times or time intervals, specified in a config file. Which is fine, but I wanted to check on S.O to verify that I am making the best decision when choosing my setup / framework
Sorry for the long / complex question - and I appreciate any suggestions or recommendations anyone has for me!
Thanks!!!
This sounds like a job for Resque and Resque-scheduler.
Here's a syntax example :
Resque.enqueue_in(5.days.from_now, SendFollowupEmail, argument)
If you need to delete it before it is executed :
Resque.remove_delayed(SendFollowUpEmail, :user_id => current_user.id)

Ruby on Rails - Trigger an event automatically on specific DateTime

I want to trigger an event, specifically send out an email and update attributes on some models, on a specific DateTime (which is a column in one of my models).
I have searched around but have not really found any solutions to this.
Is there any way of achieving this?
You can use a queueing solution along with a scheduler.
Queueing solution: Resque with Redis backend
https://github.com/resque/resque
Scheduling solution : https://github.com/resque/resque-scheduler
Resque.enqueue_at(5.days.from_now, SomeJob)
You can schedule a job to run at a particular date. Combine this with the ability to setup a schedule.
Say you trigger the first job on Jan 1st and want it to run every 30 days.
You can use a queuing solution to send out email asynchronously : something like Resque with a Redis backend.

Scheduling events in Ruby on Rails

SO sorry if this is a duplicate, I tried searching for this but wasnt sure what search terms to use and didnt really find anything.
I have a Ruby on Rails app that will be used to send text messages out to users that contain a link to a multiple choice question probably using clickatell. The questions have a date and time associated with them. I want to make the ruby on rails app automatically send those SMS messages to the users' phones on those specified dates.
I don't really know how one would go about doing this. Can anyone point me in the general direction of a a way to schedule events like this in ruby on rails. I don't need an exact solution, maybe if someone could just clarify what exactly this is called so I can find some resources on line.
thanks
It seems the sending out your questions is not reoccuring? In this case I would not do this via a cronjob. I would do this via: https://github.com/bvandenbos/resque-scheduler
So whenever a question is getting scheduled you just add it to the delayed queue and resque-scheduler handles moving them on the correct working queue when its time has come.
This way you don't have to worry about some sort of polling cronjob, this will be done by resque-scheduler automatically. You also get asynchronous handling of sending out the SMSes via resque for free. So if you have to send lots and lots of SMS you can run them in parallel.
So it would go like this:
when a question is saved, you queue a message on the delayed queue in the future for sending out the question
when the date comes up, the message is moved onto 'ready to send'-queue, which is in charge of gathering all the users the question needs to be sent to.
for each of those users you create another message on the 'ready to send'-queue
the 'ready to send'-queue will then send out the actual SMSes
You then can run many workers on the 'ready to send'-queue and have the SMSes be sent out in parallel. You also get error handling for free with resque, it gahers all messages that resulted in an exception in a 'failure' queue, which you can then debug or reschedule again
You could use whenever to schedule events.

How to have users create scheduled tasks in rails app deployed on Heroku

I have a rails app deployed on Heroku. I want to add a feature that enables users of the app to set a reminder. I need some way for the app to schedule sending an email at the time specified by the user.
I have found numerous posts referring to using delayed_job for this, but none of the write-ups / tutorials / etc. that I have found directly address what I am trying to accomplish (the descriptions I have found seem more geared towards managing long-running jobs that are to be run "whenever").
Am I on the right track looking at delayed_job for this? If so, can somebody point me towards a tutorial that might help me?
If delayed_job is not quite right for the job, does anybody have a suggestion for how I might approach this?
The most typical way of handling this is to use a cron job. You schedule a job to run every 15 minutes or so and deliver any reminders that come up in that time. Unfortunately, heroku only allows cron jobs to run every hour, which usually isn't often enough.
In this case, I'd use delayedjob and trick it into setting up a recurring task that delivers the notifications as often as necessary. For example, you could create a function that begins by rescheduling itself to run in 10 minutes and then goes on to send any reminders that popped up in the previous 10 minutes.
To view delayedjobs send_at syntax to schedule future jobs check here: https://github.com/tobi/delayed_job/wiki
ADDED after comments:
To send the reminder, you would need to create a function that searches for pending reminders and sends them. For example, let's say you have a model called Reminder (rails 3 syntax cause I like it better):
def self.find_and_send_reminders
reminders = Reminder.where("send_at < ? AND sent = ?", Time.now, false).all
reminders.each do |r|
#the following delayed_job syntax is apparently new, and I haven't tried it. came from the collective_idea fork of delayed_job on github
Notifier.delay.deliver_reminder_email(r)
#I'm not checking to make sure that anything actually sent successfully here, just assuming they did. may want to address this better in your real app
r.update_attributes!(:sent => true)
end
#again using the new syntax, untested. heroku may require the old "send_at" and "send_later" syntax
Reminder.delay(:run_at => 15.minutes.from_now).find_and_send_reminders
end
This syntax assumes you decided to use the single reminder entry for every occurence method. If you decide to use a single entry for all recurring reminders, you could create a field like "last_sent" instead of a boolean for "sent" and use that. Keep in mind these are all just ideas, I haven't actually taken the time to implement anything like this yet so I probably haven't considered all the options/problems.
Check out the runt gem, may be useful for you: http://runt.rubyforge.org/
You can use delayed_job's run_at to schedule at a specific time instead of whenever.
If your application allows the users to change the time of the reminders you need to remember the delayed_job to be able to update it or delete it when required.
Here is more details.
It's good to avoid polling if you can. The worker thread will poll at the database level, you don't want to add polling on top of polling.

Monitor database table for external changes from within Rails application

I'm integrating some non-rails-model tables in my Rails application. Everything works out very nicely, the way I set up the model is:
class Change < ActiveRecord::Base
establish_connection(ActiveRecord::Base.configurations["otherdb_#{RAILS_ENV}"])
set_table_name "change"
end
This way I can use the Change model for all existing records with find etc.
Now I'd like to run some sort of notification, when a record is added to the table. Since the model never gets created via Change.new and Change.save using ActiveRecord::Observer is not an option.
Is there any way I can get some of my Rails code to be executed, whenever a new record is added? I looked at delayed_job but can't quite get my head around, how to set that up. I imagine it evolves around a cron-job, that selects all rows that where created since the job last ran and then calls the respective Rails code for each row.
Update Currently looking at Javan's Whenever, looks like it can solve the 'run rails code from cron part'.
Yeah, you'll either want some sort of background task processor (Delayed::Job is one of the popular ones, or you can fake your own with the Daemon library or similar) or to setup a cronjob that runs on some sort of schedule. If you want to check frequently (every minute, say) I'd recommend the Delayed::Job route, if it's longer (every hour or so) a cron job will do it just fine.
Going the DJ route, you'd need to create a job that would check for new records, process them if there are any, then requeue the job, as each job is marked "completed" when it's finished.
-jon
This is what I finally did: Use Whenever, because it integrates nicely with Capistrano and showed me how to run Rails code from within cron. My missing peace was basically
script/runner -e production 'ChangeObserver.recentchanges'
which is now run every 5 minutes. The recentchanges reads the last looked-at ID from a tmp-file, pulls all new Change records which have a higher ID than that and runs the normal observer code for each record (and saves the highest looked-at ID to the tmp-file, of course).
As usual with monitoring state changes, there are two approaches : polling and notification. You seem to have chose to go the polling way for now (having a cron job look at the state of the database on a regular basis and execute some code if that changed)
You can do the same thing using one of the rails schedulers, there are a few out there (google will find them readily, they have various feature sets, I'll let you choose the one which suits your need if you got that way)
You could also try to go the notification way depending on your database. Some database support both triggers and external process execution or specific notification protocols.
In this case you are notified by the database itself that the table changed. there are many such options for various DBMS in Getting events from a database

Resources