Verified Commit 00e14768 authored by Erick Hitter's avatar Erick Hitter
Browse files

Move lock functionality to its own class so it can be reused in CPT and other...

Move lock functionality to its own class so it can be reused in CPT and other places that need rate-limiting
parent 111ca8a0
<?php
namespace WP_Cron_Control_Revisited;
class Lock {
/**
* Set a lock and limit how many concurrent jobs are permitted
*/
public static function check_lock( $lock ) {
// Prevent deadlock
if ( self::get_lock_timestamp( $lock ) < time() - JOB_TIMEOUT_IN_MINUTES * MINUTE_IN_SECONDS ) {
self::reset_lock( $lock );
return true;
}
// Check if process can run
if ( self::get_lock_value( $lock ) >= JOB_CONCURRENCY_LIMIT ) {
return false;
} else {
wp_cache_incr( self::get_key( $lock ) );
return true;
}
}
/**
* When event completes, allow another
*/
public static function free_lock( $lock ) {
if ( self::get_lock_value( $lock ) > 1 ) {
wp_cache_decr( self::get_key( $lock ) );
} else {
wp_cache_set( self::get_key( $lock ), 0 );
}
wp_cache_set( self::get_key( $lock, 'timestamp' ), time() );
return true;
}
/**
* Build cache key
*/
private static function get_key( $lock, $type = 'lock' ) {
switch ( $type ) {
case 'lock' :
return "wpccr_lock_{$lock}";
break;
case 'timestamp' :
return "wpccr_lock_ts_{$lock}";
break;
}
return false;
}
/**
* Ensure lock entries are initially set
*/
public static function prime_lock( $lock ) {
wp_cache_add( self::get_key( $lock ), 0 );
wp_cache_add( self::get_key( $lock, 'timestamp' ), time() );
return null;
}
/**
* Retrieve a lock from cache
*/
private static function get_lock_value( $lock ) {
return (int) wp_cache_get( self::get_key( $lock ), null, true );
}
/**
* Retrieve a lock's timestamp
*/
private static function get_lock_timestamp( $lock ) {
return (int) wp_cache_get( self::get_key( $lock, 'timestamp' ), null, true );
}
/**
* Clear a lock's current values, in order to free it
*/
private static function reset_lock( $lock ) {
wp_cache_set( self::get_key( $lock ), 0 );
wp_cache_set( self::get_key( $lock, 'timestamp' ), time() );
return true;
}
}
......@@ -10,8 +10,7 @@ class Main extends Singleton {
/**
* Class properties
*/
private $cache_key_lock = 'wpccr_lock';
private $cache_key_lock_timestamp = 'wpccr_lock_ts';
const LOCK = 'run-events';
/**
* Register hooks
......@@ -29,8 +28,7 @@ class Main extends Singleton {
}
// Prime lock cache if not present
wp_cache_add( $this->cache_key_lock, 0 );
wp_cache_add( $this->cache_key_lock_timestamp, time() );
Lock::prime_lock( self::LOCK );
// Load dependencies
require __DIR__ . '/class-internal-events.php';
......@@ -183,7 +181,7 @@ class Main extends Singleton {
$time_start = microtime( true );
// Limit how many events are processed concurrently
if ( ! is_internal_event( $event['action'] ) && ! $this->check_lock() ) {
if ( ! is_internal_event( $event['action'] ) && ! Lock::check_lock( self::LOCK ) ) {
return new \WP_Error( 'no-free-threads', __( 'No resources available to run this job.', 'wp-cron-control-revisited' ) );
}
......@@ -206,7 +204,7 @@ class Main extends Singleton {
// Free process for the next event
if ( ! is_internal_event( $event['action'] ) ) {
$this->free_lock();
Lock::free_lock( self::LOCK );
}
$time_end = microtime( true );
......@@ -240,49 +238,4 @@ class Main extends Singleton {
return $event;
}
/**
* PLUGIN UTILITY METHODS
*/
/**
* Set a lock and limit how many concurrent jobs are permitted
*/
private function check_lock() {
// Prevent deadlock
$lock_timestamp = (int) wp_cache_get( $this->cache_key_lock_timestamp, null, true );
if ( $lock_timestamp < time() - JOB_TIMEOUT_IN_MINUTES * MINUTE_IN_SECONDS ) {
wp_cache_set( $this->cache_key_lock, 0 );
wp_cache_set( $this->cache_key_lock_timestamp, time() );
return true;
}
// Check if process can run
$lock = (int) wp_cache_get( $this->cache_key_lock, null, true );
if ( $lock >= JOB_CONCURRENCY_LIMIT ) {
return false;
} else {
wp_cache_incr( $this->cache_key_lock );
return true;
}
}
/**
* When event completes, allow another
*/
private function free_lock() {
$lock = (int) wp_cache_get( $this->cache_key_lock, null, true );
if ( $lock > 1 ) {
wp_cache_decr( $this->cache_key_lock );
} else {
wp_cache_set( $this->cache_key_lock, 0 );
}
wp_cache_set( $this->cache_key_lock_timestamp, time() );
return true;
}
}
......@@ -13,6 +13,7 @@ namespace WP_Cron_Control_Revisited;
// Load basics needed to instantiate plugin
require __DIR__ . '/includes/constants.php';
require __DIR__ . '/includes/abstract-class-singleton.php';
require __DIR__ . '/includes/class-lock.php';
// For data consistency, ensure alternate data store is always loaded
require __DIR__ . '/includes/class-cron-options-cpt.php';
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment