Aller au contenu

BC-065B — EventBridge Persistence & Serialization Boundary

Status: HISTORICAL For the current architecture, see: ./dependances.md, ../runtime/overview.md.

Status

BC-065B completed.

No plugin file changed. No runtime mirror file changed. No Composer change. No runtime sync.

Retained option

Retained strategy: Option A — extract serialization only, plus a minimal persistence port.

Option Gain Risk Files Retained
A — payload/type extractor high low low yes
B — envelope contract DTO medium medium medium no
C — full persistence service medium high higher no

Reason:

  • EventBridge had no proven incoming consumer in production code;
  • PersistentEventStore had an isolated append signature already matching the current persisted format;
  • introducing a tiny store contract made failure-order characterization testable without changing payload, type, dispatch, store implementation or replay format.

Public API

API Signature Side effects Exceptions
constructor __construct(EventBus $eventBus, PersistableEventStore $eventStore) stores collaborators, creates serializer helper none explicitly added
publish publish(string $aggregateId, object $event): void persist then dispatch propagates store/bus exceptions unchanged
subscribe subscribe(string $eventType, callable $handler): void delegates to EventBus none explicitly added

Persisted format

EventBridge still passes the exact same values to the store:

Champ Source Type Nullabilité Exemple
aggregate_id publish($aggregateId, ...) string no product-42
event_type $event::class string no CMonChoix\Platform\Domain\Product\Event\ProductCreatedV2
payload get_object_vars($event) array<string,mixed> no ['eventId' => 'evt', 'aggregateId' => 'product-42', ...]
version default append arg int no 1
created_at generated by PersistentEventStore int no time()

Not persisted by EventBridge itself:

  • metadata
  • extra timestamp
  • renamed event type
  • replay envelope
  • hydrated object

get_object_vars() limits

The new explicit serializer preserves the old behavior exactly:

  • only publicly visible properties are extracted;
  • inherited public properties remain visible;
  • private/protected properties remain absent;
  • nested objects, arrays, nulls and DateTimeImmutable instances remain untouched.

This is now documented behavior, not an accidental side effect.

Order

The order remains:

  1. persistence
  2. dispatch

Characterized cases:

Cas Persist appelé Dispatch appelé Résultat
success / success yes yes success
persistence failure yes attempted no store exception propagated
dispatch failure yes yes attempted bus exception propagated after persistence

Partial state remains possible by design if dispatch fails after persistence.

Compatibility

Élément Avant Après Identique
event type persisted $event::class $event::class yes
payload persisted get_object_vars($event) get_object_vars($event) yes
store call count 1 1 yes
bus publish count 1 1 yes
order persist then dispatch persist then dispatch yes
plugin/runtime coupling none none yes

Remaining debt

After BC-065E final certification:

  • BC-065 is closed;
  • EventBridge remains legacy by FQCN but its persistence boundary is explicit and characterized;
  • any future redesign or retirement work must open a new dedicated BC outside BC-065.