> $listenerMap */ public function __construct( private readonly array $listenerMap, private readonly AppContainer $container, private readonly ?AuditRecorderInterface $systemAuditService = null ) { } /** * @param array $payload */ public function dispatch(string $event, array $payload): void { $listeners = $this->listenerMap[$event] ?? []; foreach ($listeners as $descriptor) { $class = ''; $method = ''; try { $class = $descriptor['class']; $method = $descriptor['method']; $listener = ModuleClassResolver::resolve($this->container, $class); if (!$listener instanceof EventListener) { continue; } $listener->{$method}($event, $payload); } catch (\Throwable $exception) { $this->recordListenerFailure($event, $class, $method, $exception); } } } private function recordListenerFailure( string $event, string $listenerClass, string $listenerMethod, \Throwable $exception ): void { if ($this->systemAuditService === null) { return; } $this->systemAuditService->record('module.listener.failed', 'failed', [ 'metadata' => [ 'module_event' => $event, 'listener_class' => $listenerClass, 'listener_method' => $listenerMethod, 'exception_class' => $exception::class, 'request_id' => RequestContext::id(), ], ]); } }