AddDomainEvent(...) ile event’i biriktirir; IUnitOfWork.SaveEntitiesAsync SaveChanges’ten sonra bu event’leri MediatR’a dispatch eder. Bir INotificationHandler<TEvent> onu yakalar (SMS, e-posta, cache drop, vb.). Süreç-arası ihtiyaç varsa handler ayrıca bir integration event yayar (Outbox → RabbitMQ).
Referans gerçek örnekler:
Domain/Events/UserOtpGeneratedDomainEvent.cs ·
Domain/AggregatesModel/UserAggregate/User.cs (AddOtpChallenge) ·
Application/DomainEventHandlers/UserOtpGenerated/SendOtpSmsDomainEventHandler.cs ·
Application/DomainEventHandlers/FaqUpdated/InvalidateFaqCacheDomainEventHandler.csGenel akış
Reçete
Domain event sınıfını tanımla
src/DiyanetCleanArchitecture.Domain/Events/FaqArchivedDomainEvent.cs. DomainEvent (SharedKernel) tabanından türet ve INotification işaretle. Event immutable ve yalnızca veri taşır:DomainEvent tabanı zaten Id (Guid v7), CorrelationID ve CreatedAt sağlar — bunları yeniden tanımlamayın. Konvansiyon: sınıf adı ...DomainEvent ile biter.Aggregate metodunda AddDomainEvent
Event yalnızca aggregate root’un içinden, iş kuralı geçtikten sonra yayılır. Karşılaştırma — gerçek
User.AddOtpChallenge’taki gerçek deseni izleyin:User örneği:Komutu/handler'ı bağla (gerekirse yeni)
Aggregate metodunu bir komut handler’dan çağırın ve mutlaka Yeni komut iskeleti için Playbook’lar overview — Command reçetesi.
SaveEntitiesAsync ile kaydedin — event’ler ancak o zaman dispatch edilir:Domain event handler yaz
src/DiyanetCleanArchitecture.Application/DomainEventHandlers/FaqArchived/InvalidateFaqCacheDomainEventHandler.cs. INotificationHandler<TEvent> implement edin. Yan etki (cache/SMS/e-posta) burada:(Opsiyonel) Integration event yayını
Olay başka bir instance/servis tarafından da işlenmeliyse (örn. çoklu-instance cache, arama indeksi, harici bildirim), Yayını domain event handler’ında yapın:
IEventBus ile bir IntegrationEvent yayın. Sözleşme BuildingBlocks.Contracts.Events altında durur:PublishAsync mesajı aynı transaction içinde MassTransit EF Outbox’a (messaging.outbox_message) yazar; relay onu RabbitMQ topic exchange’ine (integration_event_bus, routing key integration.event.FaqArchivedIntegrationEvent) bırakır.(Opsiyonel) Tüketici + abonelik
Tüketen taraf
IIntegrationEventHandler<FaqArchivedIntegrationEvent> implement eder; gerçek örnek CacheInvalidationIntegrationEventHandler’dır. Aboneliği MassTransit konfigürasyonunda AddMassTransitSubscription ile bağlayın ki IntegrationEventConsumer<FaqArchivedIntegrationEvent> kayıtlansın. Retry/DLX davranışı için Outbox Pattern ve RabbitMQ Topolojisi.Domain event mi, integration event mi?
| Soru | Domain event | Integration event |
|---|---|---|
| Aynı process içinde mi işlenir? | Evet | Hayır (process-arası) |
| Taban sınıf | DomainEvent : INotification | IntegrationEvent |
| Tetikleyici | AddDomainEvent → SaveEntitiesAsync | IEventBus.PublishAsync |
| Teslimat | In-process, transaction içi | Outbox → RabbitMQ, at-least-once |
| Idempotency gerek? | Hayır | Evet (consumer idempotent olmalı) |
| Örnek | UserOtpGeneratedDomainEvent | CacheInvalidationIntegrationEvent |
Çoğu durumda yalnızca domain event yeterlidir. Integration event’i ancak birden çok instance/servis olayı bağımsız işlemeliyse ekleyin — gereksiz integration event Outbox ve RabbitMQ yükü demektir.
İlgili
Domain Event'ler
Dispatch mekaniği ve SharedKernel DomainEvent.
Integration Event'ler
IEventBus, sözleşmeler, consumer’lar.
Outbox Pattern
Transaction-güvenli yayın + retry/DLX.
Cache Invalidation
Event’i cache düşürmek için kullanma.