ForgeEvents Module

Overview

ForgeEvents is a powerful event system module that implements the publish-subscribe pattern, allowing for decoupled communication between different parts of your application. It provides a robust foundation for event-driven architecture with support for synchronous and asynchronous event handling.

Features

The event system offers a comprehensive set of features for event management:

  • Event Dispatching: Simple and intuitive event dispatching mechanism
  • Event Listeners: Support for multiple listeners per event
  • Queue Integration: Optional queue-based event processing
  • Retry Mechanism: Configurable retry attempts for failed event handling
  • Async Processing: Support for asynchronous event processing
  • Event Subscribers: Organize related event listeners in subscriber classes
  • Error Handling: Robust error handling for event processing

Configuration

Configure the event system through the config/forge_events.php file:

// config/forge_events.php
return [
    'queue_driver' => App::env('FORGE_EVENT_QUEUE_DRIVER', 'sync'),
    'max_retries' => 3,
    'listeners' => [
        'user.created' => [
            function (\Forge\Core\Contracts\Modules\ForgeEventInterface $event) {
                $userData = $event->getPayload();
                $logger = App::getContainer()->get(LoggerInterface::class);
                $logger->log("User created " . json_encode($userData));
            }
        ]
    ]
];

queue_driver: Specifies the queue driver for event processing ('sync' or 'async').

max_retries: Maximum number of retry attempts for failed event processing.

listeners: Array of event listeners mapped to event names.

Usage Examples

Here are practical examples of using the event system:

1. Creating and Dispatching Events

use Forge\Core\Contracts\Events\EventInterface;

class DatabaseQueryExecuted implements EventInterface
{
    public function __construct(
        public readonly string $query,
        public readonly array $bindings,
        public readonly float $timeInMilliseconds
    ) {}
}

// Dispatching the event
$eventDispatcher->dispatch(new DatabaseQueryExecuted(
    $query,
    $bindings,
    $executionTime
));

2. Event Listeners

use Forge\Modules\ForgeDebugbar\Listeners\DatabaseQueryListener;

class DebugBarModule extends ModulesInterface
{
    public function onAfterModuleRegister(Container $container): void
    {
        $eventDispatcher = $container->get(EventDispatcherInterface::class);
        
        if ($container->has(DebugBarInterface::class)) {
            $debugBarInterface = $container->get(DebugBarInterface::class);
            $databaseQueryListener = new DatabaseQueryListener($debugBarInterface);
            $eventDispatcher->listen(DatabaseQueryExecuted::class, $databaseQueryListener);
        }
    }
}

3. Using Events in Core Components

// Example from Bootstrap.php
public function handleRequest(Request $request): Response
{
    $response = $this->middlewareStack->run($request, $coreHandler);

    if (!$this->isCli && $this->container->has(DebugBarInterface::class)) {
        $eventDispatcher = $this->container->get(EventDispatcherInterface::class);
        $eventDispatcher->dispatch(new ResponseReadyForDebugBarInjection(
            $response,
            $this->container
        ));
    }

    return $response;
}