There has been a fair amount of concern about the moodle cron task.
This has issues with large sites (such as ours) where some cron functions, such as the Forum digest can take VERY long time to run.
The limitation to a single cron instance means that regardless of the order that cron_* functions are called the "takt time" (http://en.wikipedia.org/wiki/Takt_time) is always going to be sum of each functions execution time, and so functions that want to run every minute will end up running every "total cron execution time".
In addition there are notional dependencies on module cron functions in particular orders. I've struggled to see this documented so it would be good to get some sort of statement about what is dependent and why
From looking at the cron lib code it would seem that the order of things (so notional dependencies) are:
- some systems administration stuff
- account updates and enrolments are done first so that everything else has up to date user and course enrolment information
- Activity Modules (Examples)
- Digest (>1hour 1x a day)
- Attempt/quiz session updating (??mins every 1minute(i think))
- Block crons
- Blog related
- Question Bank
- Site Update
- "All other plugins"
- Automated backups
The problem that we've identified as being an issue isn't the overall order of cron tasks but the independence of 3. Activity Modules.
MDL-17783 applied the use of Session locking code to *all* of the cron elements to run independently, when I think what we really need is a mechanism that allows:
- (1)->(2) to be run in series,
- All of (3) to run in parallel,
- Steps 4->end run in series
Could this (this is me spitballing) be done in a way that could be retrospectively applied to previous versions?
In theory I think it could be by:
- Define new cron locking API (instead of re-using existing session locking API).
- Re-model the cron scrip to understand 3 states:
The logic would be:
When a cron instance is started, CORE_PRE moodle core and CORE_PRE registered functions are executed. Any subsequent instances that are started would then check the state and exit straight away.
Once ALL CORE_PRE function are handled, the 1st instance starts doing the MODULE registered functions. This would effectively say "we've updated core standing data and it can be considered valid for the immediate future". Each module function obtains a lock when it is initiated and releases it once it's done. The duration to execute the function would be tracked.
Since the cron is in state MODULES, subsequent instances would skip the CORE_PRE stuff and look at the MODULES and would process the next available module function. The duration information that is recorded over iterations could be used to automatically re-order the execution so that small "fast" items are run first.
Only once ALL MODULES registered functions are completed, the cron script moves into it's final CORE_POST state, runs the registered functions whilst preventing any additional cron instances from doing any work.
In my head this "new" cron script could live alongside the current one (since administrators have to configure it outside of moodle anyway). I think that this is important as the Moodle release schedule doesn't always fit with institutions being able to go to the latest version (in our case we typically upgrade in June, so there isn't enough time to really fully evaluate a new release and update everything in time) and the issues in the cron are likely to affect institutions of a size where they (we) can't just take it from the latest version.