Just copied the description from sandbox site: http://drupal.org/sandbox/patrickd/1182956
I think it is already a good explanation. Looking forward to the review, hoping everything is fine.
I already tested it on three different linux servers and it works perfectly, but I would be very happy if someone could test it on a windows machine.
Croninfinite allows you to run cron just like a cron job - but completely without a cron job, a site visitor or a manual cron run. It's really a kind of PHP implementation of the unix cron utility what is recommended for most sites.
How does it work?
Croninfinite depends on a script that runs "infinite".
(Before you pass judgement on this claim, please continue reading)
- The script does not depend on a site visitors request
- It runs with minimal system rights, a set maximum_execution_time and save mode
- Independent from any third party service like online-cron's
The "infinite" running script doesn't run endless actually, it just times the right moment to re-execute itself just before it may gets killed by max_execution_time. I have seen this behaviour on PHP-based malware and it seems to work very solid.
How to use it?
After installation you should check out the status report page (admin/reports/status) which shows you the current status of Croninfinite. Follow the shown guidelines to Cron's settings, where it hooked into (admin/config/system/cron). Before you start, you should set the desired cron timing and the advanced settings like the max_execution_time value (if needed).
Advanced cron-timing
Croninfinite offers you a very comfortable way to time your cron runs but sometimes this is not enough and you need an advanced timing. This is what time strings are made for:
The format of time strings for advanced timing is very similar to the unix crontab utility syntax:
* * * * * <= the "time string"
┬ ┬ ┬ ┬ ┬
│ │ │ │ │
│ │ │ │ └──── Weekday (0-6) (Sunday=0) [-Weekday]
│ │ │ └────── Month (1-12) [-Month]
│ │ └──────── Day (1-31) [-Day]
│ └────────── [*/] Hour (0-23)
└──────────── [*/] Minute (0-59)
Examples:
| 0 | * | * | * | * | Hourly |
| */30 | * | * | * | * | Every thirty minutes |
| 0 | 0 | * | * | 1-5 | At midnight from Monday to Friday |
| */5 | 0 | 1 | * | * | Every five minutes about 0 o'clock on the first day of month |
| 0 | */3 | * | 2-11 | * | Every three hours from Februar to November |
Technical aspects and problems
The max_execution_time sets the maximum time in seconds a script is allowed to run before it is terminated. The default setting is 30 seconds. A value of 0 would enable scripts to run infinite.
Croninfinite could be enabled to run infinite by setting max_execution_time value to 0 (using ini_set()) or by expanding the maximum value (using set_time_limit())
But..
- ..when running safe mode this setting cannot be changed while runtime.
- ..execution could also be interrupted by the web server's timeout configuration.
The sleep() function delays the script execution for the given number of seconds. Time spend sleeping is not used to determine the time that the script has been running.
Croninfinite could be enabled to run infinite by using the sleep function between cron runs.
But..
- ..sleeping time is ignored under Linux, but it counts as execution time on Windows
- ..while sleeping execution could also be interrupted by the web server's timeout configuration.
The ignore_user_abort() function sets whether a client disconnect should cause a script to be aborted.
By fsockopen() a socket connection (eg. HTTP with TCP) can be opened with minimal requirements.
Croninfinite can be enabled to run infinite by restarting itself independent through HTTP using these functions. To save CPU performance it can delay the "re-spawn" by sleeping the left max_execution_time before it may get killed (read above).
But the max_execution_time cannot be determined reliable by PHP's configuration because many hosts set it to values like -1 to control it through kernel.
Croninfinite tries to assess it by executing a script that wants to run much longer than it's allowed to and time the period until it gets killed. This period should be equal to the value of max_execution_time.
Comments
Comment #1
jordojuice commentedInteresting! Great description, quite exciting.
Your code looks really good. Certainly follows coding standards well judging by a little peak. I think the concept differs enough from the very popular Poormanscron to warrant a project. You'll need to remove variables set by your module in hook_uninstall(). I'm not sophisticated enough to do much more on this one, but it looks good to me : ) Just wanted to check it out.
EDIT: I can test it on a Windows machine.
Comment #2
patrickd commentedThanks for review!
Doesn't the documentation say that uninstalling used variables is done by drupal 7 itsself?
(http://drupal.org/node/1187664 )
or is this only for database tables?
Looking forward to your windows testing results.
Comment #3
joachim commentedInteresting... reading this makes me wonder whether cron could be implemented with node.js but that's a whole other story! :)
> $request = "GET " . base_path() . drupal_get_path('module', 'Croninfinite') . "/croninfinite.php"
Certainly within Drupal that should be done with drupal_http_request().
> function croninfinite_requirements($phase) {
Belongs in the .install file.
Remember to end comments with a full stop. That's missing in a lot of places.
This function in particular needs to document its @return.
> if ($form_id == 'system_cron_settings' && (!isset($form['#theme']) || $form['#theme'] != 'confirm_form')) {
I recommend using hook_form_FORMID_alter() for code readability.
You should also look at how system_cron_settings() is using system_settings_form(). That may actually do some of your variable saving automatically.
Run a Coder review; it should tell you not to do the above.
We don't include the closing PHP tag.
Comment #4
jordojuice commented#2 indeed D7 got rid of drupal_uninstall_schema() but variable still have to be taken care of since theres no concrete way of identifying which modules set which variables in the variable table (if I'm remembering the table correctly)
EDIT: I will try to do some testing tomorrow.
Comment #5
patrickd commentedThank you both very much!
I think I have fixed everything so far.
But I even think I've a problem with my coder module.. it seems like it does not show me all issues.. just "No Problems Found" (even if I do them intentionally). Did I mess up something?
Comment #6
jordojuice commentedI have had some issues with Coder in D6 myself. I have ported D6 modules to D7 and found that the D7 Coder module found much more code problems that weren't mentioned in D6 though they should have been. I don't know of anything in particular that can cause this, but I'll give you a print out of my Coder results when I test it (if it works!).
Comment #7
joachim commentedControl statements should always have braces, even single lines.
Comment #8
patrickd commentedThanks, I fixed this and some other little bugs in recent commit!
Comment #9
joachim commentedI'd definitely like some input from PHP experts on the general wisdom of this approach... :)
Comment #10
fabianx commentedI believe boost crawler in boost is doing something really similar, so you might want to check in with mikeytown2 about that.
Comment #11
patrickd commentedHi,
Maybe it uses a comparable technique to keep the crawling alive but the purpose is completely different.
Also the 7.x release does not seem to be very active.
Sorry, I don't see much similarity to the functionality of croninfinite, you may be more accurate to your statement?
Comment #12
patrickd commentedComment #13
patrickd commentedComment #14
patrickd commentedSuccessfully tested on different Windows/IIS machines now!
Also made some general best practice fixes and logging start/stop functionality by watchdog.
Comment #15
pillarsdotnet commentedI like the concept.
Comment #16
joachim commentedWhen I cloned the repo just now, it put itself into: croninfinite___croning_cron_without_cron
er...?
Comment #17
patrickd commentedThat's because it tooks the full project name (because I can't choose a shorter one until it is a full project)
Simply rename it to "croninfinite"
Comment #18
patrickd commentedrewrote many code parts, made general enhancements in code quality, best practices and drupal coding standarts.
Latest version: http://drupalcode.org/sandbox/patrickd/1182956.git/snapshot/49a26ddcc12a...
Comment #19
knivets commentedWorks like clock. Everything seems okay. I'll use it on my site :)
Comment #20
patrickd commentedCause of the lack of reviews, the project will be maintained and developed together with an more experienced user.
I'll start a new project application request with another module (which is hopefully more interesting for reviewers) and try to get my full project permission another time.
Thanks for interest anyway.
regards