Skip to content
bitzorcas
EN

Reference

Eventing abstractions

Event abstractions layer — domain events, integration event contracts in SaaS.Contracts, the INotificationPublisher port, and the Null/CAP implementation pair.

Last updated

This page covers the abstraction layer behind BitzOrcas’s eventing. The actual CAP infrastructure lives in Eventing — here we document the contracts and ports that make the system testable and infrastructure-independent.

Domain events

Domain events are in-process events dispatched by the Mediator pipeline’s DomainEventDispatchPipelineBehavior:

// Defined in BitzOrcas.Domain
public abstract record DomainEvent;
// Example: Sandbox module
public record NoteCreatedDomainEvent(Guid NoteId, string Title) : DomainEvent;

Lifecycle

  1. Aggregate calls AddDomainEvent(event) during a command
  2. DomainEventDispatchPipelineBehavior collects events after handler execution
  3. Events are dispatched after the transaction commits
  4. Handlers process events within the same request scope

Key difference from integration events

AspectDomain EventIntegration Event
ScopeIn-process (same request)Cross-process (via message broker)
TransportMediator pipelineCAP + RabbitMQ
Contract locationBitzOrcas.DomainBitzOrcas.SaaS.Contracts
TransactionalSame DB transactionCAP Outbox (eventual consistency)
Handler attributeN/A (auto-discovered)[CapSubscribe]

Integration event contracts

BitzOrcas.SaaS.Contracts is a shared assembly containing all cross-module event definitions:

BitzOrcas.SaaS.Contracts/
├── Auditing/ → Audit trail events
├── Catalog/ → Plan/subscription catalog events
├── Chat/ → Channel/message/member events
├── Files/ → File upload/delete events
├── Notifications/ → Notification delivery requests
├── PlatformBilling/ → Invoice/subscription/usage events
├── Tickets/ → Ticket lifecycle events
└── Webhooks/ → Webhook event envelopes + signature helpers

Contracts are pure DTOs — no behavior, no infrastructure dependencies. Both the API Host and JobHost reference this assembly.

INotificationPublisher port

public interface INotificationPublisher
{
Task PublishAsync<T>(T @event, CancellationToken ct = default)
where T : notnull;
}

Implementations

ImplementationModeBehavior
NullNotificationPublisherDefault (no DB)No-op — events silently dropped
CapNotificationPublisherProduction (with CAP)Publishes to CAP Outbox for RabbitMQ delivery

The Null pattern enables API Shell mode — the entire application starts without RabbitMQ, useful for unit testing and local development.

PortPurpose
IFileEventPublisherFile upload/delete events
ICatalogEventPublisherCatalog plan changes
IChatEventPublisherChat message events
ITicketEventPublisherTicket lifecycle events
IPlatformBillingEventPublisherBilling/subscription events

Each follows the same Null/Production pattern — a no-op default registered in CoreRuntime, overridden by CAP-based implementation in PersistenceAdapters.

Webhook event type registry

public interface IWebhookEventTypeRegistry
{
IReadOnlySet<string> RegisteredTypes { get; }
bool IsRegistered(string eventType);
}
  • Default: InMemoryWebhookEventTypeRegistry — statically configured event types
  • Events in WebhookEventTypes define the available subscription targets

Event naming convention

All integration events follow the pattern {module}.{entity}.{action}:

ticket.created — New ticket opened
ticket.assigned — Ticket assigned to agent
ticket.commented — Comment added
ticket.status_changed — Status transition
chat.message_sent — New chat message
file.uploaded — File asset created
billing.invoice_paid — Invoice payment received

See also