src/cluster_erp/core/event_bus.py içindeki EventBus, Cluster ERP modüllerinin birbirini çağırdığı tek kanaldır. Bu sayfa iki deseni (olaylar ve sorgular), işleyicilerin nasıl çalıştığını ve çevresindeki kuralları anlatır. Tüm sözleşmelerin listesi sözleşmeler başvurusu sayfasındadır.
Kısaca¶
- Bir
Event,source_modulevetimestamptaşıyan, dondurulmuş, yalnızca anahtar sözcükle oluşturulan bir dataclass'tır;Query,Event'in alt sınıfıdır (src/cluster_erp/core/event_bus.py:24-32). emit(event), tam olarak o olay türüne abone olan her işleyiciyi öncelik sırasıyla çalıştırır ve sonuçlarını liste olarak döndürür (src/cluster_erp/core/event_bus.py:83-96).query(query), tam olarak o sorgu türü için kayıtlı tek işleyiciyi çalıştırır ve sonucunu döndürür (src/cluster_erp/core/event_bus.py:98-102).- Aynı tür için ikinci bir sorgu işleyicisi
DuplicateQueryHandlerErroryükseltir; işleyicisi olmayan bir sorguQueryHandlerNotFoundErroryükseltir (src/cluster_erp/core/event_bus.py:73-81,src/cluster_erp/core/event_bus.py:98-101). - Veri yolu süreç içidir: sunucu lifespan'inde bir örnek oluşturulur ve her modüle verilir (
src/cluster_erp/server/app.py:62,src/cluster_erp/server/app.py:140).
Nasıl çalışır¶
Olaylar ve sorgular¶
| Desen | Çağrı | İşleyiciler | Sonuç | Hata davranışı | Kaynak |
|---|---|---|---|---|---|
| Olay (yayılım) | await bus.emit(event) |
subscribe ile kaydedilen sıfır veya daha fazla işleyici |
Dönen her işleyici için bir girdi içeren liste | İşleyici istisnası günlüğe yazılır ve atlanır; diğer işleyiciler yine çalışır | src/cluster_erp/core/event_bus.py:55-65, src/cluster_erp/core/event_bus.py:83-96 |
| Sorgu (noktadan noktaya) | await bus.query(query) |
register_query_handler ile kaydedilen tam bir işleyici |
İşleyicinin dönüş değeri | İşleyici yoksa QueryHandlerNotFoundError; işleyici istisnası çağırana yayılır |
src/cluster_erp/core/event_bus.py:73-81, src/cluster_erp/core/event_bus.py:98-102 |
İşleyiciler type(event) ile aranır (src/cluster_erp/core/event_bus.py:84, src/cluster_erp/core/event_bus.py:99). Bir temel sınıfa abone olan işleyici, alt sınıf olaylarını almaz.
Sıra şeması bir olayı ve bir sorguyu gösterir.
sequenceDiagram participant P as Üretici modül participant B as EventBus participant H1 as İşleyici A participant H2 as İşleyici B participant Q as Sorgu işleyicisi P->>B: emit(PartyUpdated) B->>H1: await handler(event) H1-->>B: sonuç veya istisna (günlüğe yazılır) B->>H2: await handler(event) H2-->>B: sonuç B-->>P: sonuç listesi P->>B: query(GetPartyById) B->>Q: await handler(query) Q-->>B: sonuç B-->>P: sonuç
Düz metinle: emit abone olan her işleyiciyi birbiri ardına bekler ve sonuçları toplar; bir işleyicideki istisna günlüğe yazılır ve sonrakini durdurmaz. query kayıtlı tek işleyiciyi bekler ve değerini çağırana döndürür.
Öncelikler¶
EventPriority dört değer taşır: LOW (0), NORMAL (1), HIGH (2) ve CRITICAL (3) (src/cluster_erp/core/event_bus.py:17-21). subscribe varsayılan olarak NORMAL kullanır ve her işleyici listesini en yüksek değerden en düşüğe sıralı tutar (src/cluster_erp/core/event_bus.py:55-64). Hiçbir modül varsayılan dışı bir öncelik vermez (src/cluster_erp üzerinde grep -rn "EventPriority\.\(HIGH\|LOW\|CRITICAL\)" ile arandı).
Yanıt toplamak için kullanılan olaylar¶
Çağıran yanıt beklediği halde bazı sözleşmeler olaydır, çünkü birden fazla modül yanıt vermelidir. src/cluster_erp/core/contracts.py:2043-2056 içindeki tasarım notu nedeni belirtir: query() tek sahibe izin verir, emit() ise her işleyicinin dönüş değerini döndürür. Örnekler DescribeAnalyticsFacts, CollectSubjectData, DescribeDisplaySwitches ve ResolveEntityEmails'dir (src/cluster_erp/core/contracts.py:2060, src/cluster_erp/core/contracts.py:2385, src/cluster_erp/core/contracts.py:2441, src/cluster_erp/core/contracts.py:352). GET /api/v1/_switches, DescribeDisplaySwitches işleyicilerinin döndürdüğü sözlükleri birleştirir (src/cluster_erp/server/app.py:1558-1572).
İşleyicilerdeki oturumlar¶
Bir istek içinde çalışan işleyici isteğin işlemine (transaction) katılır. core/handler_session.py, yayınlanmış bir istek oturumu varsa onu verir, yoksa kendi oturumunu açar ve onaylar (src/cluster_erp/core/handler_session.py:25-37). Kendi oturumuna ihtiyaç duyan bir işleyici, isteğin kiracı veritabanına ulaşmak için ModuleBase.request_database() kullanır (src/cluster_erp/core/module_base.py:40-59). Bkz. veritabanı ve oturumlar.
Onaydan sonraki olaylar¶
Bazı olaylar yalnızca veri kalıcı olduktan sonra tetiklenmelidir. Değişiklik geçmişi kancası TenantFieldValuesChanged olayını session.info içinde kuyruğa alır; oturum bağımlılığı kuyruğu onaydan sonra yayınlar (src/cluster_erp/core/change_history.py:357-386, src/cluster_erp/server/dependencies.py:203-222). Başarısız bir onay sonrası işleyici günlüğe yazılır ve yanıtı değiştirmez.
Neden böyle kurulmuştur¶
Projenin yazılı mühendislik kuralları modüller arası doğrudan iletişimi yasaklar ve bunun için EventBus'ı zorunlu kılar. Kurallar ayrıca modüllerin birbirini asla içe aktarmadığını, olayların çok işleyicili "ateşle ve unut", sorguların tek işleyicili istek-yanıt olduğunu ekler. EventBus belge dizgisi aynı iki deseni belirtir (src/cluster_erp/core/event_bus.py:44-49).
Kurallar ve sınırlar¶
- Bir modül başka bir modülü içe aktarmaz; tek istisna
cluster_erp.modules.auth.guards'dır. Bunutests/test_architecture_boundaries.py:46-57zorlar ve istisnayıDOORolarak adlandırır (tests/test_architecture_boundaries.py:24). - Sözleşmeler
src/cluster_erp/core/contracts.pyiçinde durur; dosyanın belge dizgisi yeni modüllerin sözleşmelerini orada tanımladığını söyler (src/cluster_erp/core/contracts.py:1-6).
Diğer parçalarla etkileşim¶
- Her modül işleyicilerini
register_eventsiçinde bağlar (src/cluster_erp/core/module_base.py:67-68). Bkz. modül yaşam döngüsü. - Sunucunun kendisi açılışta
AnonymiseSubjectolayına bir işleyici abone eder (src/cluster_erp/server/app.py:90). - Sözleşmeler başvurusu her sözleşmenin üreticilerini ve tüketicilerini listeler.
Sınırlar ve açık noktalar¶
emitişleyicileri çağıranın görevinde sırayla çalıştırır (src/cluster_erp/core/event_bus.py:89-95). Kuyruk, yeniden deneme veya kalıcılık yoktur. Abone işleyici yokken yayınlanan bir olay bir hata ayıklama günlük satırıyla düşürülür (src/cluster_erp/core/event_bus.py:85-87).- Veri yolu süreç sınırlarını aşmaz. Birden fazla işçi süreci varsa her sürecin kendi veri yolu vardır (
src/cluster_erp/server/app.py:62).
Tanıtılan terimler¶
| Terim | Kod tanımlayıcısı | Tanım | Türkçe terim | Kaynak |
|---|---|---|---|---|
| event bus | EventBus |
Olayları ve sorguları modüller arasında ileten süreç içi aracı. | olay veri yolu | src/cluster_erp/core/event_bus.py:43 |
| event | Event |
Abone olan her işleyiciye iletilen ateşle-unut mesajı. | olay | src/cluster_erp/core/event_bus.py:24-27 |
| query | Query |
Yanıtı döndüren tam bir işleyiciye iletilen istek. | sorgu | src/cluster_erp/core/event_bus.py:30-32 |
| event priority | EventPriority |
Bir olayın işleyicilerinin çalışma sırası; en yüksek önce. | olay önceliği | src/cluster_erp/core/event_bus.py:17-21 |
İlgili sayfalar¶
- Platform çekirdeği
- Sözleşmeler başvurusu
- Modül yaşam döngüsü
- Veritabanı ve oturumlar
- Mimari sınırlar
- Modüller arası yalnızca EventBus iletişimi
92f8051 numaralı commit ile 2026-11-13 tarihinde doğrulandı.