Skip to main content
Domain event, bir aggregate’in içinde “şu önemli şey oldu” demesinin yoludur. Aggregate metodu state’i değiştirir ve 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.cs

Genel akış

Reçete

1

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.
2

Aggregate metodunda AddDomainEvent

Event yalnızca aggregate root’un içinden, iş kuralı geçtikten sonra yayılır. User.AddOtpChallenge’taki gerçek deseni izleyin:
Karşılaştırma — gerçek User örneği:
3

Komutu/handler'ı bağla (gerekirse yeni)

Aggregate metodunu bir komut handler’dan çağırın ve mutlaka SaveEntitiesAsync ile kaydedin — event’ler ancak o zaman dispatch edilir:
Yeni komut iskeleti için Playbook’lar overview — Command reçetesi.
4

Domain event handler yaz

src/DiyanetCleanArchitecture.Application/DomainEventHandlers/FaqArchived/InvalidateFaqCacheDomainEventHandler.cs. INotificationHandler<TEvent> implement edin. Yan etki (cache/SMS/e-posta) burada:
Konvansiyon: handler’lar Application/DomainEventHandlers/<EventName>/<Amaç>DomainEventHandler.cs altında, tek class tek dosya. Aynı event için birden çok yan etki gerekiyorsa (örn. SMS + e-posta) ayrı handler’lar yazın — SendOtpSmsDomainEventHandler ve SendOtpEmailDomainEventHandler aynı UserOtpGeneratedDomainEvent’i bağımsız dinler.
5

(Opsiyonel) Integration event yayını

Olay başka bir instance/servis tarafından da işlenmeliyse (örn. çoklu-instance cache, arama indeksi, harici bildirim), IEventBus ile bir IntegrationEvent yayın. Sözleşme BuildingBlocks.Contracts.Events altında durur:
Yayını domain event handler’ında yapın:
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.
6

(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.
7

Test

En az aggregate seviyesinde event üretimini doğrulayın:
Handler için DB değişikliği varsa migration ekleyin:

Domain event mi, integration event mi?

Ç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.