Files
appwrite/src/Utopia/Bus/Bus.php
T
loks0nandClaude Sonnet 4.5 a0854e0591 refactor: make Bus dispatch synchronous
Remove async coroutine wrapper from event dispatch to simplify execution model and improve trace hierarchy. Listeners now execute synchronously in the caller's context, with dependency resolution inlined.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-03 20:06:06 +00:00

52 lines
1.3 KiB
PHP

<?php
namespace Utopia\Bus;
use Utopia\Span\Span;
class Bus
{
/** @var array<class-string<Event>, Listener[]> */
private array $listeners = [];
/** @var ?\Closure(string): mixed */
private ?\Closure $resolver = null;
public function setResolver(callable $resolver): self
{
$this->resolver = $resolver(...);
return $this;
}
public function subscribe(Listener $listener): self
{
foreach ($listener::getEvents() as $event) {
$this->listeners[$event][] = $listener;
}
return $this;
}
public function dispatch(Event $event): void
{
if ($this->resolver === null) {
throw new \LogicException('Bus resolver must be set via setResolver() before dispatching events');
}
$resolver = $this->resolver;
$listeners = $this->listeners[$event::class] ?? [];
foreach ($listeners as $listener) {
$deps = array_map($resolver, $listener->getInjections());
Span::init('listener.' . $listener::getName());
Span::add('bus.event', $event::class);
try {
($listener->getCallback())($event, ...$deps);
} catch (\Throwable $e) {
Span::error($e);
} finally {
Span::current()?->finish();
}
}
}
}