queue->push($payload); } /** * Push a transactional email (high priority, immediate delivery) */ public function pushTransactionalEmail(object $email): void { $this->pushEmail( email: $email, priority: QueuePriority::high(), timeout: Duration::fromMinutes(2), retryStrategy: RetryStrategyHelper::forEmails() ); } /** * Push a notification email (normal priority, moderate retry) */ public function pushNotificationEmail(object $email): void { $this->pushEmail( email: $email, priority: QueuePriority::normal(), timeout: Duration::fromMinutes(5), retryStrategy: RetryStrategyHelper::forEmails() ); } /** * Push a marketing email (low priority, aggressive retry) */ public function pushMarketingEmail(object $email): void { $this->pushEmail( email: $email, priority: QueuePriority::low(), timeout: Duration::fromMinutes(10), retryStrategy: RetryStrategyHelper::forEmails() ); } /** * Push a system email (high priority for admin notifications) */ public function pushSystemEmail(object $email): void { $this->pushEmail( email: $email, priority: QueuePriority::high(), timeout: Duration::fromMinutes(3), retryStrategy: RetryStrategyHelper::forEmails() ); } /** * Push a bulk email (background processing with batching) */ public function pushBulkEmail(object $email): void { $this->pushEmail( email: $email, priority: QueuePriority::low(), timeout: Duration::fromMinutes(15), retryStrategy: RetryStrategyHelper::forEmails() ); } /** * Push a scheduled email (delayed delivery) */ public function pushScheduledEmail(object $email, Duration $delay): void { $this->pushEmail( email: $email, delay: $delay, priority: QueuePriority::normal(), timeout: Duration::fromMinutes(5), retryStrategy: RetryStrategyHelper::forEmails() ); } /** * Push a critical email (immediate processing, no delays) */ public function pushCriticalEmail(object $email): void { $this->pushEmail( email: $email, priority: QueuePriority::critical(), timeout: Duration::fromMinutes(1), retryStrategy: RetryStrategyHelper::forEmails() ); } /** * Push a reminder email (moderate priority, future delivery) */ public function pushReminderEmail(object $email, Duration $delay): void { $this->pushEmail( email: $email, delay: $delay, priority: QueuePriority::normal(), timeout: Duration::fromMinutes(3), retryStrategy: RetryStrategyHelper::forEmails() ); } /** * Pop the next email from the queue * * @return object|null The next email object or null if queue is empty */ public function popEmail(): ?object { $payload = $this->queue->pop(); return $payload?->job; } /** * Peek at the next email without removing it * * @return object|null The next email object or null if queue is empty */ public function peekEmail(): ?object { $payload = $this->queue->peek(); return $payload?->job; } /** * Pop the next email with its metadata * * @return JobPayload|null The complete job payload or null if queue is empty */ public function popEmailWithMetadata(): ?JobPayload { return $this->queue->pop(); } /** * Get number of pending emails */ public function size(): int { return $this->queue->size(); } /** * Check if queue is empty */ public function isEmpty(): bool { return $this->size() === 0; } /** * Clear all emails from queue * * @return int Number of emails removed */ public function clear(): int { return $this->queue->clear(); } /** * Get email queue statistics */ public function getStats(): array { $stats = $this->queue->getStats(); return [ 'type' => 'email', 'size' => $this->size(), 'is_empty' => $this->isEmpty(), ...$stats, ]; } /** * Batch push multiple emails * * @param array $emails Array of email objects * @param QueuePriority|null $priority Priority for all emails */ public function pushBatch(array $emails, ?QueuePriority $priority = null): void { foreach ($emails as $email) { $this->pushEmail($email, $priority); } } /** * Push emails with different priorities based on email type * * @param array $emails Array of email objects */ public function pushSmartBatch(array $emails): void { foreach ($emails as $email) { $this->pushEmailByType($email); } } /** * Pop multiple emails in batch * * @param int $count Maximum number of emails to pop * @return array Array of email objects */ public function popBatch(int $count): array { $emails = []; for ($i = 0; $i < $count; $i++) { $email = $this->popEmail(); if ($email === null) { break; } $emails[] = $email; } return $emails; } /** * Filter emails by type/class * * @param string $emailClass The email class to filter by * @return array Emails of the specified type */ public function getEmailsByType(string $emailClass): array { $emails = []; $tempEmails = []; // Pop all emails temporarily while (! $this->isEmpty()) { $payload = $this->popEmailWithMetadata(); if ($payload === null) { break; } if ($payload->job instanceof $emailClass) { $emails[] = $payload->job; } else { $tempEmails[] = $payload; } } // Push back non-matching emails foreach ($tempEmails as $payload) { $this->queue->push($payload); } return $emails; } /** * Get emails count by priority * * @return array Priority name => count mapping */ public function getEmailCountByPriority(): array { $stats = $this->getStats(); return $stats['priority_breakdown'] ?? []; } /** * Get emails scheduled for future delivery * * @return array Emails with future delivery times */ public function getScheduledEmails(): array { $scheduledEmails = []; $tempEmails = []; // Pop all emails temporarily while (! $this->isEmpty()) { $payload = $this->popEmailWithMetadata(); if ($payload === null) { break; } if ($payload->isDelayed()) { $scheduledEmails[] = $payload->job; } $tempEmails[] = $payload; } // Push back all emails foreach ($tempEmails as $payload) { $this->queue->push($payload); } return $scheduledEmails; } /** * Get count of emails by delivery status * * @return array Status counts */ public function getDeliveryStatusCounts(): array { return [ 'pending' => $this->size(), 'scheduled' => count($this->getScheduledEmails()), 'immediate' => $this->size() - count($this->getScheduledEmails()), ]; } /** * Bulk push emails with rate limiting awareness * * @param array $emails Array of email objects * @param Duration $interval Interval between email processing */ public function pushBulkWithRateLimit(array $emails, Duration $interval): void { $delay = Duration::zero(); foreach ($emails as $email) { $this->pushEmail( email: $email, delay: $delay, priority: QueuePriority::low(), timeout: Duration::fromMinutes(10) ); $delay = $delay->add($interval); } } /** * Push email with automatic priority based on email type */ private function pushEmailByType(object $email): void { $className = get_class($email); // Automatic priority assignment based on email name patterns if (str_contains($className, 'Transactional') || str_contains($className, 'Receipt') || str_contains($className, 'Invoice')) { $this->pushTransactionalEmail($email); } elseif (str_contains($className, 'Marketing') || str_contains($className, 'Newsletter') || str_contains($className, 'Campaign')) { $this->pushMarketingEmail($email); } elseif (str_contains($className, 'System') || str_contains($className, 'Admin') || str_contains($className, 'Alert')) { $this->pushSystemEmail($email); } elseif (str_contains($className, 'Bulk') || str_contains($className, 'Batch')) { $this->pushBulkEmail($email); } elseif (str_contains($className, 'Critical') || str_contains($className, 'Emergency')) { $this->pushCriticalEmail($email); } elseif (str_contains($className, 'Reminder') || str_contains($className, 'Follow')) { $this->pushReminderEmail($email, Duration::fromHours(1)); // Default 1 hour delay } else { // Default to notification email $this->pushNotificationEmail($email); } } }