Notification queue and cron

Summary

The notification dispatcher decides per batch whether to send immediately (wp_mail() / $sms->SendSMS() / APNs/FCM directly) or to queue for cron processing. Queueing kicks in for batches of >10 messages when the global mam_notification_use_cron option is on.

mail-cron-manager (includes/mail-cron-manager/) owns the queue tables and the cron processor.


Queueing decision

$use_cron_if_available = count( $messages ) > 10;
$use_global_cron       = get_option( 'mam_notification_use_cron' ) == 1;
$use_cron              = $use_cron_if_available && $use_global_cron;

Both conditions must be true. A 5-message batch always sends immediately. A 50-message batch on a site with cron disabled also sends immediately (and likely overruns PHP’s request timeout — turn cron on for any site with regular bulk sends).


Queue tables

Table Channels Owner repository
wp_mam_mail_queue Email MAM_Mail_Queue_Repository
wp_mam_mail_attachments Email attachments MAM_Mail_Attachments_Repository
wp_mam_sms_queue SMS + PN (unified, channel flag) MAM_Sms_Queue_Repository

All three were renamed from wp_tsl_* in PR #31. Frozen — do not rename in place.

The wp_mam_sms_queue row carries a flag indicating channel: send_text=1 for SMS, send_pn=1 for push. A single row with both flags isn’t supported — fire one row per channel.


Cron processor

mam_cron_mail::mail_cron() (includes/mail-cron-manager/mam-mail-manager.php):

  1. Pulls a batch of 50 from wp_mam_mail_queue
  2. Sends each via wp_mail(); success → mark sent, failure → increment retry count
  3. Pulls a batch of 20 from wp_mam_sms_queue where sent=0
  4. For each row, dispatches per the send_text / send_pn flag
  5. Updates sent flag + retry count

Email retry: up to 3 attempts. After that the row is left as failed (audit-trail).

PN/SMS: no retry. A failed dispatch stays failed.


Cron registration

The mail-cron handler is registered with setcron-manager via mam_cron_manager:

add_filter( 'mam_cron_manager', array( $this, 'mam_cron_manager' ) );

mam_setcron_manager then pings the AJAX endpoint on every FastCron tick, which fires mam_mail_handler (registered as add_filter — anti-pattern noted; treat as fire-and-forget).

See FastCron integration.


Tuning batch sizes

The 50/20 split is hardcoded in mam_cron_mail::mail_cron(). To change for a high-volume site:

  • Increase 50 (email) carefully — wp_mail() is synchronous; large batches risk PHP timeout
  • Increase 20 (PN/SMS) carefully — APNs HTTP/2 connection isn’t pooled; high counts pay TCP setup per send

Either change is a code edit, not a setting.


Reads / writes

  • Tables: wp_mam_mail_queue, wp_mam_mail_attachments, wp_mam_sms_queue, wp_mam_notification_history
  • Options: tsl_mam_mail_manager, mam_notification_use_cron
  • Hooks: mam_mail_handler (cron tick), wp_mail_failed, wp_mail_from, wp_mail_from_name

Gotchas

  • mam_mail_handler is registered as add_filter even though it’s effectively an action — anti-pattern preserved for return-value compat with older callers.
  • No partial-failure retry semantics across channels. If a row’s email succeeds and SMS fails, the SMS portion is lost.
  • The shared wp_mam_sms_queue for PN+SMS means a sustained PN load slows SMS draining and vice versa. Heavy senders should consider splitting via custom processors.
  • Cron disabled = synchronous everything. A site with mam_notification_use_cron = 0 and a 1000-message custom-notification job will block the request that triggered it.

  • Notifications overview
  • Notification channels: email, SMS, push
  • FastCron integration
  • Hook: mam_cron_manager
  • Frozen public contracts reference

Metadata

Field Value
Article type Plugin Overview
Plugin slug mam-main
Applies to plugin version 2.1.11+
Category Plugin Reference
Audience PHP developer
Last verified 2026-05-02
Contents

    Need Support?

    Can’t find the answer you’re looking for? Don’t worry we’re here to help!