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

tr’s picture

Status: Active » Closed (duplicate)

Duplicate 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.

rickmanelius’s picture

Ah crap. I searched for the wrong terms. Thanks for pointing out the duplicate :)