get_queue(); if ( count( $queue ) >= self::MAX_QUEUE_DEPTH ) { PRAutoBlogger_Logger::instance()->warning( sprintf( 'Opik queue full (%d items); dropping span', count( $queue ) ), 'opik' ); return false; } $item = array( 'type' => $type, 'payload' => $payload, 'enqueued' => time(), 'attempt' => 0, ); $queue[] = $item; update_option( self::QUEUE_OPTION_KEY, $queue ); return true; } /** * Dequeue the next N items from the queue for processing. * * @param int $limit Max items to dequeue. * * @return array Array of items with 'type', 'payload', 'enqueued', 'attempt'. */ public function dequeue( int $limit = 100 ): array { $queue = $this->get_queue(); if ( empty( $queue ) ) { return array(); } // Remove expired items. $now = time(); $queue = array_filter( $queue, function( $item ) use ( $now ) { return ( $now - $item['enqueued'] ) < self::ITEM_TTL_SECONDS; } ); // Grab the first $limit items. $batch = array_splice( $queue, 0, $limit ); // Save the remaining queue. update_option( self::QUEUE_OPTION_KEY, $queue ); return $batch; } /** * Re-enqueue items that failed to post (typically after backoff). * * @param array $items Items from a failed batch. */ public function reenqueue( array $items ): void { $queue = $this->get_queue(); foreach ( $items as $item ) { $item['attempt'] = ( $item['attempt'] ?? 0 ) + 1; // Drop items that have exceeded max retries (3). if ( $item['attempt'] >= 3 ) { PRAutoBlogger_Logger::instance()->warning( sprintf( 'Dropping Opik item after %d attempts: %s', $item['attempt'], $item['type'] ), 'opik' ); continue; } $queue[] = $item; } update_option( self::QUEUE_OPTION_KEY, $queue ); } /** * Get the current queue state. * * @return array */ public function get_queue(): array { $queue = get_option( self::QUEUE_OPTION_KEY, array() ); return is_array( $queue ) ? $queue : array(); } /** * Get queue depth (item count). * * @return int */ public function get_queue_depth(): int { return count( $this->get_queue() ); } /** * Clear all items from the queue. * * @return void */ public function clear(): void { delete_option( self::QUEUE_OPTION_KEY ); } /** * Get a human-readable status string for admin display. * * @return string */ public function get_status(): string { $depth = $this->get_queue_depth(); if ( 0 === $depth ) { return 'Queue empty'; } return sprintf( 'Queue: %d item%s pending', $depth, 1 !== $depth ? 's' : '' ); } }