Automattic\WooCommerce\Internal\BatchProcessing

BatchProcessingController::remove_processorpublicWC 1.0

Dequeue and de-schedule a processor instance so that it won't be processed anymore.

Method of the class: BatchProcessingController{}

No Hooks.

Returns

true|false. True if the processor has been dequeued, false if the processor wasn't enqueued (so nothing has been done).

Usage

$BatchProcessingController = new BatchProcessingController();
$BatchProcessingController->remove_processor( $processor_class_name ): bool;
$processor_class_name(string) (required)
Fully qualified class name of the processor.

BatchProcessingController::remove_processor() code WC 11.0.1

public function remove_processor( string $processor_class_name ): bool {
	// Resolve membership authoritatively inside the lock (no unguarded fast-path read). remove_processor() is
	// not a per-request hot path — the continuous-sync 'shutdown' handler enqueues rather than removes — so it
	// always takes the lock and re-reads the freshest list rather than acting on a possibly-stale cached copy.
	$was_enqueued         = false;
	$remaining_processors = $this->mutate_enqueued_processors(
		function ( array $enqueued_processors ) use ( $processor_class_name, &$was_enqueued ): array {
			if ( ! in_array( $processor_class_name, $enqueued_processors, true ) ) {
				return $enqueued_processors;
			}
			$was_enqueued = true;
			return array_values( array_diff( $this->sanitize_processor_list( $enqueued_processors ), array( $processor_class_name ) ) );
		}
	);

	if ( ! $was_enqueued ) {
		return false;
	}

	/*
	 * $remaining_processors is the list exactly as persisted inside the critical section above, so the empty
	 * check is decided from the lock-guarded snapshot rather than a second, unguarded re-read (which would only
	 * ever see this request's own post-mutation value anyway). When that snapshot is empty we unschedule every
	 * single-batch action to sweep up any orphaned "ghost" actions left in Action Scheduler for processors that
	 * are no longer enqueued; otherwise only the removed processor's own scheduling needs tearing down, so we
	 * unschedule by class name.
	 *
	 * This intentionally does NOT unschedule the watchdog: handle_watchdog_action() returns without rescheduling
	 * itself once the list is empty (so a lingering watchdog fires at most once more and then stops), and leaving
	 * it in place is what makes the empty-list sweep safe. force_clear_all_processes() is deliberately avoided:
	 * its own unguarded read-modify-write would clobber a processor that a concurrent request enqueued in the gap
	 * after this mutation committed — the exact lost-update race this change exists to prevent.
	 *
	 * There is still a narrow window: a concurrent request can enqueue processor Q and have the watchdog schedule
	 * Q's single-batch action after our lock releases but before the sweep runs, in which case the sweep cancels
	 * Q's action even though Q remains enqueued. Q is never lost from the option (the source of truth), so this is
	 * a bounded scheduling delay, not a lost update: the watchdog we leave in place reschedules Q on its next run.
	 * That recovery is bounded by the watchdog delay (woocommerce_batch_processor_watchdog_delay_seconds), not the
	 * next request, because remove_or_retry_failed_processors() no-ops while any watchdog is already scheduled.
	 */
	if ( empty( $remaining_processors ) ) {
		as_unschedule_all_actions( self::PROCESS_SINGLE_BATCH_ACTION_NAME );
	} else {
		as_unschedule_all_actions( self::PROCESS_SINGLE_BATCH_ACTION_NAME, array( $processor_class_name ) );
	}
	$this->clear_processor_state( $processor_class_name );

	return true;
}