Files
michaelschiemer/src/Framework/Queue/Wrappers/EventQueue.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

326 lines
8.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\Queue\Wrappers;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Queue\Queue;
use App\Framework\Queue\RetryStrategyHelper;
use App\Framework\Queue\ValueObjects\JobMetadata;
use App\Framework\Queue\ValueObjects\JobPayload;
use App\Framework\Queue\ValueObjects\QueuePriority;
use App\Framework\Retry\RetryStrategy;
/**
* Event Queue Wrapper
*
* Specialized queue wrapper for event processing with type-safe operations
* Optimized for domain events, system events, and integration events
*/
final readonly class EventQueue
{
public function __construct(
private Queue $queue
) {
}
/**
* Push any object as an event
*
* @param object $event Any event object to be processed
* @param QueuePriority|null $priority Event priority (defaults to normal)
* @param Duration|null $delay Delay before processing (defaults to immediate)
* @param Duration|null $timeout Maximum processing time
* @param RetryStrategy|null $retryStrategy Custom retry strategy
*/
public function pushEvent(
object $event,
?QueuePriority $priority = null,
?Duration $delay = null,
?Duration $timeout = null,
?RetryStrategy $retryStrategy = null
): void {
$payload = JobPayload::create(
job: $event,
priority: $priority ?? QueuePriority::normal(),
delay: $delay ?? Duration::zero(),
timeout: $timeout ?? Duration::fromMinutes(2),
retryStrategy: $retryStrategy ?? RetryStrategyHelper::forEvents(),
metadata: JobMetadata::forEvent($event)
);
$this->queue->push($payload);
}
/**
* Push a domain event (high priority for business logic)
*/
public function pushDomainEvent(object $event): void
{
$this->pushEvent(
event: $event,
priority: QueuePriority::high(),
timeout: Duration::fromMinutes(1),
retryStrategy: RetryStrategyHelper::forEvents()
);
}
/**
* Push a system event (normal priority for system operations)
*/
public function pushSystemEvent(object $event): void
{
$this->pushEvent(
event: $event,
priority: QueuePriority::normal(),
timeout: Duration::fromMinutes(3),
retryStrategy: RetryStrategyHelper::forEvents()
);
}
/**
* Push an integration event (low priority, high retry tolerance)
*/
public function pushIntegrationEvent(object $event): void
{
$this->pushEvent(
event: $event,
priority: QueuePriority::low(),
timeout: Duration::fromMinutes(10),
retryStrategy: RetryStrategyHelper::forWebhooks()
);
}
/**
* Push a notification event (background processing)
*/
public function pushNotificationEvent(object $event): void
{
$this->pushEvent(
event: $event,
priority: QueuePriority::low(),
timeout: Duration::fromMinutes(5),
retryStrategy: RetryStrategyHelper::forEmails()
);
}
/**
* Push a delayed event (scheduled for future processing)
*/
public function pushDelayedEvent(object $event, Duration $delay): void
{
$this->pushEvent(
event: $event,
delay: $delay,
priority: QueuePriority::normal(),
timeout: Duration::fromMinutes(2)
);
}
/**
* Push a critical event (immediate processing, no retries)
*/
public function pushCriticalEvent(object $event): void
{
$this->pushEvent(
event: $event,
priority: QueuePriority::critical(),
timeout: Duration::fromSeconds(30),
retryStrategy: RetryStrategyHelper::none()
);
}
/**
* Pop the next event from the queue
*
* @return object|null The next event object or null if queue is empty
*/
public function popEvent(): ?object
{
$payload = $this->queue->pop();
return $payload?->job;
}
/**
* Peek at the next event without removing it
*
* @return object|null The next event object or null if queue is empty
*/
public function peekEvent(): ?object
{
$payload = $this->queue->peek();
return $payload?->job;
}
/**
* Pop the next event with its metadata
*
* @return JobPayload|null The complete job payload or null if queue is empty
*/
public function popEventWithMetadata(): ?JobPayload
{
return $this->queue->pop();
}
/**
* Get number of pending events
*/
public function size(): int
{
return $this->queue->size();
}
/**
* Check if queue is empty
*/
public function isEmpty(): bool
{
return $this->size() === 0;
}
/**
* Clear all events from queue
*
* @return int Number of events removed
*/
public function clear(): int
{
return $this->queue->clear();
}
/**
* Get event queue statistics
*/
public function getStats(): array
{
$stats = $this->queue->getStats();
return [
'type' => 'event',
'size' => $this->size(),
'is_empty' => $this->isEmpty(),
...$stats,
];
}
/**
* Batch push multiple events
*
* @param array<object> $events Array of event objects
* @param QueuePriority|null $priority Priority for all events
*/
public function pushBatch(array $events, ?QueuePriority $priority = null): void
{
foreach ($events as $event) {
$this->pushEvent($event, $priority);
}
}
/**
* Push events with different priorities based on event type
*
* @param array<object> $events Array of event objects
*/
public function pushSmartBatch(array $events): void
{
foreach ($events as $event) {
$this->pushEventByType($event);
}
}
/**
* Pop multiple events in batch
*
* @param int $count Maximum number of events to pop
* @return array<object> Array of event objects
*/
public function popBatch(int $count): array
{
$events = [];
for ($i = 0; $i < $count; $i++) {
$event = $this->popEvent();
if ($event === null) {
break;
}
$events[] = $event;
}
return $events;
}
/**
* Filter events by type/class
*
* @param string $eventClass The event class to filter by
* @return array<object> Events of the specified type
*/
public function getEventsByType(string $eventClass): array
{
$events = [];
$tempEvents = [];
// Pop all events temporarily
while (! $this->isEmpty()) {
$payload = $this->popEventWithMetadata();
if ($payload === null) {
break;
}
if ($payload->job instanceof $eventClass) {
$events[] = $payload->job;
} else {
$tempEvents[] = $payload;
}
}
// Push back non-matching events
foreach ($tempEvents as $payload) {
$this->queue->push($payload);
}
return $events;
}
/**
* Get events count by priority
*
* @return array<string, int> Priority name => count mapping
*/
public function getEventCountByPriority(): array
{
$stats = $this->getStats();
return $stats['priority_breakdown'] ?? [];
}
/**
* Push event with automatic priority based on event type
*/
private function pushEventByType(object $event): void
{
$className = get_class($event);
// Automatic priority assignment based on event name patterns
if (str_contains($className, 'Domain') || str_contains($className, 'Business')) {
$this->pushDomainEvent($event);
} elseif (str_contains($className, 'System') || str_contains($className, 'Application')) {
$this->pushSystemEvent($event);
} elseif (str_contains($className, 'Integration') || str_contains($className, 'External')) {
$this->pushIntegrationEvent($event);
} elseif (str_contains($className, 'Notification') || str_contains($className, 'Email')) {
$this->pushNotificationEvent($event);
} elseif (str_contains($className, 'Critical') || str_contains($className, 'Alert')) {
$this->pushCriticalEvent($event);
} else {
// Default to system event
$this->pushSystemEvent($event);
}
}
}