draining -> disabled state machine. * * Disabling must never strand mail that is already queued: the interceptor * stops queueing immediately, but the worker keeps draining what is there. * * @package studiou-wc-mail-queue * @copyright 2026 QUADARAX * @author Dalibor Votruba * @license GPL-2.0-or-later */ defined( 'ABSPATH' ) || exit; /** * Class Studiou_WCMQ_State */ class Studiou_WCMQ_State { /** * Register hooks. */ public static function init() { // A queue emptied by retention or by manual deletion still needs to settle. add_action( 'admin_init', array( __CLASS__, 'maybe_settle' ) ); } /** * Current state. * * @return string */ public static function get() { return Studiou_WCMQ_Settings::state(); } /** * Whether new mail should be queued right now. * * @return bool */ public static function is_queueing() { return Studiou_WCMQ_Settings::STATE_ENABLED === self::get(); } /** * Turn queueing on. */ public static function enable() { Studiou_WCMQ_Settings::set_state( Studiou_WCMQ_Settings::STATE_ENABLED ); Studiou_WCMQ_DB::log( 'info', 'Queue enabled.' ); } /** * Turn queueing off, draining first if anything is in flight. */ public static function disable() { if ( Studiou_WCMQ_DB::count_unfinished() > 0 ) { Studiou_WCMQ_Settings::set_state( Studiou_WCMQ_Settings::STATE_DRAINING ); Studiou_WCMQ_DB::log( 'info', 'Queue draining; new mail sends synchronously.' ); return; } Studiou_WCMQ_Settings::set_state( Studiou_WCMQ_Settings::STATE_DISABLED ); Studiou_WCMQ_DB::log( 'info', 'Queue disabled.' ); } /** * Move draining -> disabled once nothing is left in flight. * * Called by the worker after each send and on admin_init. */ public static function maybe_settle() { if ( Studiou_WCMQ_Settings::STATE_DRAINING !== self::get() ) { return; } if ( Studiou_WCMQ_DB::count_unfinished() > 0 ) { return; } Studiou_WCMQ_Settings::set_state( Studiou_WCMQ_Settings::STATE_DISABLED ); Studiou_WCMQ_DB::log( 'info', 'Queue drained; now disabled.' ); } }