Jake Vanderwerf
2026-01-29 e6672fe38ce5d99f3b3f026154f777aded7361de
inc/rest/routes/QueueRoutes.php
@@ -11,26 +11,26 @@
use DateTimeZone;
if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
   exit; // Exit if accessed directly
}
class QueueRoutes extends RestRouteManager
{
    public function __construct()
    {
        $this->cache_name = 'queue';
        $this->cache_ttl = 300;
        parent::__construct();
   public function __construct()
   {
      $this->cache_name = 'queue';
      $this->cache_ttl = 300;
      parent::__construct();
      if (JVB_TESTING) {
         $this->cache->flush();
      }
    }
   }
    /**
     * Registers queue routes
     * @return void
     */
   /**
    * Registers queue routes
    * @return void
    */
   public function registerRoutes():void
   {
      register_rest_route($this->namespace, '/queue', [
@@ -79,48 +79,14 @@
            ]
         ]
      ]);
      register_rest_route($this->namespace, '/queue/errors', [
         'methods'   => 'GET',
         'callback'  => [$this, 'getOperationErrors'],
         'permission_callback' => [$this, 'checkPermission'],
      ]);
      register_rest_route($this->namespace, '/queue/poll', [
         'methods'   => 'GET',
         'callback'  => [$this, 'pollQueue'],
         'permission_callback' => [$this, 'checkPermission'],
         'args' => [
            'since' => [
               'type' => 'string',
               'description' => 'ISO timestamp - only return operations updated after this'
            ],
            'ids' => [
               'type' => 'string',
               'description' => 'Comma-separated IDs to check'
            ]
         ]
      ]);
      register_rest_route($this->namespace, '/queue/(?P<id>[a-zA-Z0-9_-]+)', [
         'methods'   => 'GET',
         'callback'  => [$this, 'getOperation'],
         'permission_callback' => [$this, 'checkPermission'],
         'args' => [
            'id' => [
               'required' => true,
               'type' => 'string',
            ]
         ]
      ]);
   }
    /**
     * Get queue operations with optional filtering
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
   /**
    * Get queue operations with optional filtering
    *
    * @param WP_REST_Request $request
    * @return WP_REST_Response
    */
   public function getQueue(WP_REST_Request $request): WP_REST_Response
   {
      $user_id = $request->get_param('user');
@@ -209,7 +175,7 @@
   /**
    * Format Operation object for API response
    */
   protected function formatOperationFromObject(\JVBase\managers\queue\Operation $op, bool $full = false): array
   protected function formatOperationFromObject(\JVBase\managers\queue\Operation $op): array
   {
      $formatted = [
         'id' => $op->id,
@@ -217,31 +183,31 @@
         'status' => $this->mapStateToStatus($op->state, $op->outcome),
         'progress_count' => $op->processedItems,
         'count' => $op->totalItems,
         'title' => $this->getOperationTitle($op->type, $op->requestData),
         'created_at' => $this->formatTimestamp($op->scheduledAt),
         'updated_at' => $this->formatTimestamp($op->completedAt ?? $op->startedAt ?? $op->scheduledAt),
         'retries' => $op->retries,
         'data' => $op->requestData,
         'result' => $op->result ?? [],
      ];
      if ($op->processedItems > 0 && $op->totalItems > 0) {
         $formatted['progress_percentage'] = round(($op->processedItems / $op->totalItems) * 100);
      $formatted['created_at'] = $this->formatTimestamp($op->scheduledAt);
      $formatted['updated_at'] = $this->formatTimestamp($op->completedAt ?? $op->startedAt ?? $op->scheduledAt);
      if ($op->state === 'completed' && $op->completedAt) {
         $formatted['completed_at'] = $this->formatTimestamp($op->completedAt);
      }
      if ($op->errorMessage) {
         $formatted['error_message'] = $op->errorMessage;
      }
      // Only include heavy data when requested
      if ($full) {
         $formatted['data'] = $op->requestData;
         $formatted['result'] = $op->result ?? [];
         $formatted['retries'] = $op->retries;
         $formatted['user_dismissed'] = $op->userDismissed;
         if ($op->state === 'completed' && $op->completedAt) {
            $formatted['completed_at'] = $this->formatTimestamp($op->completedAt);
         }
      if ($formatted['count'] > 0) {
         $formatted['progress_percentage'] = round(
            ($formatted['progress_count'] / $formatted['count']) * 100
         );
      }
      $formatted['title'] = $this->getOperationTitle($op->type, $op->requestData);
      $formatted['user_dismissed'] = $op->userDismissed;
      return $formatted;
   }
@@ -276,12 +242,12 @@
      return $base_title;
   }
    /**
     * Update operation status (dismiss or retry)
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
   /**
    * Update operation status (dismiss or retry)
    *
    * @param WP_REST_Request $request
    * @return WP_REST_Response
    */
   public function handleAction(WP_REST_Request $request): WP_REST_Response
   {
      $data = $request->get_json_params();
@@ -436,70 +402,4 @@
         'cleanup_reason' => null
      ];
   }
   public function pollQueue(WP_REST_Request $request): WP_REST_Response
   {
      $user_id = $request->get_param('user');
      $since = $request->get_param('since');
      $ids = $request->get_param('ids');
      $filters = [
         'not_dismissed' => true,
         'limit' => 50,
      ];
      if (!empty($ids)) {
         $filters['ids'] = array_map('trim', explode(',', $ids));
      }
      $operations = JVB()->queue()->getUserOperations($user_id, $filters);
      // Filter by timestamp if provided
      if ($since) {
         $sinceTime = strtotime($since);
         $operations = array_filter($operations, function($op) use ($sinceTime) {
            $updatedAt = strtotime($op->completedAt ?? $op->startedAt ?? $op->scheduledAt);
            return $updatedAt > $sinceTime;
         });
      }
      // Return minimal data
      $items = array_map(function($op) {
         return [
            'id' => $op->id,
            'status' => $this->mapStateToStatus($op->state, $op->outcome),
            'progress_count' => $op->processedItems,
            'count' => $op->totalItems,
            'updated_at' => $this->formatTimestamp($op->completedAt ?? $op->startedAt ?? $op->scheduledAt),
            'error_message' => $op->errorMessage,
         ];
      }, $operations);
      return new WP_REST_Response([
         'items' => array_values($items),
         'server_time' => date('c'),
         'has_active' => count(array_filter($items, fn($i) => in_array($i['status'], ['pending', 'processing']))) > 0,
      ]);
   }
   public function getOperation(WP_REST_Request $request): WP_REST_Response
   {
      $id = $request->get_param('id');
      $user_id = $request->get_param('user');
      $op = JVB()->queue()->get($id);
      if (!$op || $op->userId !== $user_id) {
         return new WP_REST_Response([
            'success' => false,
            'message' => 'Operation not found'
         ], 404);
      }
      return new WP_REST_Response([
         'success' => true,
         'operation' => $this->formatOperationFromObject($op, true) // Full data
      ]);
   }
}