completejerry-mailoptin-safest-fix
MailOptin Safest Fix - Guaranteed to Work
Instead of relying on internal methods that could change, simulate what the cron healthcheck SHOULD do - but do it right:
<?php
/**
* Plugin Name: MailOptin Pantheon Fix
* Description: Force background queue processing on Pantheon hourly cron
* Version: 1.0
*/
/**
* Override the default healthcheck behavior to process directly instead of dispatching.
*/
add_action('wp_1_mo_wp_mail_bg_process_cron', 'mailoptin_force_queue_processing', 1);
function mailoptin_force_queue_processing() {
global $wpdb;
// Find the batch(es) waiting to be processed
$batches = $wpdb->get_results(
"SELECT option_name, option_value
FROM {$wpdb->options}
WHERE option_name LIKE 'wp_%_mo_wp_mail_bg_process_batch_%'",
OBJECT
);
if (empty($batches)) {
error_log('MailOptin Pantheon: No batches in queue');
return;
}
error_log('MailOptin Pantheon: Found ' . count($batches) . ' batch(es) to process');
// Get the processor instance
if (!class_exists('MailOptin\RegisteredUsersConnect\WP_Mail_BG_Process')) {
error_log('MailOptin Pantheon: Background processor class not found');
return;
}
$processor = new MailOptin\RegisteredUsersConnect\WP_Mail_BG_Process();
// Check if already processing (respect the lock)
if (method_exists($processor, 'is_processing') && $processor->is_processing()) {
error_log('MailOptin Pantheon: Already processing, skipping');
return;
}
// Process each batch
foreach ($batches as $batch_option) {
$batch_data = maybe_unserialize($batch_option->option_value);
if (!is_array($batch_data)) {
error_log('MailOptin Pantheon: Invalid batch data format');
continue;
}
$count = count($batch_data);
error_log("MailOptin Pantheon: Processing batch with {$count} items");
// Process each item in the batch
foreach ($batch_data as $item) {
if (!is_object($item)) {
continue;
}
// Call the task() method directly on each item
// This is what handle() does internally
try {
$result = $processor->task($item);
// task() returns false when item is complete and should be removed
if ($result === false) {
error_log('MailOptin Pantheon: Processed email for ' . $item->user_email);
}
} catch (Exception $e) {
error_log('MailOptin Pantheon: Error processing item - ' . $e->getMessage());
}
}
// Delete the processed batch
delete_option($batch_option->option_name);
error_log('MailOptin Pantheon: Deleted batch ' . $batch_option->option_name);
}
// Clear the scheduled cron event since queue is now empty
$timestamp = wp_next_scheduled('wp_1_mo_wp_mail_bg_process_cron');
if ($timestamp) {
wp_unschedule_event($timestamp, 'wp_1_mo_wp_mail_bg_process_cron');
error_log('MailOptin Pantheon: Cleared scheduled cron event');
}
error_log('MailOptin Pantheon: Queue processing complete');
}
Why This Is Safer
- Doesn't rely on protected methods - uses public
task()method - Direct database queries - we know exactly what batches exist
- Respects process locks - checks
is_processing()first - Detailed logging - you'll know exactly what happens
- Handles errors gracefully - won't crash if something's wrong
- Cleans up after itself - deletes batches and clears cron
How to Test IMMEDIATELY
You have 187 users already queued, so:
# 1. Deploy the mu-plugin to test first
# (Copy code to wp-content/mu-plugins/mailoptin-pantheon-fix.php)
# 2. Commit and push
# 3. Deploy to test environment
# 4. Manually trigger to test
terminus wp completejerry.test -- cron event run wp_1_mo_wp_mail_bg_process_cron
# 5. Check the logs
# You should see:
# "MailOptin Pantheon: Found 1 batch(es) to process"
# "MailOptin Pantheon: Processing batch with 187 items"
# "MailOptin Pantheon: Processed email for [email protected]"
# ... (187 times)
# "MailOptin Pantheon: Queue processing complete"
# 6. Verify queue is empty
terminus wp completejerry.test -- option list --search="*mo_wp_mail_bg_process_batch*" --format=count
# Should return: 0
# 7. Check Mailgun dashboard for 187 sent emails
# 8. If successful, deploy to live
Alternative: Even Simpler Test First
If you want to test the theory right now without deploying code:
# Just manually trigger the existing cron and see what happens
terminus wp completejerry.live -- cron event run wp_1_mo_wp_mail_bg_process_cron
# Check if queue is still there
terminus wp completejerry.live -- option get wp_1_mo_wp_mail_bg_process_batch_938991b3f8828ae826ddfcc76c72d63
# If it still exists (likely), then the async dispatch is definitely failing
# If it's gone, emails sent! Problem might have been a one-time thing