-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Standard interface to run cron jobs, precluding the need for routes #20
Comments
I should note that I don't want to use a route for my cron definitions. I also figured loading the cron definitions on every bootstrap introduces unnecessary system load. So I can only think of 2 "proper" ways to add cron runs now: via a route or via an artisan command (both manually added). IMO both are undesirable, as they require more than just defining a cron job. A better solution IMO would be that Cron defines its own artisan command (and optionally a route), which then collects all cron definitions, perhaps by triggering an event. When all event listeners have registered their cron definitions, the command can run An simple example of code implementing a cron run using such a mechanism would be: Event::listen('cron.collect', function() {
// A cronjob which will run every minute.
Cron::add('SomeCronJob', '* * * * *', function() {
return SomeCronJobHandler::cron();
});
}); |
Hi ameenross, thanks for using Cron. Maybe your event listener is a good idea. But where will you define your jobs if you don't use a route or a command? Then it will be somewhere in the bootstrap and this will lead to an unnecessary system load. |
Yeah, I mentioned that concern as well, but in this case the only thing that is defined is an event listener and I assume that it incurs a lower overhead. It also makes it much easier for package developers to define their cron runs, and additionally means that app developers don't need to worry about creating a route. All they have to do is put |
I just did a small benchmark using tinker to test my assumption. Here is the code and results: /* Add 1000 event listeners in a loop and measure the time taken. */
$start = microtime(TRUE);
for ($i = 0; $i < 1000; $i++) {
Event::listen('cron.collect', function() {
Cron::add("SomeCronJob$i", '* * * * *', function() {
return SomeCronJobHandler::cron();
});
});
}
$time = microtime(TRUE) - $start;
print 'Time taken: ' . $time . "\n"; /* ~0.013s */ /* Add 1000 cron jobs in a loop and measure the time taken. */
$start = microtime(TRUE);
for ($i = 0; $i < 1000; $i++) {
Cron::add("SomeCronJob$i", '* * * * *', function() {
return SomeCronJobHandler::cron();
});
}
$time = microtime(TRUE) - $start;
print 'Time taken: ' . $time . "\n"; /* ~0.23s */ So it's nearly a factor 20 faster to add an event listener, and an overhead of about a millisecond for 100 cron jobs is negligable IMO. |
That looks good, thank you for the benchmark. Okay I will fire an event before calling the run method and I will add a simple command which will run Cron and one command which will list all registered jobs. Did I miss something? |
I think that's about it, so basically we have:
By the way, as |
This is a great plan. I will work on this next week. Thank you very much. |
Great! Any progress so far? I'm willing to create a pull request implementing it, if you want. |
Yes, everything should be finished. I tested everything with Windows, Debian is still outstanding but you can start testing, too. For example add Event::listen('cron.collectJobs', function($rundate) {
Cron::add('example1', '* * * * *', function() {
// Do some crazy things successfully every minute
return 'Wuhu';
});
Cron::add('example2', '* * * * *', function() {
// Do some crazy things successfully every minute
});
Cron::add('new name for disabled job', '* * * * *', function() {
// Do some crazy things successfully every minute
}, false);
}); to your global.php. You can run the commands with I hope you like it :) |
Cool! I hadn't noticed. Did you push the last stuff though? Because I don't see the |
Yes, everything is pushed. Have a look at the last commit 42dc9eb. The Debian tests are passed now. |
Ah right, I see you put the The |
I thought about this but I want to give all people (using route and commands) the possibility to use this event for registering jobs. For example, if you want to switch from command to route (maybe only temporary), you can let your job definitions unchanged but can use a route where you only call the run method. The jobs in the boot file will be loaded, too. I like your idea with this event listeners so I think that route users maybe will use this functionality, too? What do you think? |
Well I agree with your reasoning, but I'm concerned about backward compatibility. Lets say an app developer has a route setup which runs a few cronjobs with the old method. They then install a package that defines a cronjob with the new method. The app developer ran a As for people needing to use the new system, just document it in the Readme and people will start picking it up. They will just have to move their |
You win. I will move the |
Okay, it's done. Tests passed on Windows and Debian. Now it is your turn ;) |
Hi, great feature. Just wanted to add, that you can always use semver, as a way to specify breaking changes. |
The way it's implemented now is not a breaking change though. Will test tomorrow but am confident it will work! |
I was referring to the previous implementation. If you want to introduce a |
Thanks for your introduction, Moleculezz. I will take this into account in the future. But for now I have a problem. The new release has new features but does not break backwards compatibility. But the current release is v0.9.5. So what should I do? Make a v0.9.6, a v0.10.1 or a v1.0.0? |
Semver defines versioning as the following: MAJOR.MINOR.PATCH |
Yes, I read the documentation and I agree with you. But I can't find a version in the document which has a number higher than 9. So I was confused. |
If you look at definition number 2 on semver, you will see an example. |
From the FAQ:
So I think personally that it would be good to release 1.0.0 soon. Maybe after you provide a route that calls |
By the way, I tested it and it works. Just have 2 ideas for cosmetics, first is to add a line ending after the output of the commands, the other is to create an output similar to the |
Just found it, it's Symfony: http://symfony.com/doc/current/components/console/helpers/tablehelper.html |
Table Helper is awesome! I will add it ;) |
Just created a pull request for it :) |
Yeah, the request was added. Thank you. I was too slow :D The pull request for the run command was merged, too. |
Can I close this? I think we implemented all requested features. |
yeah of course :) mission accomplished |
Great, thank you :) |
It isn't clear to me where to put my cron definitions. I am writing a package that requires cron to do some pulling of data from a remote source. I defined a cron rule in my service provider's boot method, as that seems like the right place for it.
Apparently through, the facade for the "cron" class is added after my
boot
method ran, which means I can only use it with the fully qualified class name. I could, however, get it working by editingCronServiceProvider.php
to directly add the facade in theregister
method, like so:Am I doing something wrong, should I put my definition somewhere else? Is the above suggestion flawed for some reason? Or should I just put the facade in my
app.config
?The text was updated successfully, but these errors were encountered: