Skip to content

Typed Domain Publisher Generator #68

Description

@tsutomi

Generate a strongly-typed, domain-scoped publisher interface and its implementation for each logical group of [Event]-annotated classes, so services can depend on a focused contract rather than the catch-all IEventPublisher.

The problem today: Every service that publishes events depends directly on IEventPublisher and calls PublishAsync<TEvent>() with the concrete event type. In larger codebases this means any service can accidentally publish any event, there are no compile-time boundaries between publishing domains, and mocking in tests requires either a full IEventPublisher mock or the TestPublisher package. There is also no IDE auto-complete surface that lists which events a particular domain is responsible for.

What we will build: An additional generator within Deveel.Events.Generators — activated by a new [EventPublisher] assembly-level or class-level attribute — that:

  • Groups [Event]-annotated classes by a configurable domain name (derived from a namespace prefix, an explicit [EventPublisher("OrderDomain")] marker, or a shared base class).
  • Emits a public interface IOrderDomainEventPublisher (name derived from the group) containing one Task PublishXxxAsync(XxxEvent @event, EventPublishOptions? options = null, CancellationToken cancellationToken = default) method per event class in the group.
  • Emits a public sealed class OrderDomainEventPublisher : IOrderDomainEventPublisher implementation that delegates each method to the injected IEventPublisher, removing all boilerplate from user code.
  • Emits AddOrderDomainEventPublisher(this IServiceCollection) DI registration extensions that register the interface and implementation as scoped services.
  • Integrates with the factory generator (item 34): when both generators are active, the generated publisher methods call the compile-time ToCloudEvent() path instead of the reflection-based factory.

Benefits:

  • Domain services declare a precise dependency (IOrderDomainEventPublisher) rather than the broad IEventPublisher, making the publishing contract explicit and auditable.
  • Testing becomes trivial — mock only the three or four methods relevant to a given domain rather than the full IEventPublisher surface.
  • IDE auto-complete surfaces exactly the events a domain is authorised to publish, reducing the risk of cross-domain event leakage.
  • When combined with items 34 and 35, the entire publish path from typed interface through CloudEvent creation to schema registration involves zero runtime reflection.
  • Consistent with the framework-integration pattern (items 30–33), where the goal is to let teams adopt CloudEvents as a natural extension of their existing programming model rather than a separate concern.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions