How to do some "garbage collection" by removing old completed jobs, for example, those which are older than 1 hour?
Thanks!
You should be able to to use the queue's 'job complete' event to call kue.Job.get(job_id) and then use the returned job's remove() method.
But that will delete them instantly on removal.
I too would like something that calls expire with a given time on the relevant keys, but i'm not sure how it would handle delaying the removal of the jobs from the lists...
You could let the job expire after x seconds by using Redis' EXPIRE command: http://redis.io/commands/expire
Expiring the job's key does not remove it from the list of jobs.
I'd like to have this feature as well. Perhaps a command that deletes all complete jobs that I can run periodically? I suppose I can make the request directly in redis but I'm a bit unfamiliar with the structure of the data that kue uses.
+1 for having Jobs deleted from Completed Queue
+1 for periodically removal of completed jobs with certain amount of intervals
Could someone explain why they prefer a delayed removal of completed jobs rather than just using something like:
jobs.on('job complete', function(id) {
kue.Job.get(id, function(err, job) {
job.remove();
}
});
I prefer delayed removal, because that way I can be certain that the job completed ( since I can see it on the queue on complete state ) by removing the job you have the felling that the job vanish from the queue with out been certain that the job was completed or not.
This would indeed be handy. When you process 1000+ jobs per minute, the keyspace gets flooded rather quickly. I'd like to keep stuff in the complete log for at least a few minutes, so we can watch it for odd behaviour when necessary.
+1
+1 for periodically removal of completed jobs with certain amount of intervals
+1
+1 I fear millions of completed jobs isnt going to do the UI or the redis queue any favors
It seems that Redis is just now getting to the point where this can be handled asynchronously.
When an event is completed, we add to a q:expiring sorted set, with EXPIRE. Meanwhile, we subscribe to the EXPIRE event, and handle removal appropriately thereafter. http://redis.io/topics/notifications.
Alternatively, we can create a sorted set containing the job ids, sorted by seconds since epoch and periodically run a "clean up" command.
Submitted pull request that addresses this problem using the second technique I discussed. I do not think that garbage collection should be the primary means by which things are cleared out, but instead used secondarily.
@brandoncarl Really appreciate you contribution and your recent pull request. Hopefully that gets accepted soon.
Here's something I did today to clean up old jobs. Modified from an example found on Stack Exchange.
https://gist.github.com/niravmehta/6112330
HTH.
Thanks @niravmehta - great work on the exponential backoff pull request.
It seems that this repo really needs a solid set of tests. It seems that #202 is a good start.
The forums are pretty ripe with pull requests...they are just not being tested/accepted quickly enough.
@brandoncarl I'd like to have the changes tested, but do not have expertize in test suite generation / maintenance. May be @visionmedia can take that lead and combine #202 with additional tests so that future contributions can be handled better.
But till that time, @LearnBoost or @visionmedia 's eyes could be great for accepting these changes!
we are using kue to process million of jobs every hour, and found the best way to remove complete jobs is to set up a standalone sweeper service. So I wrote a small tool to do that. And following are reasons why I do so:
Good work @yi Thank you!
+1 for this entire thread!
sorry everyone I am a new guy of kue and have a question to ask about why don't just use a function to complete like
var CLEANUP_TIME = 0.5 * 60 * 1000;
var CLEANUP_INTERVAL = 0.1 * 60 * 1000;
function performCleanup() {
var now = new Date().getTime();
Job.rangeByType('someType', 'complete', 0, -1, 'asc', function (err, selectedJobs) {
selectedJobs.forEach(function (job) {
var created = job.created_at;
if (now - created > CLEANUP_TIME) {
job.remove();
}
});
});
}
setInterval(performCleanup, CLEANUP_INTERVAL);
Is this a bad way for this problem??
i simply added the redis expire to the jobs:
var job = kueJobs.create('myjob', {}, ).save(function(err) {
if(err) return console.error(err);
kueJobs.client.expire(kueJobs.client.getKey('job:' + job.id), 30*24*3600);
});
@psi-4ward that won't help much since expire only removes the job:id itself, not from the ZSETs that job id belongs to. and this makes serious inconsistencies
@AndyYou thats OK andy
oh damn, do you know how to EXPIRE the ZSET also?
You should do it programmatically, however it has a simpler solution if you are on >= 2.8 version of redis. Read these:
1) http://stackoverflow.com/questions/13174615/how-to-get-callback-when-key-expires-in-redis
2) https://groups.google.com/forum/#!topic/redis-db/rXXMCLNkNSs
Kue shall provide a job TTL feature in future :)
For those interested, you could also use
job.create( ... ).removeOnComplete( true ).save()
that will remove each job on completion.
Try this, worked for me
jobs.on('job complete', function(id) {
kue.Job.get(id, function(err, job) {
setTimeout(function() {
job.remove();
}, 60000);
});
});
For those interested, you could also use
job.create( ... ).removeOnComplete( true ).save()
that will remove each job on completion.
For smaller systems I'd say this is ideal, but if you have a system where you're creating jobs in many different places I'd say it's probably best to listen to the "on complete" event.
As for using setTimeout() to remove the jobs after a certain time interval, the downside is that if your restart the application you'll lose those callbacks and the jobs will never be removed.
Just some thoughts...
sorry everyone I am a new guy of kue and have a question to ask about why don't just use a function to complete like
var CLEANUP_TIME = 0.5 * 60 * 1000; var CLEANUP_INTERVAL = 0.1 * 60 * 1000; function performCleanup() { var now = new Date().getTime(); Job.rangeByType('someType', 'complete', 0, -1, 'asc', function (err, selectedJobs) { selectedJobs.forEach(function (job) { var created = job.created_at; if (now - created > CLEANUP_TIME) { job.remove(); } }); }); } setInterval(performCleanup, CLEANUP_INTERVAL);Is this a bad way for this problem??
Other status can be:
Most helpful comment
For those interested, you could also use
job.create( ... ).removeOnComplete( true ).save()that will remove each job on completion.