I want to know if there is a way in RoR to run a rake task, or a ruby code, twice in different times. For example, when a user registers, run the task after three days, and then run the same task one week later, but no more('stop the process'). I was looking at crontab and gems like Resque, Stalker, Starling, etc. but I don't have a clear idea who this gems can help me. I'm thinking in run a daemon for each user and count the task executions.The problem is that the daemon would be active all that time "eating" resources. Is there a way to use as least resources as possible?. I want to run this in Heroku later.
I usually solve this type of thing with date columns on the record (eg. first_reminder_sent_at, user_responed_at, week_reminder_sent_at). In this case, a date for the first item, the user's response, and for the week-later item.
Create a cron task to call a rake task - look at all users that are > 3 days old, < 1 week, user hasn't responded, date not set.
Queue up the Background Job.
The Job will send the mail (or whatever the task is) and then set the date field on the record.
Cron task to call a rake task - looks at all users that are > 1 week old where user hasn't responded and date not set.
Send the reminder and set the date in a Background Job.
Try the whenever cron and create a rake task, which is doing your stuff.. and in the database make some trigger fields when and how the rake task should do his actions..
Posix systems have the at command which is a dead simple way to schedule a job to run once at a later time. Though there's nothing wrong with using an application based queueing mechanism to schedule later work as outlined in the other answers. at is host specific so probably unsuitable if you're running a cluster, especially if the hosts may be transient.
Related
I have a rails module that processes some active record objects, only about 15-20 at a time, that I need to start off every two minutes.
I have tried to offload it to sidekiq (and sidekiq-cron), which works, but with the concurrency, created many race conditions and duplicate data.
I really just need a simple rake task cron for rails or maybe sinatra (as I would create a new sinatra app just to complete these tasks)
I either need to force sidekiq to process in a single thread or
have a "cron" job run a rake task or even the module directly
def self.process_events
events = StripeEvent.where(processed: false)
events = StripeServices.arrange_processing_order events
events.each do |event_obj|
StripeServices.new(event_obj).process_event_obj
end
end
thanks for any point in the right direction.
edited
sorry I wasnt very clear. pushing my module to sidekiq caused concurrency issues that I wasnt ready for (my bit of code is not threadsafe), and with the restrictions that Heroku places on "crons", whats the best way to run a rake task every 2 min?
If Sinatra can do it, I would prefer it, but I cant find the solution for that same problem.
It's not clear what are you asking. You already tried option 1, you can try option 2 (create the task and cron it, it's pritty easy) and you'll know better than anyone if it's better.
Anyway, I guess that both methods will have concurrency problems if one task takes more than 2 minutes.
You can add extra flags to prevent two task to process the same ServiceEvent (maybe add a boolean "processing" and set it to true when a task takes it).
Or maybe you can have a lock file to prevent a task to run if another one is already running (you create a file with a specific location and name when the task starts and delete it when it finishes processing, you can check if the file exists before starting a new task).
Hi I making a petition site. In my site i Have three types of petitions, every have self period. When period is passed it need to change petition status(integer value) automaticaly.
How to do this better? And wich time rails use on server, from my pc or from server?
I ask about because I need somehow to test it manually.
I'm noviece, so if it's possible help me with simpliest alghoritm. I don't need a pure safety and performance.
I would suggest implementing it as a rake task, that will run every day as a cron job and update the mentioned value if record matches the condition(exactly one year passed).
Using this way you avoid problems related to performance as the rake task launches in separate background and also you may run the task when your server isn't overloaded by other tasks, for example at night.
Following gem is useful to setup jobs by schedule https://github.com/javan/whenever
I have the Heroku Scheduler add-on set up and I came across techniques for running a task weekly. However, I need a task that runs every other week, but I can't think of any elegant/simple way to do this.
How about setting it to run weekly on Heroku, but then in your actual task make the first step be to check if the task was already run last week, and if so abort. This would also involve storing the current date every time the task is successfully run.
I'm trying to create a job in order to send a notification to a Twilio call, therefore it is important to have a robust solution that can make sure jobs are run at a specific time (I don't think being put into a queue is accurate enough).
What is the best solution for this type of a task?
These notifications need to happen at a specific time in the call. Such as "1 minute left". Therefore it needs to be able to:
Run at arbitrary times (1:22PM or 2:45AM)
Be defined by user input (they set the time of the call)
(It would be nice if that solution could run on Heroku)
You can use Heroku cron to run jobs either daily or hourly.
Daily cron is free, hourly cron costs $3/month: http://addons.heroku.com/cron.
Typically cron runs when you first initiate it (i.e. if you set it up at 3pm, it'll run at 3pm every day), but you can change that by sending an e-mail to support#heroku.com.
To run code in a cron, add your code to a cron.rake file and check out the cron docs here.
FYI
Heroku's own samples for cron suggest doing a time check, i.e.
if Time.now.hour % 4 == 0 # run every four hours
...
But, if you are running a daily cron, the code will run at a time that is likely to fail the above conditional. So, unless you are paying for hourly cron and you only want it to run specific hours, leave out that part of their sample code and just include your own code normally.
Running at Specific Times
Try delayed_job's :run_at column, which may give you the flexibility you need to run jobs at very specific times.
Heroku Docs: http://devcenter.heroku.com/articles/delayed-job
You need to add a cronjob for that. If you are on a Linux box then you can add a cron to the crontab and specify the time at which it runs. It is very flexible. You can find the details here:
http://en.wikipedia.org/wiki/Cron
If you want to do it in a ruby way, try whenever gem:
https://github.com/javan/whenever
For the specific case that you have mentioned, I think that you should give delayed_job a try:
https://github.com/collectiveidea/delayed_job#readme
it has a run_at option where you can specify the time at which you want to run the job.
Goto cron jobs in your hosting control panel
If I need to create recurring tasks in delayed jobs, what is a clean solution? I have an import task that I want to run every 5 minutes, but I don't want to fire up rails/rake in order to tell it to create a Delayed job that can be picked up. If Rails is already running on a system, perhaps I can just create an HTTP request that will make the rails app fire off a DJ? I could put that cron task in a ruby script which runs every 5 minutes, making requests to a server, but without firing up rails. What do you think?
This fork of delayed_job has recurrence built right in (and there may be other forks that do the same):
http://github.com/andrewroth/delayed_job
The cron approach still seems to be quite clean. It need only involve running a rake invocation, not a full Rails server. Rake doesn't need Rails to be running to work.
However if you really don't like that approach then you could arrange for the recurring jobs to be re-queue themselves when they are being processed setting a run_at time to 5 minutes (or whatever) in the future. Obviously you'd need to prime the queue the first time and make sure the delayed_job server stays running
About that... I have the same desire,
I'm planning to have a cron to fire up a curl request at a specific route at my site every 5 minutes, so it runs a action with the result, and I'm gonna be pretty sure it only ran once.
My purposes includes: Awarding Badges and compiling some Averages