Beacon/NOTES.md

108 lines
4.6 KiB
Markdown
Raw Permalink Normal View History

Beacon is an Event Management system built originally for use in the Phred Framework, but opened to the public to install in any codebase. It follows a strict PSR-14 (Event Dispatcher) implementation with an "Enterprise-First" architecture.
# Features & Functionality (Mind Map)
- Event Dispatcher (The "Engine")
- Primary entry point: `$dispatcher->dispatch($event)`
- Returns the modified/original event object (PSR-14)
- **Contract Isolation**: Split into `BeaconContracts` (Interfaces) and `Beacon` (Implementation).
- **Bridge Support**: `BeaconBridges` for third-party adapters (Symfony, Laravel).
- **Middleware Pipeline**: Onion-style pipeline for pre/post dispatch logic.
- **Resiliency**: Configurable error handling (Fail-fast vs. Continue/Log).
- Event Listeners & Providers
- **Listener Provider**: Separate PSR-14 component to resolve listeners for an event.
- **Class-based Subscribers**: Implement `SubscriberInterface` for multiple events.
- **Priority System**: Higher integer = higher priority (runs earlier).
- **Wildcard Support**: Pattern matching (e.g., `App.User.*`) translated internally to cached regex for efficiency.
- **Lazy Loading**: Listeners instantiated only when needed via PSR-11 container.
- Event Objects & Context
- **Plain Old PHP Objects (POPOs)**: Any object can be an event.
- **Event Envelope**: Optional wrapper to carry immutable metadata/context via a `ContextMap`.
- **Stoppable Events**: Implements `StoppableEventInterface` (PSR-14).
- **Inheritance Resolution**: Automatically resolves listeners for parent classes and interfaces; includes a configuration toggle for high-performance interface skipping.
- Discovery & Registration
- **Attribute Discovery**: PHP 8.2 `#[AsEventListener]` for zero-config registration.
- **Discovery Logic**: A `ListenerDiscovery` service scans directories (using PSR-4 mapping or explicit paths).
- **Discovery Cache**: PSR-16 cache support for scanning and mapping attributes (eliminates runtime scanning).
- **DI Integration**: Accept a PSR-11 container to resolve listener instances; discovery yields service IDs or class names for lazy instantiation.
- **Manual Registration**: Fluent API for one-off listeners or closures (uses `addListener`).
- Integration & Advanced Features
- **Async Dispatching**: Offloaded via `QueueingDispatcher` decorator (in Bridges); serializes the `EventEnvelope`.
- **PII & Logging**: Masking and sensitive data handling live strictly in Bridges or Middleware, keeping the engine core pure.
- **Resiliency & Error Handling**: `continue` mode emits a `DispatchFailed` event containing the listener, exception, and original event payload for audit/retry.
- **Enterprise Telemetry**: Trace execution timing and listener flow.
- **Testing Helpers**: PHPUnit traits for easy event assertions.
# Concepts: Unified Event Listening
## The Dispatcher API
The primary way to trigger an event is through the `$dispatch()` method.
```php
$dispatcher->dispatch($event);
```
## Listener Registration
We prefer structured class-based listeners, but support closures for lightweight tasks.
- `addListener(string $event, callable $listener, int $priority = 0)`
- `addSubscriber(SubscriberInterface $subscriber)`
# API Examples (Drafts)
## Basic Dispatching
```php
$dispatcher = new EventDispatcher($provider);
$event = new UserRegistered($user);
// "Enterprise" Dispatching
$dispatcher->dispatch($event);
```
## Middleware Example
```php
class LoggingMiddleware implements DispatchMiddlewareInterface {
public function handle(object $event, callable $next): object {
$log->info("Dispatching: " . $event::class);
return $next($event);
}
}
```
## Class-based Subscriber (Unified)
```php
class UserSubscriber implements SubscriberInterface {
public static function getSubscribedEvents(): array {
return [
UserRegistered::class => 'onUserRegistered',
UserDeleted::class => ['onUserDeleted', 10], // with priority
];
}
public function onUserRegistered(UserRegistered $event): void { /* ... */ }
}
```
## Attribute-based Discovery
```php
#[AsEventListener(event: UserRegistered::class, priority: 10)]
class SendWelcomeEmailListener {
public function __invoke(UserRegistered $event): void { /* ... */ }
}
```
## Stoppable Events (with Convenience Trait)
```php
class OrderEvent implements StoppableEventInterface {
use CanStopPropagation; // Provides stopPropagation() and isPropagationStopped()
}
```
## Contextual Data (Envelope)
```php
$envelope = new EventEnvelope($event, ['request_id' => 'abc-123']);
$dispatcher->dispatch($envelope);
```