diff --git a/admin/class-admin-interface.php b/admin/class-admin-interface.php
deleted file mode 100644
index a4fa45a..0000000
--- a/admin/class-admin-interface.php
+++ /dev/null
@@ -1,1327 +0,0 @@
-queue_manager = $queue_manager;
- $this->job_processor = $job_processor;
- }
-
- /**
- * Initialize admin interface.
- *
- * @since 1.0.0
- */
- public function init() {
- add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
- add_action( 'wp_ajax_redis_queue_trigger_worker', array( $this, 'ajax_trigger_worker' ) );
- add_action( 'wp_ajax_redis_queue_get_stats', array( $this, 'ajax_get_stats' ) );
- add_action( 'wp_ajax_redis_queue_clear_queue', array( $this, 'ajax_clear_queue' ) );
- add_action( 'wp_ajax_redis_queue_create_test_job', array( $this, 'ajax_create_test_job' ) );
- add_action( 'wp_ajax_redis_queue_diagnostics', array( $this, 'ajax_diagnostics' ) );
- add_action( 'wp_ajax_redis_queue_debug_test', array( $this, 'ajax_debug_test' ) );
- add_action( 'wp_ajax_redis_queue_reset_stuck_jobs', array( $this, 'ajax_reset_stuck_jobs' ) );
- add_action( 'wp_ajax_redis_queue_purge_jobs', array( $this, 'ajax_purge_jobs' ) );
- }
-
- /**
- * Add admin menu.
- *
- * @since 1.0.0
- */
- public function add_admin_menu() {
- add_menu_page(
- __( 'Redis Queue', 'redis-queue-demo' ),
- __( 'Redis Queue', 'redis-queue-demo' ),
- 'manage_options',
- 'redis-queue-demo',
- array( $this, 'render_dashboard_page' ),
- 'dashicons-database-view',
- 30
- );
-
- add_submenu_page(
- 'redis-queue-demo',
- __( 'Dashboard', 'redis-queue-demo' ),
- __( 'Dashboard', 'redis-queue-demo' ),
- 'manage_options',
- 'redis-queue-demo',
- array( $this, 'render_dashboard_page' )
- );
-
- add_submenu_page(
- 'redis-queue-demo',
- __( 'Jobs', 'redis-queue-demo' ),
- __( 'Jobs', 'redis-queue-demo' ),
- 'manage_options',
- 'redis-queue-jobs',
- array( $this, 'render_jobs_page' )
- );
-
- add_submenu_page(
- 'redis-queue-demo',
- __( 'Test Jobs', 'redis-queue-demo' ),
- __( 'Test Jobs', 'redis-queue-demo' ),
- 'manage_options',
- 'redis-queue-test',
- array( $this, 'render_test_page' )
- );
-
- add_submenu_page(
- 'redis-queue-demo',
- __( 'Settings', 'redis-queue-demo' ),
- __( 'Settings', 'redis-queue-demo' ),
- 'manage_options',
- 'redis-queue-settings',
- array( $this, 'render_settings_page' )
- );
- }
-
- /**
- * Enqueue admin scripts and styles.
- *
- * @since 1.0.0
- * @param string $hook_suffix Current admin page hook suffix.
- */
- public function enqueue_admin_scripts( $hook_suffix ) {
- // Only enqueue on our admin pages.
- if ( strpos( $hook_suffix, 'redis-queue' ) === false ) {
- return;
- }
-
- wp_enqueue_script(
- 'redis-queue-admin',
- plugin_dir_url( __FILE__ ) . '../assets/admin.js',
- array( 'jquery' ),
- REDIS_QUEUE_DEMO_VERSION,
- true
- );
-
- wp_localize_script(
- 'redis-queue-admin',
- 'redisQueueAdmin',
- array(
- 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
- 'nonce' => wp_create_nonce( 'redis_queue_admin' ),
- 'restNonce' => wp_create_nonce( 'wp_rest' ),
- 'restUrl' => rest_url( 'redis-queue/v1/' ),
- 'strings' => array(
- 'processing' => __( 'Processing...', 'redis-queue-demo' ),
- 'success' => __( 'Success!', 'redis-queue-demo' ),
- 'error' => __( 'Error occurred', 'redis-queue-demo' ),
- 'confirmClear' => __( 'Are you sure you want to clear this queue?', 'redis-queue-demo' ),
- 'workerTriggered' => __( 'Worker triggered successfully', 'redis-queue-demo' ),
- 'queueCleared' => __( 'Queue cleared successfully', 'redis-queue-demo' ),
- ),
- )
- );
-
- wp_enqueue_style(
- 'redis-queue-admin',
- plugin_dir_url( __FILE__ ) . '../assets/admin.css',
- array(),
- REDIS_QUEUE_DEMO_VERSION
- );
- }
-
- /**
- * Render dashboard page.
- *
- * @since 1.0.0
- */
- public function render_dashboard_page() {
- $stats = $this->queue_manager->get_queue_stats();
- $flat_stats = $this->flatten_stats( $stats );
- $health = $this->get_system_health();
- ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- prefix . 'redis_queue_jobs';
- $offset = ( $current_page - 1 ) * $per_page;
-
- // Build query.
- $where_conditions = array();
- $prepare_values = array();
-
- if ( $status_filter ) {
- $where_conditions[] = 'status = %s';
- $prepare_values[] = $status_filter;
- }
-
- $where_clause = '';
- if ( ! empty( $where_conditions ) ) {
- $where_clause = 'WHERE ' . implode( ' AND ', $where_conditions );
- }
-
- // Get total count.
- $count_query = "SELECT COUNT(*) FROM {$table_name} {$where_clause}";
- if ( ! empty( $prepare_values ) ) {
- $count_query = $wpdb->prepare( $count_query, ...$prepare_values );
- }
- $total_jobs = (int) $wpdb->get_var( $count_query );
-
- // Get jobs.
- $jobs_query = "SELECT * FROM {$table_name} {$where_clause} ORDER BY created_at DESC LIMIT %d OFFSET %d";
- $prepare_values[] = $per_page;
- $prepare_values[] = $offset;
-
- $jobs = $wpdb->get_results(
- $wpdb->prepare( $jobs_query, ...$prepare_values ),
- ARRAY_A
- );
-
- $total_pages = ceil( $total_jobs / $per_page );
- ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
- |
- |
- |
- |
- |
- |
- |
- |
-
-
-
-
-
- |
-
-
-
-
- |
- |
- |
-
-
-
-
- |
- |
- |
- |
-
-
-
-
-
- |
-
-
-
- |
-
-
-
-
-
-
-
- 1 ) : ?>
-
- add_query_arg( 'paged', '%#%' ),
- 'format' => '',
- 'prev_text' => __( '« Previous', 'redis-queue-demo' ),
- 'next_text' => __( 'Next »', 'redis-queue-demo' ),
- 'total' => $total_pages,
- 'current' => $current_page,
- )
- );
- ?>
-
-
-
-
-
- save_settings();
- } elseif ( isset( $_POST[ 'generate_api_token' ] ) && wp_verify_nonce( $_POST[ '_wpnonce' ], 'redis_queue_settings' ) ) {
- // Generate token then save other settings.
- $_POST[ '__generate_api_token' ] = 1; // Internal flag consumed in save_settings().
- $this->save_settings();
- } elseif ( isset( $_POST[ 'clear_api_token' ] ) && wp_verify_nonce( $_POST[ '_wpnonce' ], 'redis_queue_settings' ) ) {
- $_POST[ '__clear_api_token' ] = 1; // Internal flag.
- $this->save_settings();
- }
-
- $options = get_option( 'redis_queue_settings', array() );
- $defaults = array(
- 'redis_host' => '127.0.0.1',
- 'redis_port' => 6379,
- 'redis_database' => 0,
- 'redis_password' => '',
- 'worker_timeout' => 30,
- 'max_retries' => 3,
- 'retry_delay' => 60,
- 'batch_size' => 10,
- 'api_token' => '',
- 'api_token_scope' => 'worker',
- 'rate_limit_per_minute' => 60,
- 'enable_request_logging' => 0,
- 'log_rotate_size_kb' => 256,
- 'log_max_files' => 5,
- );
- $options = wp_parse_args( $options, $defaults );
- ?>
-
-
-
-
-
-
-
-
- sanitize_text_field( $_POST[ 'redis_host' ] ),
- 'redis_port' => intval( $_POST[ 'redis_port' ] ),
- 'redis_database' => intval( $_POST[ 'redis_database' ] ),
- 'redis_password' => sanitize_text_field( $_POST[ 'redis_password' ] ),
- 'worker_timeout' => intval( $_POST[ 'worker_timeout' ] ),
- 'max_retries' => intval( $_POST[ 'max_retries' ] ),
- 'retry_delay' => intval( $_POST[ 'retry_delay' ] ),
- 'batch_size' => intval( $_POST[ 'batch_size' ] ),
- 'api_token' => isset( $existing[ 'api_token' ] ) ? $existing[ 'api_token' ] : '', // default preserve existing
- 'api_token_scope' => isset( $_POST[ 'api_token_scope' ] ) && in_array( $_POST[ 'api_token_scope' ], array( 'worker', 'full' ), true ) ? $_POST[ 'api_token_scope' ] : ( isset( $existing[ 'api_token_scope' ] ) ? $existing[ 'api_token_scope' ] : 'worker' ),
- 'rate_limit_per_minute' => isset( $_POST[ 'rate_limit_per_minute' ] ) ? max( 1, intval( $_POST[ 'rate_limit_per_minute' ] ) ) : ( isset( $existing[ 'rate_limit_per_minute' ] ) ? intval( $existing[ 'rate_limit_per_minute' ] ) : 60 ),
- 'enable_request_logging' => isset( $_POST[ 'enable_request_logging' ] ) ? 1 : 0,
- 'log_rotate_size_kb' => isset( $_POST[ 'log_rotate_size_kb' ] ) ? max( 8, intval( $_POST[ 'log_rotate_size_kb' ] ) ) : ( isset( $existing[ 'log_rotate_size_kb' ] ) ? intval( $existing[ 'log_rotate_size_kb' ] ) : 256 ),
- 'log_max_files' => isset( $_POST[ 'log_max_files' ] ) ? max( 1, intval( $_POST[ 'log_max_files' ] ) ) : ( isset( $existing[ 'log_max_files' ] ) ? intval( $existing[ 'log_max_files' ] ) : 5 ),
- );
-
- // Handle token clear.
- if ( isset( $_POST[ '__clear_api_token' ] ) || isset( $_POST[ 'clear_api_token' ] ) ) {
- $settings[ 'api_token' ] = '';
- }
-
- // Handle token generation.
- if ( isset( $_POST[ '__generate_api_token' ] ) || isset( $_POST[ 'generate_api_token' ] ) ) {
- try {
- $settings[ 'api_token' ] = bin2hex( random_bytes( 32 ) ); // 64 hex chars ~256 bits.
- } catch (Exception $e) {
- // Fallback if random_bytes unavailable.
- $settings[ 'api_token' ] = wp_generate_password( 64, false, false );
- }
- }
-
- update_option( 'redis_queue_settings', $settings );
- add_action( 'admin_notices', array( $this, 'settings_saved_notice' ) );
- }
-
- /**
- * Display settings saved notice.
- *
- * @since 1.0.0
- */
- public function settings_saved_notice() {
- ?>
-
- queue_manager || ! $this->job_processor ) {
- wp_send_json_error( 'Queue system not initialized' );
- return;
- }
-
- // Check if Redis connection is available
- if ( ! $this->queue_manager->is_connected() ) {
- wp_send_json_error( 'Redis connection not available' );
- return;
- }
-
- // Use the helper function to process jobs safely if available
- if ( function_exists( 'redis_queue_process_jobs' ) ) {
- $results = redis_queue_process_jobs( array( 'default', 'email', 'media', 'api' ), 10 );
- } else {
- // Fallback to direct instantiation
- if ( ! class_exists( 'Sync_Worker' ) ) {
- wp_send_json_error( 'Sync_Worker class not available' );
- return;
- }
- $sync_worker = new Sync_Worker( $this->queue_manager, $this->job_processor );
- $results = $sync_worker->process_jobs( array( 'default', 'email', 'media', 'api' ), 10 );
- }
-
- // Validate results
- if ( $results === null ) {
- wp_send_json_error( 'Worker returned null results' );
- return;
- }
-
- if ( ! is_array( $results ) ) {
- wp_send_json_error( 'Worker returned invalid results format' );
- return;
- }
-
- wp_send_json_success( $results );
- } catch (Exception $e) {
- $error_message = 'Worker error: ';
- if ( $e && method_exists( $e, 'getMessage' ) ) {
- $error_message .= $e->getMessage();
- } else {
- $error_message .= 'Unknown exception occurred';
- }
- wp_send_json_error( $error_message );
- } catch (Error $e) {
- $error_message = 'Fatal error: ';
- if ( $e && method_exists( $e, 'getMessage' ) ) {
- $error_message .= $e->getMessage();
- } else {
- $error_message .= 'Unknown fatal error occurred';
- }
- wp_send_json_error( $error_message );
- } catch (Throwable $e) {
- $error_message = 'Unexpected error: ';
- if ( $e && method_exists( $e, 'getMessage' ) ) {
- $error_message .= $e->getMessage();
- } else {
- $error_message .= 'Unknown throwable occurred';
- }
- wp_send_json_error( $error_message );
- }
- }
-
- /**
- * AJAX handler for getting stats.
- *
- * @since 1.0.0
- */
- public function ajax_get_stats() {
- check_ajax_referer( 'redis_queue_admin', 'nonce' );
-
- if ( ! current_user_can( 'manage_options' ) ) {
- wp_die( -1 );
- }
-
- $stats = $this->queue_manager->get_queue_stats();
- $flat_stats = $this->flatten_stats( $stats );
- wp_send_json_success( $flat_stats );
- }
-
- /**
- * AJAX handler for clearing queue.
- *
- * @since 1.0.0
- */
- public function ajax_clear_queue() {
- check_ajax_referer( 'redis_queue_admin', 'nonce' );
-
- if ( ! current_user_can( 'manage_options' ) ) {
- wp_die( -1 );
- }
-
- $queue_name = sanitize_text_field( $_POST[ 'queue' ] ?? 'default' );
- $result = $this->queue_manager->clear_queue( $queue_name );
-
- if ( $result ) {
- wp_send_json_success( array( 'message' => 'Queue cleared successfully' ) );
- } else {
- wp_send_json_error( 'Failed to clear queue' );
- }
- }
-
- /**
- * AJAX handler for creating test jobs.
- *
- * @since 1.0.0
- */
- public function ajax_create_test_job() {
- check_ajax_referer( 'redis_queue_admin', 'nonce' );
-
- if ( ! current_user_can( 'manage_options' ) ) {
- wp_die( -1 );
- }
-
- $job_type = sanitize_text_field( $_POST[ 'job_type' ] ?? '' );
- $payload = $_POST[ 'payload' ] ?? array();
-
- // Sanitize payload data
- $payload = array_map( 'sanitize_text_field', $payload );
-
- try {
- // Use the main plugin instance to create the job
- $plugin = redis_queue_demo();
- $job_id = $plugin->enqueue_job( $job_type, $payload, array( 'priority' => 10 ) );
-
- if ( $job_id ) {
- wp_send_json_success( array(
- 'job_id' => $job_id,
- 'message' => 'Job created and enqueued successfully.',
- ) );
- } else {
- wp_send_json_error( 'Failed to enqueue job.' );
- }
- } catch (Exception $e) {
- wp_send_json_error( 'Job creation failed: ' . $e->getMessage() );
- }
- }
-
- /**
- * AJAX handler for diagnostics.
- *
- * @since 1.0.0
- */
- public function ajax_diagnostics() {
- check_ajax_referer( 'redis_queue_admin', 'nonce' );
-
- if ( ! current_user_can( 'manage_options' ) ) {
- wp_die( -1 );
- }
-
- try {
- $diagnostics = $this->queue_manager->diagnostic();
- wp_send_json_success( $diagnostics );
- } catch (Exception $e) {
- wp_send_json_error( 'Diagnostic failed: ' . ( $e ? $e->getMessage() : 'Unknown error' ) );
- }
- }
-
- /**
- * AJAX handler for comprehensive debug test.
- *
- * @since 1.0.0
- */
- public function ajax_debug_test() {
- check_ajax_referer( 'redis_queue_admin', 'nonce' );
-
- if ( ! current_user_can( 'manage_options' ) ) {
- wp_die( -1 );
- }
-
- $debug_results = array();
-
- // Test 1: Plugin initialization
- $plugin = redis_queue_demo();
- $debug_results[ '1. Plugin Initialization' ] = array(
- 'Queue Manager' => $plugin->queue_manager ? 'OK' : 'FAILED',
- 'Job Processor' => $plugin->job_processor ? 'OK' : 'FAILED',
- );
-
- // Test 2: Redis connection
- $debug_results[ '2. Redis Connection' ] = array(
- 'Connected' => $plugin->queue_manager->is_connected() ? 'YES' : 'NO',
- );
-
- // Test 3: Redis diagnostics
- $diagnostics = $plugin->queue_manager->diagnostic();
- $debug_results[ '3. Redis Diagnostics' ] = array(
- 'Test Write' => isset( $diagnostics[ 'test_write' ] ) && $diagnostics[ 'test_write' ] ? 'OK' : 'FAILED',
- 'Test Read' => isset( $diagnostics[ 'test_read' ] ) && $diagnostics[ 'test_read' ] ? 'OK' : 'FAILED',
- 'Queue Prefix' => $diagnostics[ 'queue_prefix' ] ?? 'unknown',
- 'Redis Keys Found' => isset( $diagnostics[ 'redis_keys' ] ) ? count( $diagnostics[ 'redis_keys' ] ) : 0,
- 'Keys' => isset( $diagnostics[ 'redis_keys' ] ) ? implode( ', ', $diagnostics[ 'redis_keys' ] ) : 'none',
- );
-
- // Test 4: Job creation and processing
- $debug_results[ '4. Job Creation Test' ] = array();
- $job_id = $plugin->enqueue_job( 'email', array(
- 'type' => 'single',
- 'to' => 'test@example.com',
- 'subject' => 'Debug Test Email ' . date( 'H:i:s' ),
- 'message' => 'This is a debug test email',
- ) );
-
- if ( $job_id ) {
- $debug_results[ '4. Job Creation Test' ][ 'Job Created' ] = 'YES (ID: ' . $job_id . ')';
-
- // Check Redis keys after creation
- $diagnostics_after = $plugin->queue_manager->diagnostic();
- $debug_results[ '4. Job Creation Test' ][ 'Redis Keys After Creation' ] = count( $diagnostics_after[ 'redis_keys' ] );
- $debug_results[ '4. Job Creation Test' ][ 'Keys' ] = implode( ', ', $diagnostics_after[ 'redis_keys' ] );
-
- // Try to dequeue
- $dequeued = $plugin->queue_manager->dequeue( array( 'email' ) );
- if ( $dequeued ) {
- $debug_results[ '4. Job Creation Test' ][ 'Job Dequeued' ] = 'YES';
- $debug_results[ '4. Job Creation Test' ][ 'Dequeued Job ID' ] = $dequeued[ 'job_id' ] ?? 'unknown';
- $debug_results[ '4. Job Creation Test' ][ 'Dequeued Job Type' ] = $dequeued[ 'job_type' ] ?? 'unknown';
- $debug_results[ '4. Job Creation Test' ][ 'Payload Keys' ] = isset( $dequeued[ 'payload' ] ) ? implode( ', ', array_keys( $dequeued[ 'payload' ] ) ) : 'none';
-
- // Attempt to process the dequeued job immediately so it doesn't remain stuck in 'processing'
- try {
- $job_result = $plugin->job_processor->process_job( $dequeued );
- $debug_results[ '4. Job Creation Test' ][ 'Job Processed' ] = 'YES';
- $debug_results[ '4. Job Creation Test' ][ 'Job Successful' ] = $job_result->is_successful() ? 'YES' : 'NO';
-
- // PHPMailer diagnostics (after wp_mail invocation inside job)
- global $phpmailer;
- if ( isset( $phpmailer ) && is_object( $phpmailer ) ) {
- $debug_results[ '4. Job Creation Test' ][ 'PHPMailer Host' ] = $phpmailer->Host ?? '(unset)';
- $debug_results[ '4. Job Creation Test' ][ 'PHPMailer Port' ] = $phpmailer->Port ?? '(unset)';
- $debug_results[ '4. Job Creation Test' ][ 'PHPMailer SMTPSecure' ] = $phpmailer->SMTPSecure ?? '(unset)';
- $debug_results[ '4. Job Creation Test' ][ 'PHPMailer SMTPAuth' ] = isset( $phpmailer->SMTPAuth ) ? ( $phpmailer->SMTPAuth ? 'true' : 'false' ) : '(unset)';
- $debug_results[ '4. Job Creation Test' ][ 'PHPMailer ErrorInfo' ] = ! empty( $phpmailer->ErrorInfo ) ? $phpmailer->ErrorInfo : '(none)';
- $debug_results[ '4. Job Creation Test' ][ 'PHPMailer From' ] = $phpmailer->From ?? '(unset)';
- $debug_results[ '4. Job Creation Test' ][ 'PHPMailer FromName' ] = $phpmailer->FromName ?? '(unset)';
- }
-
- if ( $job_result->is_successful() ) {
- $data = $job_result->get_data();
- $debug_results[ '4. Job Creation Test' ][ 'Result Data' ] = is_scalar( $data ) ? (string) $data : wp_json_encode( $data );
- } else {
- $debug_results[ '4. Job Creation Test' ][ 'Error Message' ] = $job_result->get_error_message();
- $debug_results[ '4. Job Creation Test' ][ 'Error Code' ] = $job_result->get_error_code();
- // Include metadata (e.g., phpmailer_error) for deeper insight
- $metadata = $job_result->get_metadata();
- if ( ! empty( $metadata ) ) {
- $debug_results[ '4. Job Creation Test' ][ 'Job Result Metadata' ] = wp_json_encode( $metadata );
- }
- }
- } catch (Throwable $e) {
- $debug_results[ '4. Job Creation Test' ][ 'Job Processed' ] = 'NO (Exception)';
- $debug_results[ '4. Job Creation Test' ][ 'Processing Exception' ] = $e->getMessage();
- $debug_results[ '4. Job Creation Test' ][ 'Processing Exception File' ] = $e->getFile() . ':' . $e->getLine();
- }
- } else {
- $debug_results[ '4. Job Creation Test' ][ 'Job Dequeued' ] = 'NO';
- }
- } else {
- $debug_results[ '4. Job Creation Test' ][ 'Job Created' ] = 'NO';
- }
-
- // Test 5: Database check
- global $wpdb;
- $table_name = $wpdb->prefix . 'redis_queue_jobs';
- $debug_results[ '5. Database Check' ] = array(
- 'Table Exists' => $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) == $table_name ? 'YES' : 'NO',
- 'Job Count' => (int) $wpdb->get_var( "SELECT COUNT(*) FROM $table_name" ),
- );
-
- // Get recent jobs
- $recent_jobs = $wpdb->get_results( "SELECT job_id, job_type, status, created_at FROM $table_name ORDER BY created_at DESC LIMIT 5", ARRAY_A );
- $debug_results[ '5. Database Check' ][ 'Recent Jobs' ] = array();
- foreach ( $recent_jobs as $job ) {
- $debug_results[ '5. Database Check' ][ 'Recent Jobs' ][] = $job[ 'job_id' ] . ' (' . $job[ 'job_type' ] . ') - ' . $job[ 'status' ] . ' - ' . $job[ 'created_at' ];
- }
-
- wp_send_json_success( $debug_results );
- }
-
- /**
- * AJAX handler to reset stuck jobs.
- *
- * @since 1.0.0
- */
- public function ajax_reset_stuck_jobs() {
- check_ajax_referer( 'redis_queue_admin', 'nonce' );
-
- if ( ! current_user_can( 'manage_options' ) ) {
- wp_die( -1 );
- }
-
- try {
- $reset_count = $this->queue_manager->reset_stuck_jobs( 30 );
- wp_send_json_success( array(
- 'message' => sprintf( 'Reset %d stuck jobs back to queued status.', $reset_count ),
- 'count' => $reset_count,
- ) );
- } catch (Exception $e) {
- wp_send_json_error( 'Failed to reset stuck jobs: ' . ( $e ? $e->getMessage() : 'Unknown error' ) );
- }
- }
-
- /**
- * Get system health status.
- *
- * @since 1.0.0
- * @return array Health status.
- */
- private function get_system_health() {
- return array(
- 'redis' => $this->queue_manager->is_connected(),
- 'database' => $this->check_database_health(),
- 'overall' => $this->queue_manager->is_connected() && $this->check_database_health(),
- );
- }
-
- /**
- * Check database health.
- *
- * @since 1.0.0
- * @return bool True if database is healthy.
- */
- private function check_database_health() {
- global $wpdb;
-
- $table_name = $wpdb->prefix . 'redis_queue_jobs';
- $table_exists = $wpdb->get_var(
- $wpdb->prepare(
- "SHOW TABLES LIKE %s",
- $table_name
- )
- );
-
- return ! empty( $table_exists );
- }
-
- /**
- * Flatten raw stats (which include per-queue arrays and a 'database' summary) into
- * a simple associative array with top-level queued / processing / completed / failed
- * counts expected by the dashboard UI and JS refresh logic.
- *
- * @since 1.0.0
- * @param array $stats Raw stats from Redis_Queue_Manager::get_queue_stats().
- * @return array Flattened stats.
- */
- private function flatten_stats( $stats ) {
- $flat = array(
- 'queued' => 0,
- 'processing' => 0,
- 'completed' => 0,
- 'failed' => 0,
- 'total' => 0,
- );
-
- // Preferred source: database summary if present.
- if ( isset( $stats[ 'database' ] ) && is_array( $stats[ 'database' ] ) ) {
- $flat[ 'queued' ] = (int) ( $stats[ 'database' ][ 'queued' ] ?? 0 );
- $flat[ 'processing' ] = (int) ( $stats[ 'database' ][ 'processing' ] ?? 0 );
- $flat[ 'completed' ] = (int) ( $stats[ 'database' ][ 'completed' ] ?? 0 );
- $flat[ 'failed' ] = (int) ( $stats[ 'database' ][ 'failed' ] ?? 0 );
- $flat[ 'total' ] = (int) ( $stats[ 'database' ][ 'total' ] ?? ( $flat[ 'queued' ] + $flat[ 'processing' ] + $flat[ 'completed' ] + $flat[ 'failed' ] ) );
- return $flat;
- }
-
- // Fallback: derive from per-queue job 'pending' counts if no database summary.
- foreach ( $stats as $queue => $data ) {
- if ( ! is_array( $data ) ) {
- continue;
- }
- // We only know 'pending' (queued) from Redis side; other states live in DB.
- if ( isset( $data[ 'pending' ] ) ) {
- $flat[ 'queued' ] += (int) $data[ 'pending' ];
- }
- }
- $flat[ 'total' ] = $flat[ 'queued' ];
- return $flat;
- }
-
- /**
- * AJAX handler for purging jobs.
- *
- * Supported scopes:
- * - completed : delete completed jobs
- * - failed : delete failed jobs
- * - older : delete jobs older than N days (default 7)
- * - all : delete ALL jobs (dangerous)
- *
- * @since 1.0.0
- */
- public function ajax_purge_jobs() {
- check_ajax_referer( 'redis_queue_admin', 'nonce' );
-
- if ( ! current_user_can( 'manage_options' ) ) {
- wp_die( -1 );
- }
-
- $scope = sanitize_text_field( $_POST[ 'scope' ] ?? '' );
- $days_arg = isset( $_POST[ 'days' ] ) ? intval( $_POST[ 'days' ] ) : 7;
- $days = $days_arg > 0 ? $days_arg : 7;
-
- if ( ! in_array( $scope, array( 'completed', 'failed', 'older', 'all' ), true ) ) {
- wp_send_json_error( __( 'Invalid purge scope.', 'redis-queue-demo' ) );
- }
-
- global $wpdb;
- $table = $wpdb->prefix . 'redis_queue_jobs';
- $where = '';
- $args = array();
-
- switch ( $scope ) {
- case 'completed':
- $where = "WHERE status = 'completed'";
- break;
- case 'failed':
- $where = "WHERE status = 'failed'";
- break;
- case 'older':
- $cutoff = gmdate( 'Y-m-d H:i:s', time() - ( $days * DAY_IN_SECONDS ) );
- $where = 'WHERE created_at < %s';
- $args[] = $cutoff;
- break;
- case 'all':
- // No where clause (will truncate all rows).
- break;
- }
-
- // Count first for reporting.
- $count_sql = "SELECT COUNT(*) FROM $table " . $where;
- if ( $args ) {
- $count = (int) $wpdb->get_var( $wpdb->prepare( $count_sql, ...$args ) );
- } else {
- $count = (int) $wpdb->get_var( $count_sql );
- }
-
- if ( 0 === $count ) {
- wp_send_json_success( array(
- 'message' => __( 'No matching jobs to purge.', 'redis-queue-demo' ),
- 'count' => 0,
- ) );
- }
-
- // Perform deletion.
- $delete_sql = "DELETE FROM $table " . $where;
- $deleted = 0;
- if ( $args ) {
- $prepared = $wpdb->prepare( $delete_sql, ...$args );
- $wpdb->query( $prepared );
- $deleted = $wpdb->rows_affected;
- } else {
- $wpdb->query( $delete_sql );
- $deleted = $wpdb->rows_affected;
- }
-
- $message = ( 'older' === $scope )
- ? sprintf( __( 'Purged %d jobs older than %d days.', 'redis-queue-demo' ), $deleted, $days )
- : sprintf( __( 'Purged %d jobs (scope: %s).', 'redis-queue-demo' ), $deleted, $scope );
-
- wp_send_json_success( array(
- 'message' => $message,
- 'count' => $deleted,
- 'scope' => $scope,
- 'days' => $days,
- ) );
- }
-}
\ No newline at end of file
diff --git a/api/class-rest-controller.php b/api/class-rest-controller.php
deleted file mode 100644
index c7aa0fa..0000000
--- a/api/class-rest-controller.php
+++ /dev/null
@@ -1,923 +0,0 @@
-queue_manager = $queue_manager;
- $this->job_processor = $job_processor;
- $this->sync_worker = new Sync_Worker( $queue_manager, $job_processor );
-
- // Attach logging filters lazily after WordPress REST server is initialized.
- add_filter( 'rest_post_dispatch', function ( $response, $server, $request ) {
- return $this->maybe_log_request( $response, $request );
- }, 10, 3 );
- }
-
- /**
- * Register REST API routes.
- *
- * @since 1.0.0
- */
- public function register_routes() {
- // Jobs endpoints.
- register_rest_route(
- self::NAMESPACE ,
- '/jobs',
- array(
- array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_jobs' ),
- 'permission_callback' => array( $this, 'check_permissions' ),
- 'args' => $this->get_collection_params(),
- ),
- array(
- 'methods' => WP_REST_Server::CREATABLE,
- 'callback' => array( $this, 'create_job' ),
- 'permission_callback' => array( $this, 'check_permissions' ),
- 'args' => $this->get_create_job_params(),
- ),
- )
- );
-
- register_rest_route(
- self::NAMESPACE ,
- '/jobs/(?P
[a-zA-Z0-9_-]+)',
- array(
- array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_job' ),
- 'permission_callback' => array( $this, 'check_permissions' ),
- ),
- array(
- 'methods' => WP_REST_Server::DELETABLE,
- 'callback' => array( $this, 'delete_job' ),
- 'permission_callback' => array( $this, 'check_permissions' ),
- ),
- )
- );
-
- // Workers endpoints.
- register_rest_route(
- self::NAMESPACE ,
- '/workers/trigger',
- array(
- 'methods' => WP_REST_Server::CREATABLE,
- 'callback' => array( $this, 'trigger_worker' ),
- 'permission_callback' => array( $this, 'check_permissions' ),
- 'args' => $this->get_trigger_worker_params(),
- )
- );
-
- register_rest_route(
- self::NAMESPACE ,
- '/workers/status',
- array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_worker_status' ),
- 'permission_callback' => array( $this, 'check_permissions' ),
- )
- );
-
- // Queue statistics endpoints.
- register_rest_route(
- self::NAMESPACE ,
- '/stats',
- array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_stats' ),
- 'permission_callback' => array( $this, 'check_permissions' ),
- )
- );
-
- register_rest_route(
- self::NAMESPACE ,
- '/health',
- array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_health' ),
- 'permission_callback' => array( $this, 'check_permissions' ),
- )
- );
-
- // Queue management endpoints.
- register_rest_route(
- self::NAMESPACE ,
- '/queues/(?P[a-zA-Z0-9_-]+)/clear',
- array(
- 'methods' => WP_REST_Server::CREATABLE,
- 'callback' => array( $this, 'clear_queue' ),
- 'permission_callback' => array( $this, 'check_admin_permissions' ),
- )
- );
- }
-
- /**
- * Get jobs from the queue.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return WP_REST_Response|WP_Error Response object.
- */
- public function get_jobs( $request ) {
- global $wpdb;
-
- $per_page = $request->get_param( 'per_page' ) ?: 10;
- $page = $request->get_param( 'page' ) ?: 1;
- $status = $request->get_param( 'status' );
- $queue = $request->get_param( 'queue' );
-
- $offset = ( $page - 1 ) * $per_page;
- $table_name = $wpdb->prefix . 'redis_queue_jobs';
-
- // Build query.
- $where_conditions = array();
- $prepare_values = array();
-
- if ( $status ) {
- $where_conditions[] = 'status = %s';
- $prepare_values[] = $status;
- }
-
- if ( $queue ) {
- $where_conditions[] = 'queue_name = %s';
- $prepare_values[] = $queue;
- }
-
- $where_clause = '';
- if ( ! empty( $where_conditions ) ) {
- $where_clause = 'WHERE ' . implode( ' AND ', $where_conditions );
- }
-
- // Get total count.
- $count_query = "SELECT COUNT(*) FROM {$table_name} {$where_clause}";
- if ( ! empty( $prepare_values ) ) {
- $count_query = $wpdb->prepare( $count_query, ...$prepare_values );
- }
- $total = (int) $wpdb->get_var( $count_query );
-
- // Get jobs.
- $jobs_query = "SELECT * FROM {$table_name} {$where_clause} ORDER BY created_at DESC LIMIT %d OFFSET %d";
- $prepare_values[] = $per_page;
- $prepare_values[] = $offset;
-
- $jobs = $wpdb->get_results(
- $wpdb->prepare( $jobs_query, ...$prepare_values ),
- ARRAY_A
- );
-
- // Format jobs for response.
- $formatted_jobs = array();
- foreach ( $jobs as $job ) {
- $formatted_jobs[] = $this->format_job_response( $job );
- }
-
- $response = rest_ensure_response( $formatted_jobs );
- $response->header( 'X-WP-Total', $total );
- $response->header( 'X-WP-TotalPages', ceil( $total / $per_page ) );
-
- return $response;
- }
-
- /**
- * Get a single job by ID.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return WP_REST_Response|WP_Error Response object.
- */
- public function get_job( $request ) {
- global $wpdb;
-
- $job_id = $request->get_param( 'id' );
- $table_name = $wpdb->prefix . 'redis_queue_jobs';
-
- $job = $wpdb->get_row(
- $wpdb->prepare( "SELECT * FROM {$table_name} WHERE job_id = %s", $job_id ),
- ARRAY_A
- );
-
- if ( ! $job ) {
- return new WP_Error(
- 'job_not_found',
- __( 'Job not found.', 'redis-queue-demo' ),
- array( 'status' => 404 )
- );
- }
-
- return rest_ensure_response( $this->format_job_response( $job ) );
- }
-
- /**
- * Create a new job.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return WP_REST_Response|WP_Error Response object.
- */
- public function create_job( $request ) {
- $job_type = $request->get_param( 'type' );
- $payload = $request->get_param( 'payload' ) ?: array();
- $priority = $request->get_param( 'priority' ) ?: 50;
- $queue = $request->get_param( 'queue' ) ?: 'default';
-
- try {
- // Create job instance based on type.
- $job = $this->create_job_instance( $job_type, $payload );
- if ( ! $job ) {
- return new WP_Error(
- 'invalid_job_type',
- __( 'Invalid job type specified.', 'redis-queue-demo' ),
- array( 'status' => 400 )
- );
- }
-
- // Set job properties.
- $job->set_priority( $priority );
- $job->set_queue_name( $queue );
-
- // Enqueue the job.
- $job_id = $this->queue_manager->enqueue( $job );
-
- if ( ! $job_id ) {
- return new WP_Error(
- 'enqueue_failed',
- __( 'Failed to enqueue job.', 'redis-queue-demo' ),
- array( 'status' => 500 )
- );
- }
-
- return rest_ensure_response(
- array(
- 'success' => true,
- 'job_id' => $job_id,
- 'message' => __( 'Job created and enqueued successfully.', 'redis-queue-demo' ),
- )
- );
-
- } catch (Exception $e) {
- return new WP_Error(
- 'job_creation_failed',
- $e->getMessage(),
- array( 'status' => 500 )
- );
- }
- }
-
- /**
- * Delete (cancel) a job.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return WP_REST_Response|WP_Error Response object.
- */
- public function delete_job( $request ) {
- global $wpdb;
-
- $job_id = $request->get_param( 'id' );
- $table_name = $wpdb->prefix . 'redis_queue_jobs';
-
- // Check if job exists and is cancellable.
- $job = $wpdb->get_row(
- $wpdb->prepare(
- "SELECT * FROM {$table_name} WHERE job_id = %s AND status IN ('queued', 'failed')",
- $job_id
- )
- );
-
- if ( ! $job ) {
- return new WP_Error(
- 'job_not_found_or_not_cancellable',
- __( 'Job not found or cannot be cancelled.', 'redis-queue-demo' ),
- array( 'status' => 404 )
- );
- }
-
- // Update job status to cancelled.
- $updated = $wpdb->update(
- $table_name,
- array(
- 'status' => 'cancelled',
- 'updated_at' => current_time( 'mysql' ),
- ),
- array( 'job_id' => $job_id ),
- array( '%s', '%s' ),
- array( '%s' )
- );
-
- if ( false === $updated ) {
- return new WP_Error(
- 'job_cancellation_failed',
- __( 'Failed to cancel job.', 'redis-queue-demo' ),
- array( 'status' => 500 )
- );
- }
-
- return rest_ensure_response(
- array(
- 'success' => true,
- 'job_id' => $job_id,
- 'message' => __( 'Job cancelled successfully.', 'redis-queue-demo' ),
- )
- );
- }
-
- /**
- * Trigger worker to process jobs.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return WP_REST_Response|WP_Error Response object.
- */
- public function trigger_worker( $request ) {
- $queues = $request->get_param( 'queues' ) ?: array( 'default' );
- $max_jobs = $request->get_param( 'max_jobs' ) ?: 10;
-
- if ( ! is_array( $queues ) ) {
- $queues = array( $queues );
- }
-
- try {
- $results = $this->sync_worker->process_jobs( $queues, $max_jobs );
-
- return rest_ensure_response(
- array(
- 'success' => $results[ 'success' ],
- 'data' => $results,
- 'message' => sprintf(
- /* translators: %d: number of jobs processed */
- __( 'Worker processed %d jobs.', 'redis-queue-demo' ),
- $results[ 'processed' ] ?? 0
- ),
- )
- );
-
- } catch (Exception $e) {
- return new WP_Error(
- 'worker_execution_failed',
- $e->getMessage(),
- array( 'status' => 500 )
- );
- }
- }
-
- /**
- * Get worker status.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return WP_REST_Response Response object.
- */
- public function get_worker_status( $request ) {
- $status = $this->sync_worker->get_status();
-
- return rest_ensure_response(
- array(
- 'success' => true,
- 'data' => $status,
- )
- );
- }
-
- /**
- * Get queue statistics.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return WP_REST_Response Response object.
- */
- public function get_stats( $request ) {
- $queue_name = $request->get_param( 'queue' );
- $stats = $this->queue_manager->get_queue_stats( $queue_name );
-
- return rest_ensure_response(
- array(
- 'success' => true,
- 'data' => $stats,
- )
- );
- }
-
- /**
- * Get system health check.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return WP_REST_Response Response object.
- */
- public function get_health( $request ) {
- $health = array(
- 'redis_connected' => $this->queue_manager->is_connected(),
- 'redis_info' => array(),
- 'database_status' => $this->check_database_health(),
- 'memory_usage' => array(
- 'current' => memory_get_usage( true ),
- 'peak' => memory_get_peak_usage( true ),
- 'limit' => ini_get( 'memory_limit' ),
- ),
- 'php_version' => PHP_VERSION,
- 'wordpress_version' => get_bloginfo( 'version' ),
- 'plugin_version' => REDIS_QUEUE_DEMO_VERSION,
- );
-
- // Get Redis info if connected.
- if ( $health[ 'redis_connected' ] ) {
- try {
- $redis = $this->queue_manager->get_redis_connection();
- if ( $redis && method_exists( $redis, 'info' ) ) {
- $redis_info = $redis->info();
- $health[ 'redis_info' ] = array(
- 'redis_version' => $redis_info[ 'redis_version' ] ?? 'unknown',
- 'used_memory' => $redis_info[ 'used_memory_human' ] ?? 'unknown',
- 'connected_clients' => $redis_info[ 'connected_clients' ] ?? 'unknown',
- );
- }
- } catch (Exception $e) {
- $health[ 'redis_info' ][ 'error' ] = $e->getMessage();
- }
- }
-
- $overall_status = $health[ 'redis_connected' ] && $health[ 'database_status' ];
-
- return rest_ensure_response(
- array(
- 'success' => $overall_status,
- 'status' => $overall_status ? 'healthy' : 'unhealthy',
- 'data' => $health,
- )
- );
- }
-
- /**
- * Clear a queue.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return WP_REST_Response|WP_Error Response object.
- */
- public function clear_queue( $request ) {
- $queue_name = $request->get_param( 'name' );
-
- if ( empty( $queue_name ) ) {
- return new WP_Error(
- 'missing_queue_name',
- __( 'Queue name is required.', 'redis-queue-demo' ),
- array( 'status' => 400 )
- );
- }
-
- $result = $this->queue_manager->clear_queue( $queue_name );
-
- if ( $result ) {
- return rest_ensure_response(
- array(
- 'success' => true,
- 'message' => sprintf(
- /* translators: %s: queue name */
- __( 'Queue "%s" cleared successfully.', 'redis-queue-demo' ),
- $queue_name
- ),
- )
- );
- } else {
- return new WP_Error(
- 'queue_clear_failed',
- __( 'Failed to clear queue.', 'redis-queue-demo' ),
- array( 'status' => 500 )
- );
- }
- }
-
- /**
- * Check if user has permission to access endpoints.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return bool|WP_Error True if user has permission, WP_Error otherwise.
- */
- public function check_permissions( $request ) {
- // 1. Capability check first (logged-in admin passes immediately).
- if ( current_user_can( 'manage_options' ) ) {
- $this->last_auth_method = 'cap';
- return true;
- }
-
- // 2. Token authentication fallback with scope + rate limiting.
- $settings = get_option( 'redis_queue_settings', array() );
- $api_token = isset( $settings[ 'api_token' ] ) ? $settings[ 'api_token' ] : '';
- $scope = isset( $settings[ 'api_token_scope' ] ) ? $settings[ 'api_token_scope' ] : 'worker';
- $rate_limit_enabled = true; // Always enforce if token used; thresholds read below.
- $rate_per_min = isset( $settings[ 'rate_limit_per_minute' ] ) ? (int) $settings[ 'rate_limit_per_minute' ] : 60;
- $rate_per_min = $rate_per_min > 0 ? $rate_per_min : 60;
-
- if ( ! empty( $api_token ) ) {
- $provided = '';
- $auth_header = $request->get_header( 'authorization' );
- if ( $auth_header && stripos( $auth_header, 'bearer ' ) === 0 ) {
- $provided = trim( substr( $auth_header, 7 ) );
- }
- if ( empty( $provided ) ) {
- $provided = $request->get_header( 'x-redis-queue-token' );
- }
-
- if ( ! empty( $provided ) && hash_equals( $api_token, $provided ) ) {
- $this->last_auth_method = 'token';
- $this->last_token_used = $provided; // kept only in-memory for this request.
-
- // Enforce scope: default 'worker' only allows trigger endpoint unless scope set to full.
- $route = $request->get_route(); // e.g. /redis-queue/v1/workers/trigger
- $allowed = true;
- if ( 'full' !== $scope ) {
- $allowed_routes = apply_filters( 'redis_queue_demo_token_allowed_routes', array( '/redis-queue/v1/workers/trigger' ), $scope );
- $allowed = in_array( $route, $allowed_routes, true );
- }
- $allowed = apply_filters( 'redis_queue_demo_token_scope_allow', $allowed, $scope, $request );
- $this->last_scope_allowed = $allowed;
- if ( ! $allowed ) {
- return new WP_Error( 'rest_forbidden_scope', __( 'Token scope does not permit this endpoint.', 'redis-queue-demo' ), array( 'status' => 403 ) );
- }
-
- // Rate limiting (only token requests).
- if ( $rate_limit_enabled && $rate_per_min > 0 ) {
- $limit_ok = $this->enforce_rate_limit( $provided, $rate_per_min );
- if ( ! $limit_ok ) {
- $this->last_rate_limited = true;
- return new WP_Error( 'rate_limited', __( 'Rate limit exceeded. Try again later.', 'redis-queue-demo' ), array( 'status' => 429 ) );
- }
- }
-
- return true;
- }
- }
-
- $this->last_auth_method = 'none';
- return new WP_Error( 'rest_forbidden', __( 'You do not have permission to access this endpoint.', 'redis-queue-demo' ), array( 'status' => 403 ) );
- }
-
- /**
- * Enforce minute-based rate limit for a token.
- * Uses transients for lightweight storage.
- *
- * @param string $token Token value.
- * @param int $per_minute Allowed requests per minute.
- * @return bool True if within limit.
- */
- private function enforce_rate_limit( $token, $per_minute ) {
- $key_root = 'redis_queue_demo_rate_' . substr( hash( 'sha256', $token ), 0, 24 );
- $minute = gmdate( 'YmdHi' );
- $key = $key_root . '_' . $minute;
- $count = (int) get_transient( $key );
- $count++;
- if ( $count === 1 ) {
- // Set transient for remainder of current minute (~60 seconds) to ensure window alignment.
- $ttl = 60 - (int) gmdate( 's' );
- set_transient( $key, 1, $ttl );
- return true;
- }
- if ( $count > $per_minute ) {
- return false;
- }
- // Increment persisted count.
- $ttl = 60 - (int) gmdate( 's' );
- set_transient( $key, $count, $ttl );
- return true;
- }
-
- /**
- * Maybe log request if logging is enabled in settings.
- * @param WP_REST_Response|mixed $response Response.
- * @param WP_REST_Request $request Request.
- * @return WP_REST_Response|mixed Original response.
- */
- private function maybe_log_request( $response, $request ) {
- if ( ! $request instanceof WP_REST_Request ) {
- return $response;
- }
- $route = $request->get_route();
- if ( 0 !== strpos( $route, '/' . self::NAMESPACE) ) {
- return $response; // Not our namespace.
- }
- $settings = get_option( 'redis_queue_settings', array() );
- if ( empty( $settings[ 'enable_request_logging' ] ) ) {
- return $response;
- }
- $rotate_kb = isset( $settings[ 'log_rotate_size_kb' ] ) ? (int) $settings[ 'log_rotate_size_kb' ] : 256;
- $max_files = isset( $settings[ 'log_max_files' ] ) ? (int) $settings[ 'log_max_files' ] : 5;
- $rotate_kb = $rotate_kb > 8 ? $rotate_kb : 256;
- $max_files = $max_files > 0 ? $max_files : 5;
- $status_code = ( $response instanceof WP_REST_Response ) ? $response->get_status() : 0;
-
- $line = wp_json_encode( array(
- 'ts' => gmdate( 'c' ),
- 'method' => $request->get_method(),
- 'route' => $route,
- 'status' => $status_code,
- 'auth' => $this->last_auth_method,
- 'scope_ok' => $this->last_scope_allowed,
- 'rate_limited' => $this->last_rate_limited,
- 'user_id' => get_current_user_id(),
- 'ip' => isset( $_SERVER[ 'REMOTE_ADDR' ] ) ? sanitize_text_field( $_SERVER[ 'REMOTE_ADDR' ] ) : '',
- ) );
- $this->append_log_line( $line, $rotate_kb, $max_files );
- return $response;
- }
-
- /**
- * Append a line to the request log with rotation.
- *
- * @param string $line JSON log line.
- * @param int $rotate_kb Rotation threshold (KB).
- * @param int $max_files Max rotated files to keep.
- */
- private function append_log_line( $line, $rotate_kb, $max_files ) {
- $upload_dir = wp_upload_dir();
- $dir = trailingslashit( $upload_dir[ 'basedir' ] ) . 'redis-queue-demo-logs';
- if ( ! file_exists( $dir ) ) {
- wp_mkdir_p( $dir );
- }
- $log_file = trailingslashit( $dir ) . 'requests.log';
- $rotate_bytes = $rotate_kb * 1024;
- if ( file_exists( $log_file ) && filesize( $log_file ) > $rotate_bytes ) {
- $rotated = trailingslashit( $dir ) . 'requests-' . gmdate( 'Ymd-His' ) . '.log';
- @rename( $log_file, $rotated );
- // Cleanup old rotated files.
- $files = glob( trailingslashit( $dir ) . 'requests-*.log' );
- if ( is_array( $files ) && count( $files ) > $max_files ) {
- sort( $files ); // Oldest first (timestamp in name ensures lexical order).
- $excess = array_slice( $files, 0, count( $files ) - $max_files );
- foreach ( $excess as $old ) {
- @unlink( $old );
- }
- }
- }
- // Append line.
- $fh = @fopen( $log_file, 'ab' );
- if ( $fh ) {
- fwrite( $fh, $line . PHP_EOL );
- fclose( $fh );
- }
- }
-
- /**
- * Check if user has admin permissions for destructive operations.
- *
- * @since 1.0.0
- * @param WP_REST_Request $request Request object.
- * @return bool|WP_Error True if user has permission, WP_Error otherwise.
- */
- public function check_admin_permissions( $request ) {
- if ( ! current_user_can( 'manage_options' ) || ! wp_verify_nonce( $request->get_header( 'X-WP-Nonce' ), 'wp_rest' ) ) {
- return new WP_Error(
- 'rest_forbidden',
- __( 'You do not have permission to perform this action.', 'redis-queue-demo' ),
- array( 'status' => 403 )
- );
- }
-
- return true;
- }
-
- /**
- * Get collection parameters for jobs endpoint.
- *
- * @since 1.0.0
- * @return array Collection parameters.
- */
- private function get_collection_params() {
- return array(
- 'page' => array(
- 'description' => __( 'Current page of the collection.', 'redis-queue-demo' ),
- 'type' => 'integer',
- 'default' => 1,
- 'minimum' => 1,
- ),
- 'per_page' => array(
- 'description' => __( 'Maximum number of items to be returned in result set.', 'redis-queue-demo' ),
- 'type' => 'integer',
- 'default' => 10,
- 'minimum' => 1,
- 'maximum' => 100,
- ),
- 'status' => array(
- 'description' => __( 'Filter jobs by status.', 'redis-queue-demo' ),
- 'type' => 'string',
- 'enum' => array( 'queued', 'processing', 'completed', 'failed', 'cancelled' ),
- ),
- 'queue' => array(
- 'description' => __( 'Filter jobs by queue name.', 'redis-queue-demo' ),
- 'type' => 'string',
- ),
- );
- }
-
- /**
- * Get parameters for job creation.
- *
- * @since 1.0.0
- * @return array Job creation parameters.
- */
- private function get_create_job_params() {
- return array(
- 'type' => array(
- 'description' => __( 'Job type.', 'redis-queue-demo' ),
- 'type' => 'string',
- 'required' => true,
- 'enum' => array( 'email', 'image_processing', 'api_sync' ),
- ),
- 'payload' => array(
- 'description' => __( 'Job payload data.', 'redis-queue-demo' ),
- 'type' => 'object',
- 'default' => array(),
- ),
- 'priority' => array(
- 'description' => __( 'Job priority (lower number = higher priority).', 'redis-queue-demo' ),
- 'type' => 'integer',
- 'default' => 50,
- 'minimum' => 0,
- 'maximum' => 100,
- ),
- 'queue' => array(
- 'description' => __( 'Queue name.', 'redis-queue-demo' ),
- 'type' => 'string',
- 'default' => 'default',
- ),
- );
- }
-
- /**
- * Get parameters for worker trigger.
- *
- * @since 1.0.0
- * @return array Worker trigger parameters.
- */
- private function get_trigger_worker_params() {
- return array(
- 'queues' => array(
- 'description' => __( 'Queue names to process.', 'redis-queue-demo' ),
- 'type' => 'array',
- 'items' => array( 'type' => 'string' ),
- 'default' => array( 'default' ),
- ),
- 'max_jobs' => array(
- 'description' => __( 'Maximum number of jobs to process.', 'redis-queue-demo' ),
- 'type' => 'integer',
- 'default' => 10,
- 'minimum' => 1,
- 'maximum' => 100,
- ),
- );
- }
-
- /**
- * Create a job instance from type and payload.
- *
- * @since 1.0.0
- * @param string $job_type Job type.
- * @param array $payload Job payload.
- * @return Queue_Job|null Job instance or null on failure.
- */
- private function create_job_instance( $job_type, $payload ) {
- switch ( $job_type ) {
- case 'email':
- return new Email_Job( $payload );
- case 'image_processing':
- return new Image_Processing_Job( $payload );
- case 'api_sync':
- return new API_Sync_Job( $payload );
- default:
- return null;
- }
- }
-
- /**
- * Format job data for API response.
- *
- * @since 1.0.0
- * @param array $job Job data from database.
- * @return array Formatted job data.
- */
- private function format_job_response( $job ) {
- $payload = json_decode( $job[ 'payload' ], true );
- $result = $job[ 'result' ] ? json_decode( $job[ 'result' ], true ) : null;
-
- return array(
- 'id' => $job[ 'job_id' ],
- 'type' => $job[ 'job_type' ],
- 'queue' => $job[ 'queue_name' ],
- 'status' => $job[ 'status' ],
- 'priority' => (int) $job[ 'priority' ],
- 'payload' => $payload,
- 'result' => $result,
- 'attempts' => (int) $job[ 'attempts' ],
- 'max_attempts' => (int) $job[ 'max_attempts' ],
- 'timeout' => (int) $job[ 'timeout' ],
- 'error_message' => $job[ 'error_message' ],
- 'created_at' => $job[ 'created_at' ],
- 'updated_at' => $job[ 'updated_at' ],
- 'processed_at' => $job[ 'processed_at' ],
- 'failed_at' => $job[ 'failed_at' ],
- );
- }
-
- /**
- * Check database health.
- *
- * @since 1.0.0
- * @return bool True if database is healthy.
- */
- private function check_database_health() {
- global $wpdb;
-
- $table_name = $wpdb->prefix . 'redis_queue_jobs';
-
- // Check if table exists.
- $table_exists = $wpdb->get_var(
- $wpdb->prepare(
- "SHOW TABLES LIKE %s",
- $table_name
- )
- );
-
- return ! empty( $table_exists );
- }
-}
\ No newline at end of file
diff --git a/api/endpoints/class-jobs-endpoint.php b/api/endpoints/class-jobs-endpoint.php
deleted file mode 100644
index 9781603..0000000
--- a/api/endpoints/class-jobs-endpoint.php
+++ /dev/null
@@ -1,50 +0,0 @@
-queue_manager = $queue_manager;
- }
-
- /**
- * Register routes for this endpoint.
- *
- * @since 1.0.0
- */
- public function register_routes() {
- // This is handled by the main REST_Controller class
- // This file exists for potential future expansion
- }
-}
\ No newline at end of file
diff --git a/api/endpoints/class-workers-endpoint.php b/api/endpoints/class-workers-endpoint.php
deleted file mode 100644
index 0ea5515..0000000
--- a/api/endpoints/class-workers-endpoint.php
+++ /dev/null
@@ -1,60 +0,0 @@
-queue_manager = $queue_manager;
- $this->job_processor = $job_processor;
- }
-
- /**
- * Register routes for this endpoint.
- *
- * @since 1.0.0
- */
- public function register_routes() {
- // This is handled by the main REST_Controller class
- // This file exists for potential future expansion
- }
-}
\ No newline at end of file
diff --git a/class-github-plugin-updater.php b/class-github-plugin-updater.php
deleted file mode 100644
index c1dfee6..0000000
--- a/class-github-plugin-updater.php
+++ /dev/null
@@ -1,80 +0,0 @@
-github_url = $config[ 'github_url' ];
- $this->plugin_file = $config[ 'plugin_file' ];
- $this->plugin_slug = $config[ 'plugin_slug' ];
- $this->branch = isset( $config[ 'branch' ] ) ? $config[ 'branch' ] : 'main';
- $this->name_regex = isset( $config[ 'name_regex' ] ) ? $config[ 'name_regex' ] : '';
- $this->enable_release_assets = isset( $config[ 'enable_release_assets' ] )
- ? $config[ 'enable_release_assets' ]
- : ! empty( $this->name_regex );
-
- add_action( 'init', array( $this, 'setup_updater' ) );
- }
-
- public function setup_updater() {
- try {
- $update_checker = PucFactory::buildUpdateChecker(
- $this->github_url,
- $this->plugin_file,
- $this->plugin_slug
- );
-
- $update_checker->setBranch( $this->branch );
-
- if ( $this->enable_release_assets && ! empty( $this->name_regex ) ) {
- $update_checker->getVcsApi()->enableReleaseAssets( $this->name_regex );
- }
- } catch (\Exception $e) {
- if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
- error_log( 'GitHub Plugin Updater Error: ' . $e->getMessage() );
- }
- }
- }
-
- public static function create( $github_url, $plugin_file, $plugin_slug, $branch = 'main' ) {
- return new self( array(
- 'github_url' => $github_url,
- 'plugin_file' => $plugin_file,
- 'plugin_slug' => $plugin_slug,
- 'branch' => $branch,
- ) );
- }
-
- public static function create_with_assets( $github_url, $plugin_file, $plugin_slug, $name_regex, $branch = 'main' ) {
- return new self( array(
- 'github_url' => $github_url,
- 'plugin_file' => $plugin_file,
- 'plugin_slug' => $plugin_slug,
- 'branch' => $branch,
- 'name_regex' => $name_regex,
- ) );
- }
-}
diff --git a/composer.json b/composer.json
index 820aaf7..0d8189a 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
- "name": "soderlind/redis-queue-demo",
+ "name": "soderlind/redis-queue",
"description": "Redis-backed prioritized, delayed & retryable background jobs for WordPress (token auth, rate limiting, logging)",
- "homepage": "https://github.com/soderlind/redis-queue-demo",
+ "homepage": "https://github.com/soderlind/redis-queue",
"type": "wordpress-plugin",
"license": "GPL-2.0-or-later",
"authors": [
@@ -24,7 +24,7 @@
"scaling"
],
"support": {
- "issues": "https://github.com/soderlind/redis-queue-demo/issues"
+ "issues": "https://github.com/soderlind/redis-queue/issues"
},
"require": {
"yahnis-elsts/plugin-update-checker": "^5.6"
diff --git a/debug.php b/debug.php
deleted file mode 100644
index eba5510..0000000
--- a/debug.php
+++ /dev/null
@@ -1,85 +0,0 @@
-queue_manager ) ? 'OK' : 'FAILED' ) . "\n";
-echo " - Job Processor: " . ( is_object( $plugin->job_processor ) ? 'OK' : 'FAILED' ) . "\n";
-
-// Test 2: Check Redis connection
-echo "\n2. Redis connection:\n";
-if ( $plugin->queue_manager ) {
- echo " - Connected: " . ( $plugin->queue_manager->is_connected() ? 'YES' : 'NO' ) . "\n";
-
- // Run diagnostics
- $diagnostics = $plugin->queue_manager->diagnostic();
- echo " - Test Write: " . ( $diagnostics[ 'test_write' ] ? 'OK' : 'FAILED' ) . "\n";
- echo " - Test Read: " . ( $diagnostics[ 'test_read' ] ? 'OK' : 'FAILED' ) . "\n";
- echo " - Queue Prefix: " . $diagnostics[ 'queue_prefix' ] . "\n";
- echo " - Redis Keys: " . count( $diagnostics[ 'redis_keys' ] ) . "\n";
- if ( ! empty( $diagnostics[ 'redis_keys' ] ) ) {
- echo " - Keys: " . implode( ', ', $diagnostics[ 'redis_keys' ] ) . "\n";
- }
-} else {
- echo " - Queue manager not available\n";
-}
-
-// Test 3: Try creating a simple job
-echo "\n3. Job creation test:\n";
-try {
- $job_id = $plugin->enqueue_job( 'email', array(
- 'to' => 'test@example.com',
- 'subject' => 'Test Email',
- 'message' => 'This is a test email',
- ) );
-
- if ( $job_id ) {
- echo " - Job created: $job_id\n";
-
- // Check if it's in Redis
- $diagnostics = $plugin->queue_manager->diagnostic();
- echo " - Redis keys after job creation: " . count( $diagnostics[ 'redis_keys' ] ) . "\n";
- if ( ! empty( $diagnostics[ 'redis_keys' ] ) ) {
- echo " - Keys: " . implode( ', ', $diagnostics[ 'redis_keys' ] ) . "\n";
- }
-
- // Try to dequeue it
- $dequeued = $plugin->queue_manager->dequeue( array( 'default' ) );
- if ( $dequeued ) {
- echo " - Job dequeued successfully: " . $dequeued[ 'job_id' ] . "\n";
- echo " - Job type: " . $dequeued[ 'job_type' ] . "\n";
- echo " - Payload keys: " . implode( ', ', array_keys( $dequeued[ 'payload' ] ) ) . "\n";
- } else {
- echo " - Failed to dequeue job\n";
- }
-
- } else {
- echo " - Failed to create job\n";
- }
-} catch (Exception $e) {
- echo " - Exception: " . $e->getMessage() . "\n";
-}
-
-echo "\n=== Debug Complete ===\n";
\ No newline at end of file
diff --git a/docs/worker-rest-api.md b/docs/worker-rest-api.md
index f541d62..efebc4d 100644
--- a/docs/worker-rest-api.md
+++ b/docs/worker-rest-api.md
@@ -335,7 +335,7 @@ If token scope is worker-only and you call a disallowed endpoint:
---
## Logging & Rotation
-When enabled, logs are written to: `wp-content/uploads/redis-queue-demo-logs/requests.log`
+When enabled, logs are written to: `wp-content/uploads/redis-queue-logs/requests.log`
Rotation occurs when the file exceeds the configured size (KB). Old logs are named `requests-YYYYmmdd-HHMMSS.log`. The oldest rotated files are pruned beyond the configured maximum count.
Log line sample (JSON):
diff --git a/src/API/REST_Controller.php b/src/API/REST_Controller.php
index 988a958..e0c2558 100644
--- a/src/API/REST_Controller.php
+++ b/src/API/REST_Controller.php
@@ -1,12 +1,12 @@
prefix . 'redis_queue_jobs';
$job = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table_name} WHERE job_id = %s", $job_id ), ARRAY_A );
if ( ! $job ) {
- return new WP_Error( 'job_not_found', __( 'Job not found.', 'redis-queue-demo' ), [ 'status' => 404 ] );
+ return new WP_Error( 'job_not_found', __( 'Job not found.', 'redis-queue' ), [ 'status' => 404 ] );
}
return \rest_ensure_response( $this->format_job_response( $job ) );
}
@@ -111,15 +111,15 @@ public function create_job( $request ) {
try {
$job = $this->create_job_instance( $job_type, $payload );
if ( ! $job ) {
- return new WP_Error( 'invalid_job_type', __( 'Invalid job type specified.', 'redis-queue-demo' ), [ 'status' => 400 ] );
+ return new WP_Error( 'invalid_job_type', __( 'Invalid job type specified.', 'redis-queue' ), [ 'status' => 400 ] );
}
$job->set_priority( $priority );
$job->set_queue_name( $queue );
$job_id = $this->queue_manager->enqueue( $job );
if ( ! $job_id ) {
- return new WP_Error( 'enqueue_failed', __( 'Failed to enqueue job.', 'redis-queue-demo' ), [ 'status' => 500 ] );
+ return new WP_Error( 'enqueue_failed', __( 'Failed to enqueue job.', 'redis-queue' ), [ 'status' => 500 ] );
}
- return \rest_ensure_response( [ 'success' => true, 'job_id' => $job_id, 'message' => __( 'Job created and enqueued successfully.', 'redis-queue-demo' ) ] );
+ return \rest_ensure_response( [ 'success' => true, 'job_id' => $job_id, 'message' => __( 'Job created and enqueued successfully.', 'redis-queue' ) ] );
} catch (Exception $e) {
return new WP_Error( 'job_creation_failed', $e->getMessage(), [ 'status' => 500 ] );
}
@@ -131,13 +131,13 @@ public function delete_job( $request ) {
$table_name = $wpdb->prefix . 'redis_queue_jobs';
$job = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table_name} WHERE job_id = %s AND status IN ('queued','failed')", $job_id ) );
if ( ! $job ) {
- return new WP_Error( 'job_not_found_or_not_cancellable', __( 'Job not found or cannot be cancelled.', 'redis-queue-demo' ), [ 'status' => 404 ] );
+ return new WP_Error( 'job_not_found_or_not_cancellable', __( 'Job not found or cannot be cancelled.', 'redis-queue' ), [ 'status' => 404 ] );
}
$updated = $wpdb->update( $table_name, [ 'status' => 'cancelled', 'updated_at' => current_time( 'mysql' ) ], [ 'job_id' => $job_id ], [ '%s', '%s' ], [ '%s' ] );
if ( false === $updated ) {
- return new WP_Error( 'job_cancellation_failed', __( 'Failed to cancel job.', 'redis-queue-demo' ), [ 'status' => 500 ] );
+ return new WP_Error( 'job_cancellation_failed', __( 'Failed to cancel job.', 'redis-queue' ), [ 'status' => 500 ] );
}
- return \rest_ensure_response( [ 'success' => true, 'job_id' => $job_id, 'message' => __( 'Job cancelled successfully.', 'redis-queue-demo' ) ] );
+ return \rest_ensure_response( [ 'success' => true, 'job_id' => $job_id, 'message' => __( 'Job cancelled successfully.', 'redis-queue' ) ] );
}
public function trigger_worker( $request ) {
@@ -148,7 +148,7 @@ public function trigger_worker( $request ) {
}
try {
$results = $this->sync_worker->process_jobs( $queues, $max_jobs );
- return \rest_ensure_response( [ 'success' => $results[ 'success' ], 'data' => $results, 'message' => sprintf( __( 'Worker processed %d jobs.', 'redis-queue-demo' ), $results[ 'processed' ] ?? 0 ) ] );
+ return \rest_ensure_response( [ 'success' => $results[ 'success' ], 'data' => $results, 'message' => sprintf( __( 'Worker processed %d jobs.', 'redis-queue' ), $results[ 'processed' ] ?? 0 ) ] );
} catch (Exception $e) {
return new WP_Error( 'worker_execution_failed', $e->getMessage(), [ 'status' => 500 ] );
}
@@ -172,7 +172,7 @@ public function get_health( $request ) {
'memory_usage' => [ 'current' => memory_get_usage( true ), 'peak' => memory_get_peak_usage( true ), 'limit' => ini_get( 'memory_limit' ) ],
'php_version' => PHP_VERSION,
'wordpress_version' => get_bloginfo( 'version' ),
- 'plugin_version' => \defined( 'REDIS_QUEUE_DEMO_VERSION' ) ? REDIS_QUEUE_DEMO_VERSION : 'unknown',
+ 'plugin_version' => \defined( 'REDIS_QUEUE_VERSION' ) ? REDIS_QUEUE_VERSION : 'unknown',
];
if ( $health[ 'redis_connected' ] ) {
try {
@@ -192,13 +192,13 @@ public function get_health( $request ) {
public function clear_queue( $request ) {
$queue_name = $request->get_param( 'name' );
if ( empty( $queue_name ) ) {
- return new WP_Error( 'missing_queue_name', __( 'Queue name is required.', 'redis-queue-demo' ), [ 'status' => 400 ] );
+ return new WP_Error( 'missing_queue_name', __( 'Queue name is required.', 'redis-queue' ), [ 'status' => 400 ] );
}
$result = $this->queue_manager->clear_queue( $queue_name );
if ( $result ) {
- return \rest_ensure_response( [ 'success' => true, 'message' => sprintf( __( 'Queue "%s" cleared successfully.', 'redis-queue-demo' ), $queue_name ) ] );
+ return \rest_ensure_response( [ 'success' => true, 'message' => sprintf( __( 'Queue "%s" cleared successfully.', 'redis-queue' ), $queue_name ) ] );
}
- return new WP_Error( 'queue_clear_failed', __( 'Failed to clear queue.', 'redis-queue-demo' ), [ 'status' => 500 ] );
+ return new WP_Error( 'queue_clear_failed', __( 'Failed to clear queue.', 'redis-queue' ), [ 'status' => 500 ] );
}
public function check_permissions( $request ) {
@@ -226,36 +226,36 @@ public function check_permissions( $request ) {
$route = $request->get_route();
$allowed = true;
if ( 'full' !== $scope ) {
- $allowed_routes = apply_filters( 'redis_queue_demo_token_allowed_routes', [ '/redis-queue/v1/workers/trigger' ], $scope );
+ $allowed_routes = apply_filters( 'redis_queue_token_allowed_routes', [ '/redis-queue/v1/workers/trigger' ], $scope );
$allowed = in_array( $route, $allowed_routes, true );
}
- $allowed = apply_filters( 'redis_queue_demo_token_scope_allow', $allowed, $scope, $request );
+ $allowed = apply_filters( 'redis_queue_token_scope_allow', $allowed, $scope, $request );
$this->last_scope_allowed = $allowed;
if ( ! $allowed ) {
- return new WP_Error( 'rest_forbidden_scope', __( 'Token scope does not permit this endpoint.', 'redis-queue-demo' ), [ 'status' => 403 ] );
+ return new WP_Error( 'rest_forbidden_scope', __( 'Token scope does not permit this endpoint.', 'redis-queue' ), [ 'status' => 403 ] );
}
if ( $rate_per_min > 0 ) {
if ( ! $this->enforce_rate_limit( $provided, $rate_per_min ) ) {
$this->last_rate_limited = true;
- return new WP_Error( 'rate_limited', __( 'Rate limit exceeded. Try again later.', 'redis-queue-demo' ), [ 'status' => 429 ] );
+ return new WP_Error( 'rate_limited', __( 'Rate limit exceeded. Try again later.', 'redis-queue' ), [ 'status' => 429 ] );
}
}
return true;
}
}
$this->last_auth_method = 'none';
- return new WP_Error( 'rest_forbidden', __( 'You do not have permission to access this endpoint.', 'redis-queue-demo' ), [ 'status' => 403 ] );
+ return new WP_Error( 'rest_forbidden', __( 'You do not have permission to access this endpoint.', 'redis-queue' ), [ 'status' => 403 ] );
}
public function check_admin_permissions( $request ) {
if ( ! current_user_can( 'manage_options' ) || ! wp_verify_nonce( $request->get_header( 'X-WP-Nonce' ), 'wp_rest' ) ) {
- return new WP_Error( 'rest_forbidden', __( 'You do not have permission to perform this action.', 'redis-queue-demo' ), [ 'status' => 403 ] );
+ return new WP_Error( 'rest_forbidden', __( 'You do not have permission to perform this action.', 'redis-queue' ), [ 'status' => 403 ] );
}
return true;
}
private function enforce_rate_limit( $token, $per_minute ) {
- $key_root = 'redis_queue_demo_rate_' . substr( hash( 'sha256', $token ), 0, 24 );
+ $key_root = 'redis_queue_rate_' . substr( hash( 'sha256', $token ), 0, 24 );
$minute = gmdate( 'YmdHi' );
$key = $key_root . '_' . $minute;
$count = (int) get_transient( $key );
@@ -297,7 +297,7 @@ private function maybe_log_request( $response, $request ) {
private function append_log_line( $line, $rotate_kb, $max_files ) {
$upload_dir = wp_upload_dir();
- $dir = trailingslashit( $upload_dir[ 'basedir' ] ) . 'redis-queue-demo-logs';
+ $dir = trailingslashit( $upload_dir[ 'basedir' ] ) . 'redis-queue-logs';
if ( ! file_exists( $dir ) ) {
wp_mkdir_p( $dir );
}
diff --git a/src/Admin/Admin_Interface.php b/src/Admin/Admin_Interface.php
index 8c0c9be..2e5d224 100644
--- a/src/Admin/Admin_Interface.php
+++ b/src/Admin/Admin_Interface.php
@@ -1,9 +1,9 @@
\admin_url( 'admin-ajax.php' ),
'nonce' => \wp_create_nonce( 'redis_queue_admin' ),
'restNonce' => \wp_create_nonce( 'wp_rest' ),
'restUrl' => \rest_url( 'redis-queue/v1/' ),
'strings' => [
- 'processing' => __( 'Processing...', 'redis-queue-demo' ),
- 'success' => __( 'Success!', 'redis-queue-demo' ),
- 'error' => __( 'Error occurred', 'redis-queue-demo' ),
- 'confirmClear' => __( 'Are you sure you want to clear this queue?', 'redis-queue-demo' ),
- 'workerTriggered' => __( 'Worker triggered successfully', 'redis-queue-demo' ),
- 'queueCleared' => __( 'Queue cleared successfully', 'redis-queue-demo' ),
+ 'processing' => __( 'Processing...', 'redis-queue' ),
+ 'success' => __( 'Success!', 'redis-queue' ),
+ 'error' => __( 'Error occurred', 'redis-queue' ),
+ 'confirmClear' => __( 'Are you sure you want to clear this queue?', 'redis-queue' ),
+ 'workerTriggered' => __( 'Worker triggered successfully', 'redis-queue' ),
+ 'queueCleared' => __( 'Queue cleared successfully', 'redis-queue' ),
],
] );
- \wp_enqueue_style( 'redis-queue-admin', \plugin_dir_url( __FILE__ ) . '../../assets/admin.css', [], REDIS_QUEUE_DEMO_VERSION );
+ \wp_enqueue_style( 'redis-queue-admin', \plugin_dir_url( __FILE__ ) . '../../assets/admin.css', [], REDIS_QUEUE_VERSION );
}
// The following render methods replicate legacy output exactly.
@@ -152,7 +152,7 @@ private function save_settings() {
public function settings_saved_notice() {
?>
enqueue_job( $job_type, $payload, [ 'priority' => 10 ] );
+ $job_id = redis_queue()->enqueue_job( $job_type, $payload, [ 'priority' => 10 ] );
if ( $job_id ) {
wp_send_json_success( [ 'job_id' => $job_id, 'message' => 'Job created and enqueued successfully.' ] );
} else {
@@ -237,7 +237,7 @@ public function ajax_debug_test() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( -1 );
}
- $plugin = redis_queue_demo();
+ $plugin = redis_queue();
$results = [ 'plugin' => [ 'Queue Manager' => $plugin->queue_manager ? 'OK' : 'FAILED', 'Job Processor' => $plugin->job_processor ? 'OK' : 'FAILED' ], 'redis' => [ 'Connected' => $plugin->queue_manager->is_connected() ? 'YES' : 'NO' ] ];
wp_send_json_success( $results );
}
diff --git a/src/Admin/partials/dashboard-inline.php b/src/Admin/partials/dashboard-inline.php
index 5a76d37..cec1442 100644
--- a/src/Admin/partials/dashboard-inline.php
+++ b/src/Admin/partials/dashboard-inline.php
@@ -2,58 +2,58 @@
// Dashboard template (ported from legacy admin/class-admin-interface.php)
?>
-
+
-
+
+ class="label">
+ class="label">
-
+
+ id="trigger-worker">
+ id="refresh-stats">
+ id="run-diagnostics">
+ id="debug-test">
+ id="reset-stuck-jobs">
diff --git a/src/Admin/partials/jobs-inline.php b/src/Admin/partials/jobs-inline.php
index 9f7b74f..b489ab4 100644
--- a/src/Admin/partials/jobs-inline.php
+++ b/src/Admin/partials/jobs-inline.php
@@ -2,59 +2,59 @@
// Jobs page template.
?>
-
+
- |
- |
- |
- |
- |
- |
- |
- |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
- |
+ |
@@ -69,9 +69,9 @@ class="status-badge status-">
|
+ data-job-id="">
|
+ data-job-id="">
|
@@ -79,7 +79,7 @@ class="status-badge status-">
1 ) : ?>
- add_query_arg( 'paged', '%#%' ), 'format' => '', 'prev_text' => __( '« Previous', 'redis-queue-demo' ), 'next_text' => __( 'Next »', 'redis-queue-demo' ), 'total' => $total_pages, 'current' => $current_page ] ); ?>
+ add_query_arg( 'paged', '%#%' ), 'format' => '', 'prev_text' => __( '« Previous', 'redis-queue' ), 'next_text' => __( 'Next »', 'redis-queue' ), 'total' => $total_pages, 'current' => $current_page ] ); ?>
\ No newline at end of file
diff --git a/src/Admin/partials/settings-inline.php b/src/Admin/partials/settings-inline.php
index edae119..1b4e832 100644
--- a/src/Admin/partials/settings-inline.php
+++ b/src/Admin/partials/settings-inline.php
@@ -2,136 +2,136 @@
// Settings page template.
?>