Durum: Kabul edildi; projenin yazılı mühendislik kurallarında belirtilir. Bu kayıt, Cluster ERP'nin bir modülünün başka bir modülü asla import etmediği ve diğer modüllere yalnız src/cluster_erp/core/event_bus.py içindeki EventBus üzerinden, src/cluster_erp/core/contracts.py sözleşmeleriyle ulaştığı kuralı kapsar. Mekanizmanın kendisi olay veri yolu sayfasında açıklanır.
Bağlam¶
Cluster ERP src/cluster_erp/modules/ altında modüllere bölünür; paket klasörü olarak sayıldığında 28 tanedir. Her modül kayıt defteri tarafından ayrı yüklenir ve etkin olabilir ya da olmayabilir (src/cluster_erp/core/module_registry.py:58-72). Projenin yazılı mühendislik kuralları modüller arası doğrudan iletişimi yasaklar ve buna zorunlu bir mimari kural der. Sınır testi amacı belirtir: kurallar "held by a test instead of by memory" (tests/test_architecture_boundaries.py:1-11). Modülleri bağımsız tutmanın ötesinde bir gerekçe koddan belirlenemez.
Karar¶
- Bir modül başka bir modülü asla import etmez. Onaylanmış tek import, kullanıcı tipini ve yetki bağımlılıklarını sağlayan
cluster_erp.modules.auth.guards'tır (tests/test_architecture_boundaries.py:3-7,tests/test_architecture_boundaries.py:24). - Geri kalan her şey
EventBusüzerinden gider: birEventateşle-unut türündedir ve herhangi sayıda işleyicisi olabilir; birQueryistek ve yanıttır ve tam olarak bir işleyicisi vardır (src/cluster_erp/core/event_bus.py:43-49). - Sözleşmeler
src/cluster_erp/core/contracts.pyiçindeki dondurulmuş dataclass'lardır. src/cluster_erp/server/routes/içindeki uygulama katmanı bir modül değildir. Tek bir istekte birden çok modül servisini düzenleyebilir (src/cluster_erp/server/routes/party_composite.py:4-9).
Sıra şeması iki kalıbı gösterir.
sequenceDiagram participant A as Modül A servisi participant Bus as EventBus participant B as Modül B işleyicisi participant C as Modül C işleyicisi A->>Bus: emit(Event) Bus->>B: handler(event), önceliğe göre Bus->>C: handler(event), önceliğe göre A->>Bus: query(Query) Bus->>B: kayıtlı tek işleyici B-->>A: sonuç
Düzyazıyla: emit, olayın tipine abone olan her işleyiciyi EventPriority sırasıyla çağırır ve sonuçlarını döndürür (src/cluster_erp/core/event_bus.py:55-65, src/cluster_erp/core/event_bus.py:83-96). query, sorgunun tipi için kayıtlı tek işleyiciyi çağırır ve yanıtını döndürür (src/cluster_erp/core/event_bus.py:98-102).
Sonuçlar¶
src/cluster_erp/core/contracts.py,Event'ten türeyen 146 veQuery'den türeyen 118 sınıf içerir (grep -cile sayıldı).- Bir olay işleyicisindeki istisna günlüğe yazılır ve göndericiye ulaşmaz; diğer işleyiciler yine çalışır (
src/cluster_erp/core/event_bus.py:91-95). - İşleyicisi olmayan bir sorgu
QueryHandlerNotFoundErrorfırlatır (src/cluster_erp/core/event_bus.py:98-101). Aynı sorgu için ikinci bir işleyici kayıt sırasındaDuplicateQueryHandlerErrorfırlatır (src/cluster_erp/core/event_bus.py:78-79). - Bir istek içinde çalışan işleyiciler, geçerli kiracının veritabanını okumak için
request_database()kullanır (src/cluster_erp/core/module_base.py:40-59). - Modülleri aşan doğrulama bir sorgudur. Örnek:
ensure_product_breakdown,products_and_servicesmodülünün yanıtladığıValidateProductBreakdowngönderir (src/cluster_erp/core/product_breakdown.py:11-13,src/cluster_erp/modules/products_and_services/module.py:131). - Masaüstü istemci aynı fikri kendi sinyal veri yoluyla izler; bkz. sinyal veri yolu ve watch_entity.
Kodun uyguladığı yerler¶
| Mekanizma | Neyi denetler | Kaynak |
|---|---|---|
test_no_module_imports_another_module_except_through_the_guards_door |
Her modül dosyasındaki her import | tests/test_architecture_boundaries.py:46-57 |
test_modules_exist |
Tarama en az 20 modülü kapsar | tests/test_architecture_boundaries.py:42-43 |
EventBus.register_query_handler |
Sorgu tipi başına bir işleyici | src/cluster_erp/core/event_bus.py:73-81 |
CI test işi |
Sınır testini her gönderimde çalıştırır | .github/workflows/ci.yml:124 |
İlgili sayfalar¶
92f8051 numaralı commit ile 2026-11-13 tarihinde doğrulandı.