Purpose
The cron-task registry. Sibling plugins register their scheduled tasks by appending entries to the array passed through this filter. The mam_setcron_processor AJAX endpoint (pinged by FastCron on every tick) walks the registry and dispatches tasks whose schedule matches “now”.
25+ subscribers across mam-suite-hold and the use-case plugins.
Signature
$crons = apply_filters( 'mam_cron_manager', array $crons );
| Parameter | Type | Description |
|---|---|---|
$crons |
array | Map of cron_id => definition |
Returns: array — the augmented map.
Cron entry shape
array(
'my_plugin_nightly_sync' => array(
'title' => 'Nightly Sync',
'expression' => '0 2 * * *', // standard cron syntax
'callback' => 'my_plugin_nightly_sync_action',
),
// ...
)
| Field | Purpose |
|---|---|
title |
Human-readable label for the admin grid |
expression |
Cron-syntax schedule (0 2 * * * = 2am daily) |
callback |
Function name (string) — invoked via apply_filters($cron_id, []) |
The cron id (the key) is the dispatch handle. It must be unique site-wide.
Example: register a cron
add_filter( 'mam_cron_manager', function ( array $crons ): array {
$crons['my_plugin_nightly_sync'] = array(
'title' => 'My Plugin: Nightly Sync',
'expression' => '0 2 * * *',
'callback' => 'my_plugin_nightly_sync_action',
);
return $crons;
} );
// The callback registered against the dispatch hook (cron id):
function my_plugin_nightly_sync_action( $unused = array() ) {
// do the work
// return value is discarded
}
add_filter( 'my_plugin_nightly_sync', 'my_plugin_nightly_sync_action' );
⚠️ Note: per-cron callbacks are invoked via apply_filters( $cron_id, array() ), not do_action. This is for return-value compatibility with older callbacks. Treat your return value as discarded.
How dispatch works
mam_setcron_manager::mam_setcron_processor():
On every FastCron tick (typically every 1–5 minutes):
1. Resolve current time + timezone (wp_timezone_string())
2. $crons = apply_filters('mam_cron_manager', array());
3. For each cron entry:
- Evaluate `expression` against "now"
- If schedule matches: apply_filters($cron_id, array())
Multiple crons matching the same tick run serially.
Cron expression gotchas
- Standard 5-field cron syntax. Minute / hour / day-of-month / month / day-of-week.
- Time zone matters. The processor uses
wp_timezone_string(). A site set toAsia/Kolkata(+05:30) evaluates expressions in IST. - Off-set zones (e.g.,
+05:30) fall back through twotimezone_name_from_abbrattempts. Failed lookups silently fall through to UTC. Use named timezones where possible. - FastCron’s resolution is the real ceiling — if FastCron pings every 5 minutes, a
* * * * *cron runs every 5 minutes, not every minute.
Common cron tasks
| Cron id | Source | Purpose |
|---|---|---|
mam_mail_handler |
mam_mail_manager |
Drain email + PN/SMS queues |
mam_custom_notifications |
mam_message_and_notification_manager |
Trigger scheduled custom notifications |
| (sibling-plugin specific) | various | Per-plugin scheduled work |
Gotchas
- Cron id must be unique. Two plugins registering the same id produce dispatch ambiguity; the second registration overwrites the first.
apply_filtersnotdo_action. Return values are discarded; this is for compat with old callbacks.- No retry semantics. A failed cron callback isn’t retried until the next tick that matches its expression.
- Long-running callbacks block other crons on the same tick. Keep work short or move to a queue + drain pattern.
- Time-zone resolution can silently fall through to UTC for offset-style timezones.
- FastCron must be configured for crons to fire — see Integration: FastCron.
Related articles
- Integration: FastCron
- Notification queue and cron
- Recipe: Register a scheduled cron task
Metadata
| Field | Value |
|---|---|
| Article type | Hook Reference |
| Plugin slug | mam-main |
| Applies to plugin version | 2.1.11+ |
| Hook type | filter |
| Audience | PHP developer |
| Frozen contract | yes — 25+ subscribers |
| Last verified | 2026-05-02 |
