Ana içeriğe geç

Rule Servisi

Rule Servisi, Cınga veri hattındaki ölçüm katmanlarını (raw, synth, window, status-register) kural tablosuna göre değerlendiren ve koşul sağlandığında aksiyon üreten karar mikroservisidir.

Bu servis hesap motorlarının yerine geçmez; hesaplanmış veriyi ve register bitlerini okuyup iş kuralı çalıştırır.

Sorumluluk

  • raw.persisted.v1, synth.ready.v1, window.ready.v1, heartbeat.status.changed.v1 eventlerini tüketmek
  • Kural snapshot’ını (cihaz özel > global) çözmek
  • Koşulları değerlendirmek (threshold, trend, bitmask, kombinasyon)
  • Kural tetiklenince aksiyon üretmek (alarm, komut, bildirim, kayıt)
  • Sonuçları audit trail’e yazmak

Kural Kaynakları

  • Grup tablosu: rule_groups
  • Kural tablosu: rules
  • Kural cache: Redis rules:{device_id}:latest / rules:0:latest
  • Öncelik:
    1. Cihaz özel kural
    2. Global kural

İşlem Akışı

Kural Tipleri (V1)

  • Threshold kuralı (value > limit, value < limit)
  • Trend kuralı (slope, r2, p95 bazlı)
  • Status-bit kuralı (STATUS_FAULT_*, STATUS_P_HIGH vb.)
  • Kompozit kural (AND/OR ile çoklu kaynak)
  • Süre koşulu (condition true for X min)

Aksiyon Tipleri (V1)

  • ALERT_CREATE (Observer/notification pipeline)
  • DEVICE_COMMAND_REQUEST (kontrollü komut akışı)
  • RULE_TAG_WRITE (durum etiketleme)
  • AUDIT_ONLY (yalnız kayıt)

Not: Cihaz komutu doğrudan Rule Servisi içinden gönderilmez; komut ayrı kontrol katmanına event ile devredilir.

Aksiyon yürütme katmanı için bkz: Action Executor Servisi.

Çoklu Aksiyon Modeli (Action Plan)

Tek action_id yerine plan tabanlı model kullanılır:

  • trigger_action_plan_id
  • reset_action_plan_id

Bir action plan içinde birden fazla aksiyon adımı olabilir:

  • WhatsApp mesajı
  • E-posta
  • Mobil push
  • Webhook
  • Audit kaydı

Bu sayede tek kural tetiğiyle çoklu kanal orkestrasyonu yapılır.

Veri Modeli (Group + Rules)

rule_groups

Birden fazla koşul tek bir grubu tetikleyebilir. Aksiyon ve mesaj davranışı grup seviyesinde yönetilir.

KolonTipNot
idbigint PK
device_idvarchar(21)0 global
namevarchar(100)
descriptionvarchar(255)
statusbooleangrup aktif/pasif
multi_triggerbooleanfalse=edge, true=level
notify_on_resetbooleannormale dönünce event/mesaj
trigger_countbiginttoplam tetik sayacı
trigger_action_plan_idbiginttrigger aksiyon planı
reset_action_plan_idbigintreset aksiyon planı
trigger_message_idbiginttrigger mesaj şablonu
reset_message_idbigintreset mesaj şablonu
publish_bitsmallintpublish gate biti (99=always publish)
cooldown_secintegertekrar tetik engeli
priorityintegerdüşük sayı daha öncelikli
valid_from, valid_totimestamptzaktiflik penceresi
rule_versioninteger
rule_hashvarchar(64)
last_statevarchar(16)normal/triggered
last_changed_attimestamptzson state geçişi
created_at, updated_attimestamptz

rules

Grup altındaki atomik koşul kayıtları.

KolonTipNot
idbigint PK
group_idbigint FKrule_groups.id
variable_idvarchar(30)ölçülen alan
source_scopevarchar(16)raw/synth/window/status
condition_typevarchar(16)threshold/bit_set/bit_change/range/trend
operatorvarchar(8)>,<,>=,<=,=,!=
valuedouble precisioneşik
duration_secintegerkoşulun sağlanma süresi
logicvarchar(4)AND/OR
bit_indexsmallintstatus bit koşulları için
bit_expectedbooleanstatus bit beklenen değer
window_typevarchar(16)window kuralları için
old_register_valuebigintedge/pulse kontrolü
new_register_valuebigintedge/pulse kontrolü
statusbooleankural aktif/pasif
created_at, updated_attimestamptz

action_plans

KolonTipNot
idbigint PK
namevarchar(100)plan adı
statusbooleanaktif/pasif
dedup_scopevarchar(32)device/group/global
cooldown_secintegerplan seviyesinde cooldown
created_at, updated_attimestamptz

Not: Plan adımlarının gerçek hedefe çözülmesi Action Executor tarafında recipient_profiles/recipient_channels/action_routes tabloları üzerinden yapılır (bkz: /projects/cinga/backend/architecture/action-executor).

action_plan_steps

KolonTipNot
idbigint PK
plan_idbigint FKaction_plans.id
step_orderintegerçalıştırma sırası
channel_typevarchar(32)whatsapp/email/push/webhook/audit
template_idbigintmesaj şablonu
config_jsonjsonbkanal ayarı / hedef
retry_policy_jsonjsonbretry/backoff
enabledbooleanaktif/pasif
created_at, updated_attimestamptz

message_templates

KolonTipNot
idbigint PK
channel_typevarchar(32)
namevarchar(100)
subject_tpltexte-posta/başlık için
body_tpltextrender şablonu
localevarchar(8)tr/en
created_at, updated_attimestamptz

Locked Group Semantics (V1)

multi_trigger davranışı

  • multi_trigger = false (edge mode)
    • Grup normal -> triggered geçişinde bir kez trigger event üretir.
    • Grup triggered -> normal geçişinde (ve notify_on_reset=true) reset event üretir.
  • multi_trigger = true (level mode)
    • Koşul true olduğu her değerlendirmede trigger event üretilebilir.
    • cooldown_sec zorunlu uygulanır.

notify_on_reset davranışı

  • true: koşul düzelince reset event/mesaj üret.
  • false: reset sessiz geçsin, yalnız state güncellensin.

publish_bit davranışı

  • publish_bit = 99 -> her durumda mesaj publish edilir.
  • Diğer değerler için PUBLISH_STATUS register bit map'ine göre bit kontrolü yapılır.
  • PUBLISH_STATUS alanı status register sözlüğünün publish bölümüyle aynı bit sıralamasını kullanır.
  • Bit mapping kaynağı: /projects/cinga/backend/architecture/status-register.
  • Bit kapalıysa:
    • aksiyon audit/log yine çalışabilir,
    • dış mesaj publish edilmez.

Fault / Pulse / Status yorumu

  • Status fault bitleri (STATUS_FAULT_*) level mantığıyla değerlendirilir (düzelene kadar true).
  • P_RISE, P_DROP pulse/event mantığıyla değerlendirilir.
  • status_pump fiziksel çalışma feedback'i olarak yorumlanır.

Group State Machine

Publish Gate Akışı

Dinamik Mesaj İçeriği (Template Render)

Kural tetiklenince gönderilecek mesajlar template üzerinden render edilir.

Örnek template:

  • Basınç limiti {{limit_bar}} bar, anlık {{current_bar}} bar ({{delta_bar}} bar aşım).

Önerilen render context:

  • device_id
  • rule_name
  • metric
  • current_value
  • limit_value
  • delta
  • unit
  • timestamp

Örnek render sonucu:

  • Basınç limiti 3.0 bar, anlık 4.5 bar (1.5 bar aşım).

Action Orchestration Akışı

Not: Rule Servisi step'leri doğrudan çalıştırmaz; yalnız action.execute.requested.v1 üretir. Kanal bazlı yürütme ayrı Action Executor katmanında yapılır.

Action Sonucu Geri Besleme Politikası

Rule Servisi action.executed.v1 ve action.failed.v1 eventlerini izleyerek grup state ve escalation kararlarını günceller.

  • action.executed.v1 -> ilgili step tamamlandı olarak işaretlenir.
  • action.failed.v1 -> retry/dead-letter durumuna göre escalation akışı değerlendirilir.
  • Aynı evaluation_key + step_order için idempotent sonuç işlenir.

Execution Boundary Contract (Rule vs Executor vs Communication)

Sorumluluk sınırı kesin kural:

  • Rule Servisi: yalnız karar verir ve action.execute.requested.v1 üretir.
  • Action Executor: kanal/adım yürütmesini yapar (push/email/whatsapp/webhook/audit).
  • Communication: sadece cihaza downlink komut iletimini yürütür.

Rule Servisi hiçbir kanala doğrudan mesaj göndermez ve cihaza doğrudan komut basmaz.

Topic ve Event Standardı

  • Topic:
    • cinga.rule.evaluated
    • cinga.rule.triggered
    • cinga.action.requested
    • cinga.rule.failed
  • Event:
    • rule.evaluated.v1
    • rule.triggered.v1
    • action.execute.requested.v1
    • rule.failed.v1

Event Örnekleri

rule.triggered.v1

{
"event": "rule.triggered.v1",
"meta": {
"schema_version": 1,
"trace_id": "rule-9f3f...",
"producer_service": "rule-service",
"produced_at": "2026-03-12T20:30:21.120Z",
"process_ms": 15
},
"context": {
"device_id": "400000011D081B70",
"stream_id": 9823412
},
"data": {
"group_id": 12,
"rule_id": 114,
"event_type": "trigger",
"rule_hash": "a8be...",
"source_event": "window.ready.v1",
"trigger_reason": "P95_RTT_HIGH",
"severity": "high",
"trigger_count": 57,
"actions": ["ALERT_CREATE", "AUDIT_ONLY"]
},
"error": null
}

rule.triggered.v1 (reset örneği)

{
"event": "rule.triggered.v1",
"meta": {
"schema_version": 1,
"trace_id": "rule-9f3f...",
"producer_service": "rule-service",
"produced_at": "2026-03-12T20:40:21.120Z",
"process_ms": 12
},
"context": {
"device_id": "400000011D081B70",
"stream_id": 9823519
},
"data": {
"group_id": 12,
"rule_id": 114,
"event_type": "reset",
"rule_hash": "a8be...",
"source_event": "window.ready.v1",
"trigger_reason": "P_HIGH_NORMALIZED",
"severity": "info",
"trigger_count": 58,
"actions": ["AUDIT_ONLY"]
},
"error": null
}

action.execute.requested.v1

{
"event": "action.execute.requested.v1",
"meta": {
"schema_version": 1,
"trace_id": "rule-9f3f...",
"producer_service": "rule-service",
"produced_at": "2026-03-12T20:30:21.135Z",
"process_ms": 15
},
"context": {
"device_id": "400000011D081B70",
"stream_id": 9823412
},
"data": {
"group_id": 12,
"rule_id": 114,
"action_plan_id": 21,
"step_order": 1,
"action_type": "ALERT_CREATE",
"channel_type": "whatsapp",
"payload": {
"title": "High pressure trend",
"metric": "P_HIGH",
"current_bar": 4.5,
"limit_bar": 3.0,
"delta_bar": 1.5,
"severity": "high",
"message": "Basınç limiti 3.0 bar, anlık 4.5 bar (1.5 bar aşım)."
}
},
"error": null
}

rule.failed.v1

{
"event": "rule.failed.v1",
"meta": {
"schema_version": 1,
"trace_id": "rule-9f3f...",
"producer_service": "rule-service",
"produced_at": "2026-03-12T20:30:21.180Z",
"process_ms": 15
},
"context": {
"device_id": "400000011D081B70",
"stream_id": 9823412
},
"data": null,
"error": {
"failed_stage": "rule_evaluation",
"error_code": "RULE_CONDITION_INVALID",
"error_message": "unknown variable: P95_X",
"retryable": false,
"failed_at": "2026-03-12T20:30:21Z"
}
}

Operasyon Notları

  • Kural değerlendirme idempotent olmalıdır (event_id + group_id + rule_id).
  • evaluation_key önerisi: sha1(event_id|group_id|rule_id|event_type).
  • Cooldown mekanizması zorunludur (alarm fırtınasını önlemek için).
  • Cooldown öncelik sırası: group.cooldown_sec -> action_plan.cooldown_sec.
  • Group içinde AND/OR precedence soldan-sağa değerlendirilir; kısa devre (short-circuit) uygulanır.
  • Rule değişikliklerinde cache invalidation zorunludur.
  • Dry-run modu desteklenmelidir (aksiyon üretmeden sadece evaluate).
  • event_type alanı trigger veya reset olarak standartlaştırılmalıdır.

Örnek Kural Setleri (V1)

1) Yüksek Gerilim Alarmı

  • Group: VOLTAGE_HIGH_ALERT
  • Scope: raw
  • Koşul: VRMS_R > 250 OR VRMS_S > 250 OR VRMS_T > 250
  • multi_trigger=false, notify_on_reset=true
  • Trigger aksiyon planı: WhatsApp + Push + Audit
  • Reset aksiyon planı: Push + Audit

2) Pompa Çalışırken Akım Dengesizliği Yüksek

  • Group: PUMP_ON_IIMB_HIGH
  • Scope: synth + status
  • Koşul:
    • status_pump == true
    • i_imb > 20
    • duration_sec >= 30
  • multi_trigger=true, cooldown_sec=300
  • Trigger aksiyon planı: WhatsApp + Email + Audit
  • Reset aksiyon planı: Audit (opsiyonel notify)

3) MP/TH Fault Kritik Alarmı

  • Group: MOTOR_PROTECTION_FAULT
  • Scope: status
  • Koşul: STATUS_FAULT_MP == 1 OR STATUS_FAULT_TH == 1
  • multi_trigger=false, notify_on_reset=true
  • Trigger aksiyon planı: WhatsApp + Email + Webhook + Audit
  • Reset aksiyon planı: WhatsApp (resolved) + Audit

Servis Bazlı SLO Hedefleri (Öneri)

MetrikHedef
p95 rule_evaluation_ms< 200ms
rule evaluation success rate> 99.5%
duplicate trigger rate< 0.1%
cooldown violation0

Çıktı

Rule Servisi çıktısı:

  • Kural değerlendirme kayıtları
  • Tetiklenen aksiyon eventleri
  • Hata durumunda rule-failed görünürlüğü