SLA Policy Evaluator System Behavior (Implemented)
Dokumen ini menjelaskan behavior runtime SLA Policy Evaluator yang sudah berjalan saat ini.
Komponen utama:
apps/worker-workflow/src/sla-policy-evaluator/services/cdc-forwarder/sla-cdc-forwarder.consumer.tsapps/worker-workflow/src/sla-policy-evaluator/services/transition/sla-transition-check.service.tsapps/worker-workflow/src/sla-policy-evaluator/services/transition/sla-aging.service.tsapps/worker-workflow/src/sla-policy-evaluator/services/schedule/sla-schedule.consumer.tsapps/worker-workflow/src/sla-policy-evaluator/utils/sla-checker.utils.ts
1. Source of Truth dan Kontrak Event
Sumber event SLA:
- Hanya dari CDC
wxl_submission_log. - Hanya memproses operasi CDC insert (
op='c') untuk menjaga append-only semantics.
Payload transition yang dikirim ke checker:
submission_idaction_idfrom_status_idto_status_idactor_user_idchanged_atsource_table = wxl_submission_logsubmission_log_id(untuk dedupe; alias kompatibilitas:source_log_id)source_lsn(metadata CDC)submission_hint(snapshot ringan untuk troubleshooting)
Catatan:
- Forwarder publish ke topic
workflow.sla.check.on_transition.*(instant) jikachanged_at <= now. - Forwarder publish ke topic
workflow.sla.schedule.*jikachanged_at > now, lalu dijalankan scheduler. - Checker tetap membaca
wxl_submissionterbaru denganpessimistic_write. submission_hinttidak dijadikan state final, hanya hint observability.
2. Flow Transition (Start/Resolve SLA)
Saat event transition diterima:
- Checker buka transaksi.
- Checker lock row
wxl_submission. - Checker resolve policy dari tabel live
wml_sla_policy(authoritative), lalu fallback keworkflow_snapshot.slaPoliciesjika live policy kosong. - Untuk tiap policy, checker jalankan guard idempotency.
- Checker tentukan apakah policy harus
RESOLVE. - Jika tidak resolve, checker evaluasi apakah policy harus
START.
Behavior resolve:
- Jika
event.to_status_idsudah di statusresolve_status_idatau lebih maju (wml_status.order >= resolve order), instance open yangis_resolveable=truedi-markRESOLVED. - Log
wxl_sla_logbertipeRESOLVEDditambahkan.
Behavior start:
- Scope
STATUS: start ketikaevent.to_status_id == policy.start_status_id. - Scope
ACTION: wajib event dari submission log dan wajib adaaction_id. condition_policydiperlakukan sebagai aturan kepatuhan.- Jika aturan tidak terpenuhi (
condition_policy = false) saat trigger start:- SLA instance tetap dicatat untuk jejak audit,
- instance langsung ditandai
BREACHED(tanpa menunggu due), - outcome policy dijalankan.
- Jika aturan terpenuhi, instance
RUNNINGdibuat dan due schedule dipublish.
3. Flow Aging Check (Breach vs Resolve)
Saat due event diproses:
- Checker lock
wxl_sla_instance. - Skip jika instance sudah
RESOLVEDatauBREACHED. - Jika
due_atbelum lewat, instance di-reschedule. - Jika due sudah lewat, checker tentukan apakah harus resolve atau breach.
Resolve guard saat due:
- Guard A: jika
submission.current_status_idsaat ini sudahresolve_status_idatau lebih maju (status.order >= resolve order), instanceRESOLVED. - Guard B: jika current status belum memenuhi Guard A, checker cari histori
wxl_submission_logsejakinstance.started_at(ataudate_created). - Jika pernah ada transisi
to_status_idyang order-nya >= resolve order, instance tetapRESOLVED(tidakBREACHED).
Catatan is_resolveable:
- Nilai
wxl_sla_instance.is_resolveablediset saat start instance. - Jika
resolve_status_idpolicy kosong, instance dibuat denganis_resolveable=false. - Instance
is_resolveable=falsetidak akan masuk jalur auto-resolve.
Jika kedua guard tidak terpenuhi:
- Instance di-mark
BREACHED. - Log
wxl_sla_logbertipeBREACHEDditambahkan. - Outcome policy dijalankan.
4. Behavior Condition Policy
Condition policy diproses sebagai SQL terparameter dengan konteks JSON.
Semantik: true = patuh, false = melanggar.
Jika submission.entity dan submission.entity_id tersedia, checker menjalankan query ke tabel entity sumber:
FROM <submission.entity> entity_rowWHERE entity_row.id::text = <submission.entity_id>- Row entity diinjeksi ke context sebagai key
entity(jsonb_set(..., '{entity}', to_jsonb(entity_row), true)).
Didukung:
- Group nested:
AND,OR,NOT. - Tipe rule:
string,number,boolean,date,datetime. - Operator umum:
eq,neq,in,not_in,contains,between,gt,gte,lt,lte,empty,not_empty. - Alias operator Directus juga diterima, contoh:
_eq,_neq,_icontains,_null,_nnull,_in,_nin.
Catatan field:
- Field tanpa dot (contoh
name,flag_id) otomatis diprefix menjadientity.<field>. - Field yang sudah berprefix (
event.*,submission.*,policy.*, dst) tetap dipakai apa adanya.
Semantik:
- Hasil akhir harus boolean (
matchedtrue/false). - Jika
condition_policykosong/null, defaultmatched = true. - Modifier runtime juga didukung:
{"exclude_weekend": true}untuk skip Sabtu/Minggu pada kalkulasi due.{"business_hours_only": true}sebagai fallback aktivasi business-hours jikais_use_business_hoursbelum diisi.
5. Native Business Hours / Weekend
Jika policy is_use_business_hours = true:
- Due tidak dihitung 24/7, tetapi hanya di window UTC:
business_start_utcbusiness_end_utc
- Hari kerja dapat diatur dengan
working_days(contoh[1,2,3,4,5]untuk Senin-Jumat). - Default window jika null/invalid:
09:00:00sampai17:00:00(UTC). - Jika
is_exclude_weekend = true, Sabtu/Minggu tidak dihitung ke SLA timer. condition_policy.exclude_weekendmasih didukung sebagai fallback kompatibilitas.
Contoh konfigurasi:
- Kolom policy:
is_use_business_hours = trueis_exclude_weekend = trueworking_days = [1,2,3,4,5]business_start_utc = '08:00:00'business_end_utc = '17:00:00'
- JSON condition:
{ "exclude_weekend": true }
6. Idempotency dan Concurrency Guard
Guard yang aktif:
- Dedupe event by
submission_log_idpersubmission + policy. - No double start jika masih ada instance open pada policy yang sama.
- Stale event guard: event lama diabaikan jika
event.changed_atlebih tua dari update instance terakhir. - Seluruh operasi kritikal berjalan dalam transaksi DB.
7. Outcome Policy Behavior
Saat breach, outcome policy yang berjalan:
setStatusTo: mengubahwxl_sla_instance.sla_status(nilai valid:OK,BREACHED,PAUSED, dan aliasBREACH -> BREACHED).publishSubject: publish eventSLA_BREACHEDvia JetStream, fallback ke core NATS jika publish gagal.
Catatan:
- Outcome policy tidak mengubah
wxl_submission.current_status_id.
8. Failure Handling
Forwarder/Scheduler/Checker behavior:
- Payload invalid: di-drop +
ack. - Error proses:
nakagar bisa redelivery. - Scheduler melakukan delay dengan mekanisme
nak(delay)sampaicheck_at.
9. Timeline Example (Kasus “Status Sudah Lewat”)
Contoh:
t0: logA -> B(policy start diB) => SLARUNNING.t+30m: logB -> C(policy resolve diC).t+45m: logC -> D.t+60m: aging dieksekusi.
Hasil:
- Walau current status sudah
D, checker tetap menemukan historito_status_id = Csetelah start. - Instance ditandai
RESOLVED, bukanBREACHED.
10. Batasan Saat Ini
- Dedupe kuat jika
submission_log_idtersedia di event. - Behavior cross-workflow SLA agregasi kompleks belum jadi native flow khusus.