PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 2.8.16
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v2.8.16
3.13.3 3.13.2 3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 All 261 releases
wpfunnels / packages / action-scheduler / classes / ActionScheduler_QueueRunner.php

ActionScheduler_QueueRunner.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 2.8.16, at packages/action-scheduler/classes/ActionScheduler_QueueRunner.php

203 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class ActionScheduler_QueueRunner
5 */
6 class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
7 const WP_CRON_HOOK = 'action_scheduler_run_queue';
8
9 const WP_CRON_SCHEDULE = 'every_minute';
10
11 /**
12 * @var ActionScheduler_AsyncRequest_QueueRunner
13 */
14 protected $async_request;
15
16 /**
17 * @var ActionScheduler_QueueRunner
18 */
19 private static $runner = null;
20
21 /**
22 * @return ActionScheduler_QueueRunner
23 * @codeCoverageIgnore
24 */
25 public static function instance() {
26 if ( empty(self::$runner) ) {
27 $class = apply_filters('action_scheduler_queue_runner_class', 'ActionScheduler_QueueRunner');
28 self::$runner = new $class();
29 }
30 return self::$runner;
31 }
32
33 /**
34 * ActionScheduler_QueueRunner constructor.
35 *
36 * @param ActionScheduler_Store $store
37 * @param ActionScheduler_FatalErrorMonitor $monitor
38 * @param ActionScheduler_QueueCleaner $cleaner
39 */
40 public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null, ActionScheduler_AsyncRequest_QueueRunner $async_request = null ) {
41 parent::__construct( $store, $monitor, $cleaner );
42
43 if ( is_null( $async_request ) ) {
44 $async_request = new ActionScheduler_AsyncRequest_QueueRunner( $this->store );
45 }
46
47 $this->async_request = $async_request;
48 }
49
50 /**
51 * @codeCoverageIgnore
52 */
53 public function init() {
54
55 add_filter( 'cron_schedules', array( self::instance(), 'add_wp_cron_schedule' ) );
56
57 // Check for and remove any WP Cron hook scheduled by Action Scheduler < 3.0.0, which didn't include the $context param
58 $next_timestamp = wp_next_scheduled( self::WP_CRON_HOOK );
59 if ( $next_timestamp ) {
60 wp_unschedule_event( $next_timestamp, self::WP_CRON_HOOK );
61 }
62
63 $cron_context = array( 'WP Cron' );
64
65 if ( ! wp_next_scheduled( self::WP_CRON_HOOK, $cron_context ) ) {
66 $schedule = apply_filters( 'action_scheduler_run_schedule', self::WP_CRON_SCHEDULE );
67 wp_schedule_event( time(), $schedule, self::WP_CRON_HOOK, $cron_context );
68 }
69
70 add_action( self::WP_CRON_HOOK, array( self::instance(), 'run' ) );
71 $this->hook_dispatch_async_request();
72 }
73
74 /**
75 * Hook check for dispatching an async request.
76 */
77 public function hook_dispatch_async_request() {
78 add_action( 'shutdown', array( $this, 'maybe_dispatch_async_request' ) );
79 }
80
81 /**
82 * Unhook check for dispatching an async request.
83 */
84 public function unhook_dispatch_async_request() {
85 remove_action( 'shutdown', array( $this, 'maybe_dispatch_async_request' ) );
86 }
87
88 /**
89 * Check if we should dispatch an async request to process actions.
90 *
91 * This method is attached to 'shutdown', so is called frequently. To avoid slowing down
92 * the site, it mitigates the work performed in each request by:
93 * 1. checking if it's in the admin context and then
94 * 2. haven't run on the 'shutdown' hook within the lock time (60 seconds by default)
95 * 3. haven't exceeded the number of allowed batches.
96 *
97 * The order of these checks is important, because they run from a check on a value:
98 * 1. in memory - is_admin() maps to $GLOBALS or the WP_ADMIN constant
99 * 2. in memory - transients use autoloaded options by default
100 * 3. from a database query - has_maximum_concurrent_batches() run the query
101 * $this->store->get_claim_count() to find the current number of claims in the DB.
102 *
103 * If all of these conditions are met, then we request an async runner check whether it
104 * should dispatch a request to process pending actions.
105 */
106 public function maybe_dispatch_async_request() {
107 if ( is_admin() && ! ActionScheduler::lock()->is_locked( 'async-request-runner' ) ) {
108 // Only start an async queue at most once every 60 seconds
109 ActionScheduler::lock()->set( 'async-request-runner' );
110 $this->async_request->maybe_dispatch();
111 }
112 }
113
114 /**
115 * Process actions in the queue. Attached to self::WP_CRON_HOOK i.e. 'action_scheduler_run_queue'
116 *
117 * The $context param of this method defaults to 'WP Cron', because prior to Action Scheduler 3.0.0
118 * that was the only context in which this method was run, and the self::WP_CRON_HOOK hook had no context
119 * passed along with it. New code calling this method directly, or by triggering the self::WP_CRON_HOOK,
120 * should set a context as the first parameter. For an example of this, refer to the code seen in
121 *
122 * @see ActionScheduler_AsyncRequest_QueueRunner::handle()
123 *
124 * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
125 * Generally, this should be capitalised and not localised as it's a proper noun.
126 * @return int The number of actions processed.
127 */
128 public function run( $context = 'WP Cron' ) {
129 ActionScheduler_Compatibility::raise_memory_limit();
130 ActionScheduler_Compatibility::raise_time_limit( $this->get_time_limit() );
131 do_action( 'action_scheduler_before_process_queue' );
132 $this->run_cleanup();
133 $processed_actions = 0;
134 if ( false === $this->has_maximum_concurrent_batches() ) {
135 $batch_size = apply_filters( 'action_scheduler_queue_runner_batch_size', 25 );
136 do {
137 $processed_actions_in_batch = $this->do_batch( $batch_size, $context );
138 $processed_actions += $processed_actions_in_batch;
139 } while ( $processed_actions_in_batch > 0 && ! $this->batch_limits_exceeded( $processed_actions ) ); // keep going until we run out of actions, time, or memory
140 }
141
142 do_action( 'action_scheduler_after_process_queue' );
143 return $processed_actions;
144 }
145
146 /**
147 * Process a batch of actions pending in the queue.
148 *
149 * Actions are processed by claiming a set of pending actions then processing each one until either the batch
150 * size is completed, or memory or time limits are reached, defined by @see $this->batch_limits_exceeded().
151 *
152 * @param int $size The maximum number of actions to process in the batch.
153 * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
154 * Generally, this should be capitalised and not localised as it's a proper noun.
155 * @return int The number of actions processed.
156 */
157 protected function do_batch( $size = 100, $context = '' ) {
158 $claim = $this->store->stake_claim($size);
159 $this->monitor->attach($claim);
160 $processed_actions = 0;
161
162 foreach ( $claim->get_actions() as $action_id ) {
163 // bail if we lost the claim
164 if ( ! in_array( $action_id, $this->store->find_actions_by_claim_id( $claim->get_id() ) ) ) {
165 break;
166 }
167 $this->process_action( $action_id, $context );
168 $processed_actions++;
169
170 if ( $this->batch_limits_exceeded( $processed_actions ) ) {
171 break;
172 }
173 }
174 $this->store->release_claim($claim);
175 $this->monitor->detach();
176 $this->clear_caches();
177 return $processed_actions;
178 }
179
180 /**
181 * Running large batches can eat up memory, as WP adds data to its object cache.
182 *
183 * If using a persistent object store, this has the side effect of flushing that
184 * as well, so this is disabled by default. To enable:
185 *
186 * add_filter( 'action_scheduler_queue_runner_flush_cache', '__return_true' );
187 */
188 protected function clear_caches() {
189 if ( ! wp_using_ext_object_cache() || apply_filters( 'action_scheduler_queue_runner_flush_cache', false ) ) {
190 wp_cache_flush();
191 }
192 }
193
194 public function add_wp_cron_schedule( $schedules ) {
195 $schedules['every_minute'] = array(
196 'interval' => 60, // in seconds
197 'display' => __( 'Every minute', 'woocommerce' ),
198 );
199
200 return $schedules;
201 }
202 }
203