$status, 'per_page' => 100, 'group' => $group, ) ); $count += is_array( $actions ) ? count( $actions ) : 0; } return $count; } /** * Summarize pending/in-progress agile_events_processing actions for logs. * * @return string */ function agile_tix_describe_pending_actions( $group = 'agile_events_processing' ) { if ( ! function_exists( 'as_get_scheduled_actions' ) ) { return 'AS unavailable'; } $parts = array(); foreach ( array( 'pending', 'in-progress' ) as $status ) { $actions = as_get_scheduled_actions( array( 'status' => $status, 'per_page' => 20, 'group' => $group, ) ); if ( ! is_array( $actions ) || empty( $actions ) ) { $parts[] = $status . '=0'; continue; } $hooks = array(); foreach ( $actions as $action ) { $hook = method_exists( $action, 'get_hook' ) ? $action->get_hook() : 'unknown'; $id = method_exists( $action, 'get_id' ) ? $action->get_id() : '?'; $hooks[] = $hook . '#' . $id; } $extra = count( $actions ) >= 20 ? ' (capped at 20 listed)' : ''; $parts[] = $status . '=' . count( $actions ) . ' [' . implode( ', ', $hooks ) . ']' . $extra; } return implode( '; ', $parts ); } /** * Process due Action Scheduler actions in the current request. * * Needed when DISABLE_WP_CRON is set and/or AS async loopback fails (common on staging). * Does not schedule WP-Cron refresh events — only drains already-queued batch work. * * @param string $context Label for AS / logs. * @return int Number of actions processed, or -1 if runner unavailable. */ function agile_tix_maybe_run_due_actions( $context = 'AgileTix' ) { static $running = false; if ( $running ) { return 0; } if ( ! class_exists( 'ActionScheduler_QueueRunner', false ) ) { if ( class_exists( 'agile_tix' ) ) { agile_tix::agile_tix_log_event( "AS queue kick ($context): QueueRunner unavailable" ); } return -1; } $running = true; $processed = 0; try { $processed = (int) ActionScheduler_QueueRunner::instance()->run( $context ); } catch ( Exception $e ) { if ( class_exists( 'agile_tix' ) ) { agile_tix::agile_tix_log_event( "AS queue kick ($context): EXCEPTION " . $e->getMessage() ); } $running = false; return -1; } $running = false; if ( class_exists( 'agile_tix' ) ) { agile_tix::agile_tix_log_event( "AS queue kick ($context): processed=$processed" . ' | DISABLE_WP_CRON=' . ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ? 'yes' : 'no' ) . ' | AS=' . agile_tix_describe_pending_actions() ); } return $processed; } /** * Ensure due actions get another drain attempt at end of this PHP request. */ function agile_tix_schedule_queue_kick_on_shutdown() { static $hooked = false; if ( $hooked ) { return; } $hooked = true; add_action( 'shutdown', static function () { agile_tix_maybe_run_due_actions( 'AgileTix Shutdown' ); }, 100 ); } /** * After scheduling batch/finalize work: run due actions now and once more on shutdown. * * @param string $context Label for AS / logs. * @return int Actions processed by the immediate kick. */ function agile_tix_kick_queue_after_schedule( $context = 'AgileTix' ) { agile_tix_schedule_queue_kick_on_shutdown(); return agile_tix_maybe_run_due_actions( $context ); }