Skip to content

Cron Jobs

The plugin uses a single WP-Cron event to detect and publish activities when their scheduled time arrives.

The cron event is registered on WordPress’s init hook:

if ( ! wp_next_scheduled( 'buddypress_schedule_activity_publish' ) ) {
$frequency = apply_filters( 'buddypress_schedule_activity_frequency', 'bp_every_min' );
wp_schedule_event( time(), $frequency, 'buddypress_schedule_activity_publish' );
}

The custom bp_every_min schedule (60 seconds) is registered via the cron_schedules filter:

$schedules['bp_every_min'] = array(
'interval' => MINUTE_IN_SECONDS, // 60
'display' => __( 'Every minute', 'buddypress-schedule-activity' ),
);

The buddypress_check_schedule_activity_publish function runs on every cron tick:

  1. Acquire lock — Checks the bpsa_publish_lock transient. If another process already holds it, exits immediately. Otherwise sets the transient for 60 seconds.

  2. Query due activities — Fetches all activities where date_recorded <= current_time() and _bp_activity_status = 'scheduled'.

  3. Atomic status update — Updates each row’s meta value from 'scheduled' to 'publishing' using a WHERE clause that requires meta_value = 'scheduled'. This prevents two overlapping cron workers from publishing the same activity twice.

  4. Publish — For each activity that was successfully marked 'publishing':

    • Deletes the _bp_activity_status meta entirely (making the activity visible in the feed)
    • Updates date_recorded to current_time( 'mysql' ) so the activity appears as “posted now” in the feed
  5. Release lock — Deletes the bpsa_publish_lock transient.

Errors at each step are written to the PHP error log with the prefix BPSA Cron Error: or BPSA Cron Warning:.

WP-Cron fires based on page requests — the event will not run until a page loads after the scheduled time. On a low-traffic site, activities may be delayed beyond the 1-minute window. The typical real-world delay is 1-2 minutes on a site with regular traffic.

For precise timing, replace WP-Cron with a real server cron job (see below).

// Check when the next run is scheduled.
$next = wp_next_scheduled( 'buddypress_schedule_activity_publish' );
if ( $next ) {
echo 'Next run: ' . date( 'Y-m-d H:i:s', $next );
} else {
echo 'Not scheduled — will register on next page load.';
}

Using WP-CLI:

Terminal window
wp cron event list

Look for buddypress_schedule_activity_publish in the output. If it does not appear, the plugin may not have loaded due to a missing BuddyPress dependency.

If activities stop publishing but the cron event is still registered, the transient lock may be stuck. This can happen if PHP crashed mid-run before the lock was released.

// Inspect the lock (returns true if stuck, false/null if clear).
$lock = get_transient( 'bpsa_publish_lock' );
var_dump( $lock );
// Clear a stuck lock.
delete_transient( 'bpsa_publish_lock' );

Disable WP-Cron and trigger it externally for reliable per-minute delivery:

  1. In wp-config.php:

    define( 'DISABLE_WP_CRON', true );
  2. Add a crontab entry on the server:

    Terminal window
    # Run every minute.
    * * * * * wget -q -O /dev/null "https://example.com/wp-cron.php?doing_wp_cron" >/dev/null 2>&1

    Or with WP-CLI (preferred — avoids HTTP overhead):

    Terminal window
    * * * * * /usr/local/bin/wp cron event run buddypress_schedule_activity_publish --path=/var/www/example.com >/dev/null 2>&1

See buddypress_schedule_activity_frequency in the Hooks and Filters reference.

After changing the filter, force re-registration:

// Run once — in a plugin activation hook or from a WP-CLI command.
wp_clear_scheduled_hook( 'buddypress_schedule_activity_publish' );

On the next page load, init will register a new event with the new frequency.