Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 162 additions & 17 deletions assets/admin.js

Large diffs are not rendered by default.

58 changes: 57 additions & 1 deletion redis-queue.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@
* Domain Path: /languages
* Update URI: false
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

// Plugin version and requirements.
define( 'REDIS_QUEUE_VERSION', '2.0.0' );
define( 'REDIS_QUEUE_MIN_PHP', '8.3' );

// Plugin file paths and URLs.
define( 'REDIS_QUEUE_PLUGIN_FILE', __FILE__ );
define( 'REDIS_QUEUE_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
define( 'REDIS_QUEUE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
Expand All @@ -33,31 +37,52 @@

/**
* One-time migration of options from old prefix redis_queue_demo_ to redis_queue_.
*
* Migrates plugin options from the old naming convention (redis_queue_demo_*)
* to the new naming convention (redis_queue_*). This runs once during plugin
* upgrade from version 1.x to 2.0.0.
*/
function redis_queue_migrate_options_v2() {
// Check if migration has already been performed.
if ( get_option( 'redis_queue_migrated_options_v2' ) ) {
return;
}

// Define all option keys that need to be migrated.
$option_suffixes = [
'redis_host', 'redis_port', 'redis_password', 'redis_database', 'default_queue', 'max_jobs_per_run',
'worker_timeout', 'max_retries', 'retry_backoff', 'enable_logging', 'cleanup_completed_jobs', 'cleanup_after_days',
];

// Migrate each option from old to new key name.
foreach ( $option_suffixes as $suffix ) {
$old_key = 'redis_queue_demo_' . $suffix;
$new_key = 'redis_queue_' . $suffix;
$old_val = get_option( $old_key, null );

// Only migrate if old value exists and new value doesn't exist.
if ( $old_val !== null && get_option( $new_key, null ) === null ) {
update_option( $new_key, $old_val );
}
}

// Mark migration as complete.
update_option( 'redis_queue_migrated_options_v2', '1' );
}
add_action( 'plugins_loaded', 'redis_queue_migrate_options_v2', 1 );

// Bootstrap namespaced main class (new namespace & class name).
/**
* Bootstrap the main plugin class.
*
* Initializes the Redis Queue plugin if all dependencies are loaded.
* If dependencies are missing (e.g., Composer autoloader not run),
* displays an admin notice to inform the user.
*/
if ( class_exists( 'Soderlind\RedisQueue\Core\Redis_Queue' ) ) {
// Initialize the plugin singleton instance.
Soderlind\RedisQueue\Core\Redis_Queue::get_instance();
} else {
// Show error notice if dependencies are missing.
add_action( 'admin_notices', function() {
if ( current_user_can( 'activate_plugins' ) ) {
echo '<div class="notice notice-error"><p>';
Expand All @@ -68,13 +93,32 @@ function redis_queue_migrate_options_v2() {
} );
}

/**
* Get the main plugin instance.
*
* Provides global access to the Redis Queue plugin singleton instance.
* This is the recommended way to access the plugin's public API.
*
* @return \Soderlind\RedisQueue\Core\Redis_Queue|null Plugin instance or null if not loaded.
*/
function redis_queue() {
if ( class_exists( 'Soderlind\RedisQueue\Core\Redis_Queue' ) ) {
return Soderlind\RedisQueue\Core\Redis_Queue::get_instance();
}
return null;
}

/**
* Enqueue a background job.
*
* Convenience function to add a job to the Redis queue. This is a wrapper
* around the main plugin's enqueue_job method.
*
* @param string $job_type The type of job (email, image_processing, api_sync, or custom).
* @param array $payload Job-specific data to be processed.
* @param array $options Optional settings: priority, queue, delay.
* @return string|false Job ID on success, false on failure.
*/
function redis_queue_enqueue_job( $job_type, $payload = array(), $options = array() ) {
$instance = redis_queue();
if ( ! $instance ) {
Expand All @@ -83,11 +127,23 @@ function redis_queue_enqueue_job( $job_type, $payload = array(), $options = arra
return $instance->enqueue_job( $job_type, $payload, $options );
}

/**
* Process queued jobs synchronously.
*
* Creates a synchronous worker and processes jobs from the specified queue(s).
* This can be called from WP-CLI, cron jobs, or custom worker scripts.
*
* @param string|array $queue Queue name(s) to process. Default 'default'.
* @param int|null $max_jobs Maximum number of jobs to process. Default from settings.
* @return array|false Processing results array or false on failure.
*/
function redis_queue_process_jobs( $queue = 'default', $max_jobs = null ) {
$instance = redis_queue();
if ( ! $instance || ! $instance->get_queue_manager() || ! $instance->get_job_processor() ) {
return false;
}

// Create a synchronous worker and process jobs.
$worker = new \Soderlind\RedisQueue\Workers\Sync_Worker( $instance->get_queue_manager(), $instance->get_job_processor() );
return $worker->process_jobs( (array) $queue, $max_jobs );
}
65 changes: 65 additions & 0 deletions src/Contracts/Job_Result.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,79 @@
<?php
namespace Soderlind\RedisQueue\Contracts;

/**
* Job Result Interface.
* Defines the contract for job execution results.
*
* Results track success/failure status, data, errors, and performance metrics.
* They must be serializable for storage in the database.
*/
interface Job_Result {
/**
* Check if job execution was successful.
*
* @return bool True if successful, false if failed.
*/
public function is_successful();

/**
* Get result data.
* Data returned by successful job execution.
*
* @return mixed Result data.
*/
public function get_data();

/**
* Get error message.
* Returns error message if job failed.
*
* @return string|null Error message or null if successful.
*/
public function get_error_message();

/**
* Get error code.
* Returns error code if job failed.
*
* @return int|null Error code or null if successful.
*/
public function get_error_code();

/**
* Get result metadata.
* Additional contextual information about the result.
*
* @return array Metadata.
*/
public function get_metadata();

/**
* Get job execution time in seconds.
*
* @return float|null Execution time or null if not measured.
*/
public function get_execution_time();

/**
* Get peak memory usage in bytes.
*
* @return int|null Memory usage or null if not measured.
*/
public function get_memory_usage();

/**
* Convert result to array for serialization.
*
* @return array Result data as array.
*/
public function to_array();

/**
* Create result from array data.
*
* @param array $data Result data array.
* @return self Result instance.
*/
public static function from_array( $data );
}
88 changes: 87 additions & 1 deletion src/Contracts/Queue_Job.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,103 @@
<?php
namespace Soderlind\RedisQueue\Contracts;

/**
* Queue Job Interface.
* Defines the contract that all queue jobs must implement.
*
* Jobs must be serializable for storage in Redis and the database.
* They must also handle execution, failures, and retry logic.
*/
interface Queue_Job {
/**
* Get job type identifier.
*
* @return string Job type.
*/
public function get_job_type();

/**
* Get job payload data.
*
* @return array Job payload.
*/
public function get_payload();

/**
* Get job priority.
* Lower values indicate higher priority.
*
* @return int Priority value.
*/
public function get_priority();

/**
* Get maximum retry attempts.
*
* @return int Max retry attempts.
*/
public function get_retry_attempts();

/**
* Get execution timeout in seconds.
*
* @return int Timeout in seconds.
*/
public function get_timeout();

/**
* Get queue name for this job.
*
* @return string Queue name.
*/
public function get_queue_name();
public function execute(); // Must return Job_Result

/**
* Execute the job.
* Must return a Job_Result indicating success or failure.
*
* @return Job_Result Job execution result.
*/
public function execute();

/**
* Handle job failure.
* Called when job fails to allow custom error handling and logging.
*
* @param mixed $exception Exception or failure reason.
* @param int $attempt Current attempt number.
*/
public function handle_failure( $exception, $attempt );

/**
* Determine if job should be retried after failure.
*
* @param mixed $exception Exception or failure reason.
* @param int $attempt Current attempt number.
* @return bool True if job should be retried.
*/
public function should_retry( $exception, $attempt );

/**
* Get delay before retry in seconds.
*
* @param int $attempt Attempt number.
* @return int Delay in seconds.
*/
public function get_retry_delay( $attempt );

/**
* Serialize job for storage.
*
* @return array Serialized job data.
*/
public function serialize();

/**
* Deserialize job from stored data.
*
* @param array $data Serialized job data.
* @return self Job instance.
*/
public static function deserialize( $data );
}
Loading