Warning: Undefined variable $config in /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-content/plugins/sg-cachepress/core/File_Cacher/Cache.php on line 55
Warning: foreach() argument must be of type array|object, null given in /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-content/plugins/sg-cachepress/core/File_Cacher/Cache.php on line 55
Warning: Undefined property: SiteGround_Optimizer\File_Cacher\Cache::$logged_in_cache in /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-content/plugins/sg-cachepress/core/File_Cacher/Cache.php on line 156
up ) ) {
$group = $this->get_claim_filter( 'exclude-groups' );
$group_operator = 'NOT IN';
}
if ( ! empty( $group ) ) {
$group_ids = $this->get_group_ids( $group, false );
// throw exception if no matching group(s) found, this matches ActionScheduler_wpPostStore's behaviour.
if ( empty( $group_ids ) ) {
throw new InvalidArgumentException(
sprintf(
/* translators: %s: group name(s) */
_n(
'The group "%s" does not exist.',
'The groups "%s" do not exist.',
is_array( $group ) ? count( $group ) : 1,
'woocommerce'
),
$group
)
);
}
$id_list = implode( ',', array_map( 'intval', $group_ids ) );
$where .= " AND group_id {$group_operator} ( $id_list )";
}
/**
* Sets the order-by clause used in the action claim query.
*
* @param string $order_by_sql
* @param string $claim_id Claim Id.
* @param array $hooks Hooks to filter for.
*
* @since 3.8.3 Made $claim_id and $hooks available.
* @since 3.4.0
*/
$order = apply_filters( 'action_scheduler_claim_actions_order_by', 'ORDER BY priority ASC, attempts ASC, scheduled_date_gmt ASC, action_id ASC', $claim_id, $hooks );
$skip_locked = $this->db_supports_skip_locked() ? ' SKIP LOCKED' : '';
// Selecting the action_ids that we plan to claim, while skipping any locked rows to avoid deadlocking.
$select_sql = $wpdb->prepare( "SELECT action_id from {$wpdb->actionscheduler_actions} {$where} {$order} LIMIT %d FOR UPDATE{$skip_locked}", array_merge( $where_params, array( $limit ) ) );
// Now place it into an UPDATE statement by joining the result sets, allowing for the SKIP LOCKED behavior to take effect.
$update_sql = "UPDATE {$wpdb->actionscheduler_actions} t1 JOIN ( $select_sql ) t2 ON t1.action_id = t2.action_id SET claim_id=%d, last_attempt_gmt=%s, last_attempt_local=%s";
$update_params = array(
$claim_id,
$now->format( 'Y-m-d H:i:s' ),
current_time( 'mysql' ),
);
$rows_affected = $wpdb->query( $wpdb->prepare( $update_sql, $update_params ) );
if ( false === $rows_affected ) {
$error = empty( $wpdb->last_error )
? _x( 'unknown', 'database error', 'woocommerce' )
: $wpdb->last_error;
throw new \RuntimeException(
sprintf(
/* translators: %s database error. */
__( 'Unable to claim actions. Database error: %s.', 'woocommerce' ),
$error
)
);
}
return (int) $rows_affected;
}
/**
* Determines whether the database supports using SKIP LOCKED. This logic mimicks the $wpdb::has_cap() logic.
*
* SKIP_LOCKED support was added to MariaDB in 10.6.0 and to MySQL in 8.0.1
*
* @return bool
*/
private function db_supports_skip_locked() {
global $wpdb;
$db_version = $wpdb->db_version();
$db_server_info = $wpdb->db_server_info();
$is_mariadb = ( false !== strpos( $db_server_info, 'MariaDB' ) );
if ( $is_mariadb &&
'5.5.5' === $db_version &&
PHP_VERSION_ID < 80016 // PHP 8.0.15 or older.
) {
/*
* Account for MariaDB version being prefixed with '5.5.5-' on older PHP versions.
*/
$db_server_info = preg_replace( '/^5\.5\.5-(.*)/', '$1', $db_server_info );
$db_version = preg_replace( '/[^0-9.].*/', '', $db_server_info );
}
$is_supported = ( $is_mariadb && version_compare( $db_version, '10.6.0', '>=' ) ) ||
( ! $is_mariadb && version_compare( $db_version, '8.0.1', '>=' ) );
/**
* Filter whether the database supports the SKIP LOCKED modifier for queries.
*
* @param bool $is_supported Whether SKIP LOCKED is supported.
*
* @since 3.9.3
*/
return apply_filters( 'action_scheduler_db_supports_skip_locked', $is_supported );
}
/**
* Get the number of active claims.
*
* @return int
*/
public function get_claim_count() {
global $wpdb;
$sql = "
SELECT COUNT(*)
FROM {$wpdb->actionscheduler_claims} c
WHERE EXISTS (
SELECT 1
FROM {$wpdb->actionscheduler_actions} a
WHERE a.claim_id = c.claim_id
AND a.status IN ( %s, %s )
)
";
$sql = $wpdb->prepare( $sql, array( self::STATUS_PENDING, self::STATUS_RUNNING ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
return (int) $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Return an action's claim ID, as stored in the claim_id column.
*
* @param string $action_id Action ID.
* @return mixed
*/
public function get_claim_id( $action_id ) {
/**
* Global.
*
* @var \wpdb $wpdb
*/
global $wpdb;
$sql = "SELECT claim_id FROM {$wpdb->actionscheduler_actions} WHERE action_id=%d";
$sql = $wpdb->prepare( $sql, $action_id ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
return (int) $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Retrieve the action IDs of action in a claim.
*
* @param int $claim_id Claim ID.
* @return int[]
*/
public function find_actions_by_claim_id( $claim_id ) {
/**
* Global.
*
* @var \wpdb $wpdb
*/
global $wpdb;
$action_ids = array();
$before_date = isset( $this->claim_before_date ) ? $this->claim_before_date : as_get_datetime_object();
$cut_off = $before_date->format( 'Y-m-d H:i:s' );
$sql = $wpdb->prepare(
"SELECT action_id, scheduled_date_gmt FROM {$wpdb->actionscheduler_actions} WHERE claim_id = %d ORDER BY priority ASC, attempts ASC, scheduled_date_gmt ASC, action_id ASC",
$claim_id
);
// Verify that the scheduled date for each action is within the expected bounds (in some unusual
// cases, we cannot depend on MySQL to honor all of the WHERE conditions we specify).
foreach ( $wpdb->get_results( $sql ) as $claimed_action ) { // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
if ( $claimed_action->scheduled_date_gmt <= $cut_off ) {
$action_ids[] = absint( $claimed_action->action_id );
}
}
return $action_ids;
}
/**
* Release pending actions from a claim and delete the claim.
*
* @param ActionScheduler_ActionClaim $claim Claim object.
* @throws \RuntimeException When unable to release actions from claim.
*/
public function release_claim( ActionScheduler_ActionClaim $claim ) {
/**
* Global.
*
* @var \wpdb $wpdb
*/
global $wpdb;
if ( 0 === intval( $claim->get_id() ) ) {
// Verify that the claim_id is valid before attempting to release it.
return;
}
/**
* Deadlock warning: This function modifies actions to release them from claims that have been processed. Earlier, we used to it in a atomic query, i.e. we would update all actions belonging to a particular claim_id with claim_id = 0.
* While this was functionally correct, it would cause deadlock, since this update query will hold a lock on the claim_id_.. index on the action table.
* This allowed the possibility of a race condition, where the claimer query is also running at the same time, then the claimer query will also try to acquire a lock on the claim_id_.. index, and in this case if claim release query has already progressed to the point of acquiring the lock, but have not updated yet, it would cause a deadlock.
*
* We resolve this by getting all the actions_id that we want to release claim from in a separate query, and then releasing the claim on each of them. This way, our lock is acquired on the action_id index instead of the claim_id index. Note that the lock on claim_id will still be acquired, but it will only when we actually make the update, rather than when we select the actions.
*
* We only release pending actions in order for them to be claimed by another process.
*/
$action_ids = $wpdb->get_col( $wpdb->prepare( "SELECT action_id FROM {$wpdb->actionscheduler_actions} WHERE claim_id = %d AND status = %s", $claim->get_id(), self::STATUS_PENDING ) );
$row_updates = 0;
if ( count( $action_ids ) > 0 ) {
$action_id_string = implode( ',', array_map( 'absint', $action_ids ) );
$row_updates = $wpdb->query( "UPDATE {$wpdb->actionscheduler_actions} SET claim_id = 0 WHERE action_id IN ({$action_id_string})" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
$wpdb->delete( $wpdb->actionscheduler_claims, array( 'claim_id' => $claim->get_id() ), array( '%d' ) );
if ( $row_updates < count( $action_ids ) ) {
throw new RuntimeException(
sprintf(
// translators: %d is an id.
__( 'Unable to release actions from claim id %d.', 'woocommerce' ),
$claim->get_id()
)
);
}
}
/**
* Remove the claim from an action.
*
* @param int $action_id Action ID.
*
* @return void
*/
public function unclaim_action( $action_id ) {
/**
* Global.
*
* @var \wpdb $wpdb
*/
global $wpdb;
$wpdb->update(
$wpdb->actionscheduler_actions,
array( 'claim_id' => 0 ),
array( 'action_id' => $action_id ),
array( '%s' ),
array( '%d' )
);
}
/**
* Mark an action as failed.
*
* @param int $action_id Action ID.
* @throws \InvalidArgumentException Throw an exception if action was not updated.
*/
public function mark_failure( $action_id ) {
/**
* Global.
* @var \wpdb $wpdb
*/
global $wpdb;
$updated = $wpdb->update(
$wpdb->actionscheduler_actions,
array(
'status' => self::STATUS_FAILED,
'last_attempt_gmt' => current_time( 'mysql', true ),
'last_attempt_local' => current_time( 'mysql' ),
),
array( 'action_id' => $action_id ),
array( '%s', '%s', '%s' ),
array( '%d' )
);
if ( empty( $updated ) ) {
/* translators: %s is the action ID */
throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s: we were unable to mark this action as having failed. It may may have been deleted by another process.', 'woocommerce' ), $action_id ) );
}
}
/**
* Add execution message to action log.
*
* @throws Exception If the action status cannot be updated to self::STATUS_RUNNING ('in-progress').
*
* @param int $action_id Action ID.
*
* @return void
*/
public function log_execution( $action_id ) {
/**
* Global.
*
* @var \wpdb $wpdb
*/
global $wpdb;
$sql = "UPDATE {$wpdb->actionscheduler_actions} SET attempts = attempts+1, status=%s, last_attempt_gmt = %s, last_attempt_local = %s WHERE action_id = %d";
$sql = $wpdb->prepare( $sql, self::STATUS_RUNNING, current_time( 'mysql', true ), current_time( 'mysql' ), $action_id ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$status_updated = $wpdb->query( $sql );
if ( ! $status_updated ) {
throw new Exception(
sprintf(
/* translators: 1: action ID. 2: status slug. */
__( 'Unable to update the status of action %1$d to %2$s.', 'woocommerce' ),
$action_id,
self::STATUS_RUNNING
)
);
}
}
/**
* Mark an action as complete.
*
* @param int $action_id Action ID.
*
* @return void
* @throws \InvalidArgumentException Throw an exception if action was not updated.
*/
public function mark_complete( $action_id ) {
/**
* Global.
*
* @var \wpdb $wpdb
*/
global $wpdb;
$updated = $wpdb->update(
$wpdb->actionscheduler_actions,
array(
'status' => self::STATUS_COMPLETE,
'last_attempt_gmt' => current_time( 'mysql', true ),
'last_attempt_local' => current_time( 'mysql' ),
),
array( 'action_id' => $action_id ),
array( '%s', '%s', '%s' ),
array( '%d' )
);
if ( empty( $updated ) ) {
/* translators: %s is the action ID */
throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s: we were unable to mark this action as having completed. It may may have been deleted by another process.', 'woocommerce' ), $action_id ) );
}
/**
* Fires after a scheduled action has been completed.
*
* @since 3.4.2
*
* @param int $action_id Action ID.
*/
do_action( 'action_scheduler_completed_action', $action_id );
}
/**
* Get an action's status.
*
* @param int $action_id Action ID.
*
* @return string
* @throws \InvalidArgumentException Throw an exception if not status was found for action_id.
* @throws \RuntimeException Throw an exception if action status could not be retrieved.
*/
public function get_status( $action_id ) {
/**
* Global.
*
* @var \wpdb $wpdb
*/
global $wpdb;
$sql = "SELECT status FROM {$wpdb->actionscheduler_actions} WHERE action_id=%d";
$sql = $wpdb->prepare( $sql, $action_id ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$status = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
if ( is_null( $status ) ) {
throw new \InvalidArgumentException( __( 'Invalid action ID. No status found.', 'woocommerce' ) );
} elseif ( empty( $status ) ) {
throw new \RuntimeException( __( 'Unknown status found for action.', 'woocommerce' ) );
} else {
return $status;
}
}
}
Fatal error: Uncaught Error: Class "ActionScheduler_DBStore" not found in /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-content/plugins/woocommerce/packages/action-scheduler/classes/abstracts/ActionScheduler_Store.php:502
Stack trace:
#0 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-content/plugins/woocommerce/packages/action-scheduler/classes/abstracts/ActionScheduler.php(48): ActionScheduler_Store::instance()
#1 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-content/plugins/woocommerce/packages/action-scheduler/classes/abstracts/ActionScheduler.php(187): ActionScheduler::store()
#2 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-content/plugins/woocommerce/packages/action-scheduler/action-scheduler.php(60): ActionScheduler::init()
#3 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-content/plugins/woocommerce/packages/action-scheduler/classes/ActionScheduler_Versions.php(115): action_scheduler_initialize_4_dot_0_dot_0()
#4 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-includes/class-wp-hook.php(351): ActionScheduler_Versions::initialize_latest_version()
#5 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-includes/class-wp-hook.php(377): WP_Hook->apply_filters()
#6 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-includes/plugin.php(523): WP_Hook->do_action()
#7 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-settings.php(630): do_action()
#8 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-config.php(102): require_once('...')
#9 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-load.php(50): require_once('...')
#10 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-blog-header.php(13): require_once('...')
#11 /var/www/vhosts/bininntaranaki.co.nz/httpdocs/index.php(17): require('...')
#12 {main}
thrown in /var/www/vhosts/bininntaranaki.co.nz/httpdocs/wp-content/plugins/woocommerce/packages/action-scheduler/classes/abstracts/ActionScheduler_Store.php on line 502