I run a website with about 10,000 users, 6500 which are setup with a roll through uc_roles. The problem I'm experiencing is that the cron function runs for almost 6 minutes each and every time because it loops over every record via the following:
$result = db_query("SELECT * FROM {uc_roles_expirations}");
foreach ($result as $expiration) {
Inside this loop are essentially 3 if/else conditions.
- Cleanup if already deleted
- Handle current expirations
- Remind users who are about to expire.
I'm proposing we break up this single loop into 3 queries/loops.
1. Find all uc_role_expirations records that no longer contain that role -> delete.
2. Find all uc_role_expirations that are less than now and delete
3. Find all uc_role_expirations records with expiration > now and less than the reminder window -> notify
In my setup alone, this would reduce the number of records to test from 10,000 to 50-100 per run. The only penalties this brings up is a possible subquery in #1 and some additional conditions in #2 and #3. But it would greatly reduce the number of loaded user objects in the loop and bring the cron cycle down to a few seconds instead of a few minutes.
So my question: If I provide a patch based on this strategy, would it be committed or are there other considerations I need to address first?
Comments
Comment #1
tr commentedDuplicate of #911350: uc_roles_cron() does not scale (horribly). Please contribute to that issue if you want to get this fixed! A patch would be welcome.
Comment #2
rickmanelius commentedAh crap. I searched for the wrong terms. Thanks for pointing out the duplicate :)