p)x D}QMDABÕz)0'Y/DH/0@?H1b,`@!|*Lxpװr'_'lq <)`qp@0}4}hf&"@ku:Hq:Ct^QqXL? \_XD=W{/aFG@)40@X0H@$EdP.`q3l s͗kdxq /pUcS7R'b 9q7 7e]F' |'a{X&NǕ$@ք|*0qZ/~/slHq`qCOeCxq*qAĐq ;zߕ1܏' }Pq0@ D@#Xo4h`-0@t$PtRHDqDsT`q*@ dxqD>fO|q(MCO@hcW3i@rsq۽#MB ׻40@wHqG0 [i (\`q"w`OlxΆmrRIa?i>HO@~qNy !;/F};snX/a 7$@3dX0@!j7H_c%-`H3|x@1uEx9qTg?_PR2qA8(_@5@՜`x@^ X5 hA48q:+V40:2a"9r qxYW$0(@Z4Hq0Lv/tL`x1JW0|x@9qs533ygq4.q&&7-hq wq(*/P q!9M0w9q%bZ.q::T$0ŲŅ3DHq9bn(T`@1þ:xq +Pߡl@q td`Vq(F@jM鬝HQ7D'mfx @ :'<<0<qo9 $0@v:رH@G8`@SW=x [u&@2@D͓9q?t t)ךd4cw h=q0ohl1Ch=qR!Tv)"aڋDU@Ý0@8xXHqq pAD`@KY:x@(J =@SUhq0 3 }tq$ɍ @Kȭ@MI( @yBs q'GmrO8i"h1q*0 a^IUHqxW<q|?HPM@W-oG?`qtxsհqĞ^J֐qDDF01qpPeZaPZ@ j1PDA/~8 88q86&[' 10p@&jiO@ 0@Jcx?Hp%'l`q4%xpj4$'@ @! *0.d&>A@qԇ$Xq'&<~/'?aY"$q3 b\<0prtr_'LH@i@`8PX5xqRF"$p|D^@"c8@qW_)zqq4~qIG_3y'"a&N>$@=PC0@ bHFL p`a{y@ x@aC@ <=P%q>eZGgq=/u/qqk6Ha /Lm|$DNO48T0424P D@DBx0@pH(1h+`+F:)xx̲2E()q|*c+1̨pQQ ڟ'$h;p@qXr.ޠ ')a9q F$0= +% H! =01hpG`qNw o2dx@9@pBsGPwmrG EU$@Aq80|:pL?F w' qB8D;̳P"'a\Hq u 40qoMݚ\Hq߄R/8 l`iTXEFsHcxq$$6q.~m/@A#$#.0cq_Qh(DsC0X#q2o{  j ܟh0\ I@-u I0@?8YHS=`,`ު"LA LXDxqgL@NH@#8mqLtq%33egȶ[=`aLxtY@a552n<8q} ٧P@MqX0qOjK=q"<f$0D38%4H@2ыK`q"WcLxq=<)7==Drow,HE4&[ `p&&r*'dxqb'C| } do_action( 'woocommerce_gla_debug_message', sprintf( 'The %s job has failed due to a timeout error, rescheduling...', $hook ), __METHOD__ ); $this->action_scheduler->schedule_immediate( $hook, $args ); } } /** * Determines whether the given error is an execution "timeout" error. * * @param array $error An associative array describing the error with keys "type", "message", "file" and "line". * * @return bool * * @link https://www.php.net/manual/en/function.error-get-last.php * * @since 1.7.0 */ protected function is_timeout_error( array $error ): bool { return isset( $error['type'] ) && $error['type'] === E_ERROR && isset( $error['message'] ) && strpos( $error ['message'], 'Maximum execution time' ) !== false; } /** * Check whether the job's failure rate is above the specified threshold within the timeframe. * * @param string $hook The job action hook. * @param array|null $args The job arguments. * * @return bool True if the job's error rate is above the threshold, and false otherwise. * * @see ActionSchedulerJobMonitor::get_failure_rate_threshold() * @see ActionSchedulerJobMonitor::get_failure_timeframe() * * @since 1.7.0 */ protected function is_failure_rate_above_threshold( string $hook, ?array $args = null ): bool { $failed_actions = $this->action_scheduler->search( [ 'hook' => $hook, 'args' => $args, 'status' => $this->action_scheduler::STATUS_FAILED, 'per_page' => $this->get_failure_rate_threshold(), 'date' => gmdate( 'U' ) - $this->get_failure_timeframe(), 'date_compare' => '>', ], 'ids' ); return count( $failed_actions ) >= $this->get_failure_rate_threshold(); } /** * Get the job failure rate threshold (per timeframe). * * @return int */ protected function get_failure_rate_threshold(): int { return absint( apply_filters( 'woocommerce_gla_job_failure_rate_threshold', 3 ) ); } /** * Get the job failure timeframe (in seconds). * * @return int */ protected function get_failure_timeframe(): int { return absint( apply_filters( 'woocommerce_gla_job_failure_timeframe', 2 * HOUR_IN_SECONDS ) ); } /** * Generates a unique hash (checksum) for each job using its hook name and arguments. * * @param string $hook * @param array|null $args * * @return string * * @since 1.7.0 */ protected static function get_job_hash( string $hook, ?array $args = null ): string { return hash( 'crc32b', $hook . json_encode( $args ) ); } /** * Determines whether the given set of job hook and arguments is monitored for timeout. * * @param string $hook * @param array|null $args * * @return bool * * @since 1.7.0 */ protected function is_monitored_for_timeout( string $hook, ?array $args = null ): bool { return isset( $this->monitored_hooks[ self::get_job_hash( $hook, $args ) ] ); } }