Rule Service - Sık Sorulan Sorular
Durum ve Counter Yönetimi
S: Bir kural hem threshold hem duration koşuludur; duration sayacı ne zaman sıfırlanır?
A: Duration sayacı, eşik koşulu sağlanmadığında sıfırlanır. Eğer bir sonraki window'da koşul tekrar sağlanırsa, sayaç baştan başlar.
Örnek: VRMS_R > 250 for 600 seconds
T=0s: VRMS_R=260, condition=true, counter=50s
T=50s: VRMS_R=260, condition=true, counter=100s
T=100s: VRMS_R=240, condition=false, counter=0 (reset!)
T=150s: VRMS_R=270, condition=true, counter=50s (restart)
T=600s: VRMS_R=270, condition=true, counter=550s
T=650s: VRMS_R=270, condition=true, counter=600s → TRIGGER! ✓
Kural Değerlendirmesi
S: match_type=not tam olarak ne anlama gelir?
A: Gruptaki hiçbir kural true olmamalı. Tüm kurallar false ise grup=true, herhangi biri true ise grup=false.
match_type=not, 3 kural
Senaryo 1 (tümü false):
Rule1: false, Rule2: false, Rule3: false
Sonuç: Grup = TRUE ✓ (hiçbiri true değil)
Senaryo 2 (biri true):
Rule1: false, Rule2: true, Rule3: false
Sonuç: Grup = FALSE ✗ (Rule2 true, not koşulu bozuldu)
Kullanım örneği:
"Pompa çalışmıyor VE akım yok VE alarm yok → Normal durum" gibi
"tüm uyarıcı sinyaller sessiz" durumunu yakalamak için kullanılır
S: Bir grup içinde 5 kural var; tümü true ama match_type=any; ne olur?
A: Grup true olur ve tetiklenme aksiyonu çalışır. Erken çıkış (short-circuit) optimize için uygulanabilir ama tüm kurallar değerlendirilir.
match_type=any
Rule1: false
Rule2: true ← İlk true, ama diğerleri de kontrol edilir (audit için)
Rule3: true
Rule4: true
Rule5: true
Sonuç: Grup = true (any → en az 1 true yeterli)
S: multi_trigger=true ve cooldown_sec=300 ise ne olur?
A: Koşul her window'da sağlansa bile, son tetiklenme üstünden 300 saniye geçmeden yeni tetikleme yapılmaz.
Cooldown_Sec = 300
T=0s: Condition=true → Trigger! ✓ Last_Fired_Time = T+0
T=50s: Condition=true → Skip ✗ (250s cooldown kaldı)
T=200s: Condition=true → Skip ✗ (100s cooldown kaldı)
T=300s: Condition=true → Trigger! ✓ Last_Fired_Time = T+300
T=350s: Condition=true → Skip ✗ (yeniden cooldown başladı)
Kontrol: now() - Last_Fired_Time >= Cooldown_Sec. Last_Fired_Time buffer'da saklanır.
S: Grubun valid_from / valid_to penceresi dışında event gelirse ne olur?
A: Grup skip edilir; mevcut state değiştirilmez.
Grup: valid_from = "08:00", valid_to = "20:00"
Event timestamp = 22:30 → Pencere dışı → Grup skip
- Triggered durumu değiştirilmez
- duration_counter değiştirilmez
- Hiç event üretilmez
Event timestamp = 10:00 → Pencere içi → Normal değerlendirme
valid_from ve valid_to null ise her zaman aktif kabul edilir.
S: multi_trigger=false; aynı kural grubu aynı window'da iki kez tetiklenir se ne olur?
A: Sadece ilk tetiklenme kaydedilir. device_rule_state.is_triggered=true olduğunda, aynı window'da ikinci bir tetiklenme event'i üretilmez.
State: is_triggered = false
Window 1:
- Condition: true
- State change: false → true ✓
- Emit: rule.triggered.v1
Window 2:
- Condition: still true
- State change: none (already true)
- multi_trigger=false → NO event
- is_triggered remains true
Window 3:
- Condition: false
- State change: true → false ✓
- Emit: rule.reset.v1 (if notify_on_reset=true)
Publish ve Bildirim
S: Publish=false iken kural tetiklenir; ne olur?
A: Action tetiklenir (inbox mesajı gönderilir) ama push notification gönderilmez. Audit tablosuna yaz yapılır.
Kural: HighVoltage (trigger_action_plan_id=21)
Publish=false
Aksiyon Plan 21 içinde:
├─ Step 1: WhatsApp (channel=whatsapp)
├─ Step 2: Push (channel=push) ← Gönderilmeyecek!
├─ Step 3: Audit (channel=audit)
└─ Step 4: Email (channel=email) ← Gönderilecek
Sonuç: WhatsApp + Email + Audit yapılır, Push yok.
S: publish_bit=99 ne demek?
A: publish_bit=99 her zaman publish anlamına gelir. Diğer değerler (0-63) measurement_register.publish bitini kontrol eder.
publish_bit = 99
→ Her durumda mesaj publish edilir (measurement_register bit kontrolü yapılmaz)
publish_bit = 5
→ Sadece measurement_register.bit[5]=1 ise publish
Device Rule Buffer
S: Device rule buffer nedir?
A: Device Rule Buffer, bir (device_id, rule_group_id) çifti için tüm durum bilgisini tutan Redis object'idir.
Saklanan Veriler:
- Register geçmişi (transition'lar için eski değer)
- Duration counter'lar (her kural için)
- Grup state (is_triggered, trigger_count)
- Publish cache (measurement_register.publish snapshot)
- Last accessed timestamp
TTL: 24 saat (güncelleme ile reset)
[Detay bkz: Device Rule Buffer Design - TBD]
Kural Priority'si
S: Rule priority ne zaman kullanılır?
A: Kural priority, bir grup içundeki kuralların değerlendirme sırasını belirler. Düşük sayı daha önceliklidir.
Grup: HighCurrentCheck (match_type=all)
├─ Rule1 (priority=0): IRMS > 50
├─ Rule2 (priority=1): i_imb < 20
└─ Rule3 (priority=2): duration >= 30s
Evaluation order: Rule1 → Rule2 → Rule3
AND logic: tüm kurallar true olmalı
If Rule1=false → short-circuit, Rule2/3 skip
Grup level priority:
GroupA (priority=1) → evaluated first
GroupB (priority=2) → evaluated second
GroupC (priority=3) → evaluated third
Aksiyon sırası da grup priority'ye göre
Register Transition
S: Register transition'da joker (*) nasıl çalışır?
A: Bit masking ile. 0x01** demek "ilk 2 bit 01, sonrası önemsiz" demek.
Rule: old_value=0x0101 → new_value=0x0111 (mask: 0xFF00)
Device Status Changes:
0x0100 → 0x0101: Matches ✓ (last 2 bit changed)
0x0101 → 0x0111: Matches ✓
0x0100 → 0x0110: No match ✗ (ilk 2 bit aynı kaldı)
State Persistence
S: device_rule_state ve rule_events arasındaki fark ne?
A:
-
device_rule_state: Güncel state (snapshot) - one row per (device_id, rule_group_id)
is_triggered: true/falsetrigger_count: toplam tetik sayısılast_trigger_time,last_reset_time
-
rule_events: Append-only audit log - her tetikleme/sıfırlama/reset bir satır
- Event type: triggered, reset, notified, command_sent
- Details JSON ile sebep kaydı
Senaryo: Kural 5 kez tetiklendi, 2 kez sıfırlandı
device_rule_state:
├─ is_triggered: false
├─ trigger_count: 5
├─ last_trigger_time: 2026-03-14 20:30:15Z
└─ last_reset_time: 2026-03-14 20:45:30Z
rule_events (append-only):
├─ Event 1: triggered, 2026-03-14 20:15:00Z
├─ Event 2: triggered, 2026-03-14 20:15:50Z
├─ Event 3: triggered, 2026-03-14 20:16:40Z
├─ Event 4: reset, 2026-03-14 20:45:25Z
├─ Event 5: triggered, 2026-03-14 20:20:00Z
├─ Event 6: triggered, 2026-03-14 20:20:50Z
└─ Event 7: reset, 2026-03-14 20:45:30Z
Cache ve Fallback
S: Redis'te kural yoksa ne olur?
A: DB'den yüklenir ve Redis'e cachelenir (TTL=24h).
Lookup Order:
1. Redis: rule:{group_id}
└─ Found → Use immediately (Fast path ~1-5ms)
└─ Not found → Step 2
2. PostgreSQL: SELECT * FROM rule_groups WHERE id=X
└─ Found → Load to Redis (TTL=24h), use
└─ Not found → Error, skip evaluation
Operasyon Notları
S: Kural değişikliğinde ne olur?
A: Cache invalidation yapılmalı. Yaklaşım:
- Rule tanımı PostgreSQL'de update edilir
- Redis cache key'den sil (
DEL rule:{group_id}) - Sonraki evaluation'da DB'den yeni tanım yüklenir
Not: rule_hash alanı değişiklik tespit etmek için kullanılır.
S: Cooldown nedir?
A: Aynı grubu çok hızlı tetiklemekten korumak için. multi_trigger=true ise zorunlu.
group.cooldown_sec = 300
T=0s: Condition true → Trigger Event ✓
T=50s: Condition still true → Skip (300s cooldown'da)
T=200s: Condition still true → Skip (cooldown'da)
T=300s: Condition still true → Trigger Event ✓ (cooldown reset)
Hata Senaryoları
S: Kural değerlendirme sırasında hata olursa?
A: Observer pattern:
- Kritik hata (e.g., corrupted rule) →
rule.failed.v1emit, device skip - Cache miss (e.g., Redis down) → DB fallback
- Kısmi başarısızlık (e.g., 5/10 cihaz başarısız) → Log and continue
Processing Device E2E-001:
├─ GroupA: ✓ Success
├─ GroupB: ✗ Cache miss → DB fallback → ✓ Success
├─ GroupC: ✗ Invalid variable → rule.failed.v1, skip, continue
├─ GroupD: ✓ Success
│
Sonuç: 3/4 group başarılı, error logged