Sentez Servisi
Topoloji referansı: /projects/cinga/backend#sistem-işleyiş-akışı
Sentez Servisi, raw.persisted.v1 eventini tüketip ham + kalibre edilmiş ölçüm setinden türetilmiş metrikleri üreten mikroservistir.
Bu servis ham segment yazımı yapmaz. Kural motorunu çalıştırır, sentez çıktısını energy_synth_results tablosuna yazar ve bir sonraki katmanı tetikler.
Sorumluluk
raw.persisted.v1eventini consume etmek- Redis
device_buffer:{device_id}içinden gerekli anlık seti okumak - Redis/DB üzerinden synthesis rule snapshot çözmek
- Kural önceliğine göre sentez metriklerini hesaplamak
- Sonuçları
energy_synth_resultstablosuna idempotent upsert etmek - Başarıda
synth.ready.v1, hatadasynth.failed.v1üretmek
İşlem Akışı
Girdi Kaynakları
Sentez servisi girdi setini iki kaynaktan çözer:
- Redis (
device_buffer)assembly.payload_merged(kalibre edilmiş güncel set)raw_buffer(gerekli kısa geçmiş)
- DB fallback
energy_*_measurementstabloları
Alan çözümleme sırası (deterministic):
assembly.payload_merged- Eksik kalan alanlar için
raw_buffer - Hâlâ eksikse DB fallback (
energy_*_measurements)
Not: Redis miss veya eksik alan durumunda DB fallback zorunludur.
Kural Çözümleme
Kural kaynağı:
- Redis cihaz kuralı:
synth_rules:{device_id}:latest - Redis global kuralı:
synth_rules:0:latest - Cache miss -> DB (
synthesis_variable_rules) + write-back
Öncelik:
- Cihaz özel kural
- Global kural
- Kural yoksa değişken pas geç
Çalıştırma sırası:
priority ASC- eşitlikte
id DESC(id büyük olan en son)
Sentez Persist Tablosu
Sentez çıktıları energy_synth_results tablosuna yazılır.
Ortak Kolonlar
| Kolon | Tip | Not |
|---|---|---|
id | bigint PK | |
stream_id | bigint FK UNIQUE | streams.id |
device_id | varchar(21) | |
device_time | timestamptz | |
stream_time | timestamptz | |
calc_version | integer | |
rule_hash | varchar(64) | |
quality_flags | jsonb | skip/hata/warning |
created_at, updated_at | timestamptz |
V1 Sentez Kolonları (28)
| Kolon | Tip | Not |
|---|---|---|
vrms_a | double precision | Faz RMS gerilim ortalaması |
v_eq | double precision | Eşdeğer RMS gerilim |
vrms_max | double precision | Faz RMS gerilim maksimumu |
vrms_min | double precision | Faz RMS gerilim minimumu |
v_imb | double precision | Gerilim dengesizlik oranı (%) |
v_sr | double precision | Faz gerilim yayılım oranı (%) |
irms_a | double precision | Faz RMS akım ortalaması |
i_eq | double precision | Eşdeğer RMS akım |
irms_max | double precision | Faz RMS akım maksimumu |
irms_min | double precision | Faz RMS akım minimumu |
ipeak_max | double precision | Faz tepe akım maksimumu |
i_imb | double precision | Akım dengesizlik oranı (%) |
ipeak_ratio | double precision | Tepe/RMS oranı |
vharm_ratio | double precision | Gerilim harmonik oranı (%) |
iharm_ratio | double precision | Akım harmonik oranı (%) |
pf_calc | double precision | Hesaplanmış güç faktörü |
q_ratio | double precision | Reaktif güç oranı |
pharm_ratio | double precision | Harmonik aktif güç oranı (%) |
qharm_ratio | double precision | Harmonik reaktif güç oranı (%) |
s_calc | double precision | Hesaplanmış görünür güç |
p_unb_pct | double precision | Aktif güç dengesizliği (%) |
q_unb_pct | double precision | Reaktif güç dengesizliği (%) |
s_unb_pct | double precision | Görünür güç dengesizliği (%) |
f_dev | double precision | Frekans sapması |
thd_v_eq | double precision | Eşdeğer gerilim THD |
thd_i_eq | double precision | Eşdeğer akım THD |
q_mode | varchar(16) | LEAD/LAG/NEUTRAL |
energy_dir | varchar(16) | IMPORT/EXPORT/IDLE |
V1 Sentez Değişken Açıklamaları ve Formüller
Aşağıdaki formüller V1 referans hesap tanımıdır. Üretimde gerçek hesaplar synthesis_variable_rules içindeki aktif kural snapshot'ından çalıştırılır; burada verilen ifadeler dokümantasyon standardı içindir.
İsim standardı ve kısaltmalar:
- Ingest/stream canonical isimleri korunur:
VRMS_R,IRMS_R,P_R,Q_R,S_R,FREQ(uppercase snake_case). - DB kolonları snake_case yazılır (
vrms_a,i_eqgibi). V_R/S/T = VRMS_R/VRMS_S/VRMS_TI_R/S/T = IRMS_R/IRMS_S/IRMS_TP_R/S/T,Q_R/S/T,S_R/S/Tfaz güçleriP_TOT=P_R+P_S+P_T,Q_TOT=Q_R+Q_S+Q_T,S_TOT=S_R+S_S+S_TAVG(x,y,z) = (x+y+z)/3MAX3(x,y,z)veMIN3(x,y,z)üçlü max/minEPS = 1e-9(sıfıra bölmeyi engellemek için)
| Değişken | Açıklama | Referans Formül (V1) |
|---|---|---|
VRMS_A | Faz RMS gerilim ortalaması | AVG(V_R, V_S, V_T) |
V_EQ | Eşdeğer RMS gerilim | sqrt((V_R^2 + V_S^2 + V_T^2) / 3) |
VRMS_MAX | Faz RMS gerilim maksimumu | MAX3(V_R, V_S, V_T) |
VRMS_MIN | Faz RMS gerilim minimumu | MIN3(V_R, V_S, V_T) |
V_IMB | Gerilim dengesizlik oranı (%) | 100 * MAX(abs(V_R-VRMS_A), abs(V_S-VRMS_A), abs(V_T-VRMS_A)) / max(VRMS_A, EPS) |
V_SR | Gerilim yayılım oranı (%) | 100 * (VRMS_MAX - VRMS_MIN) / max(VRMS_A, EPS) |
IRMS_A | Faz RMS akım ortalaması | AVG(I_R, I_S, I_T) |
I_EQ | Eşdeğer RMS akım | sqrt((I_R^2 + I_S^2 + I_T^2) / 3) |
IRMS_MAX | Faz RMS akım maksimumu | MAX3(I_R, I_S, I_T) |
IRMS_MIN | Faz RMS akım minimumu | MIN3(I_R, I_S, I_T) |
IPEAK_MAX | Faz tepe akım maksimumu | MAX3(IPEAK_R, IPEAK_S, IPEAK_T) |
I_IMB | Akım dengesizlik oranı (%) | 100 * MAX(abs(I_R-IRMS_A), abs(I_S-IRMS_A), abs(I_T-IRMS_A)) / max(IRMS_A, EPS) |
IPEAK_RATIO | Tepe/RMS oranı | IPEAK_MAX / max(IRMS_MAX, EPS) |
VHARM_RATIO | Gerilim harmonik oranı (%) | 100 * AVG(VHARM_R, VHARM_S, VHARM_T) / max(VRMS_A, EPS) |
IHARM_RATIO | Akım harmonik oranı (%) | 100 * AVG(IHARM_R, IHARM_S, IHARM_T) / max(IRMS_A, EPS) |
PF_CALC | Hesaplanmış güç faktörü | P_TOT / max(S_TOT, EPS) |
Q_RATIO | Reaktif güç oranı | abs(Q_TOT) / max(abs(P_TOT), EPS) |
PHARM_RATIO | Harmonik aktif güç oranı (%) | 100 * PHARM_TOT / max(abs(P_TOT), EPS) |
QHARM_RATIO | Harmonik reaktif güç oranı (%) | 100 * QHARM_TOT / max(abs(Q_TOT), EPS) |
S_CALC | Hesaplanmış görünür güç | sqrt(P_TOT^2 + Q_TOT^2) |
P_UNB_PCT | Aktif güç dengesizliği (%) | 100 * (MAX3(P_R,P_S,P_T)-MIN3(P_R,P_S,P_T)) / max(abs(P_TOT)/3, EPS) |
Q_UNB_PCT | Reaktif güç dengesizliği (%) | 100 * (MAX3(Q_R,Q_S,Q_T)-MIN3(Q_R,Q_S,Q_T)) / max(abs(Q_TOT)/3, EPS) |
S_UNB_PCT | Görünür güç dengesizliği (%) | 100 * (MAX3(S_R,S_S,S_T)-MIN3(S_R,S_S,S_T)) / max(abs(S_TOT)/3, EPS) |
F_DEV | Frekans sapması | FREQ - F_NOM; V1 varsayılan F_NOM=50.0 Hz |
THD_V_EQ | Eşdeğer gerilim THD (%) | 100 * sqrt(sum_h(V_h^2)) / max(VFUND_EQ, EPS) |
THD_I_EQ | Eşdeğer akım THD (%) | 100 * sqrt(sum_h(I_h^2)) / max(IFUND_EQ, EPS) |
Q_MODE | Reaktif güç yön modu | Q_TOT > +Q_TH => LEAD, Q_TOT < -Q_TH => LAG, aksi NEUTRAL |
ENERGY_DIR | Enerji akış yönü | PE_TOT_DELTA > +E_TH => IMPORT, < -E_TH => EXPORT, aksi IDLE |
Notlar:
THD_*hesaplarında harmonik seti cihazın gönderdiği banda bağlıdır (V1: 3/5/7; varsa genişletilir).VFUND_EQveIFUND_EQ, faz temel bileşenlerinin RMS eşdeğeridir (sqrt((X_R^2+X_S^2+X_T^2)/3)).Q_THveE_THeşikleri rule setinden okunur; default sabitler yalnız fallback içindir.- Formula değişikliği veya eşik güncellemesi
rule_hashdeğişimiyle izlenmelidir.
Yazım Kuralları
- Yazım anahtarı
stream_id'dir. - Aynı
stream_idtekrar işlenirse idempotent upsert uygulanır. - Rule hesaplaması sırasında bir değişken üretilemezse ilgili alan
NULLbırakılabilir; bu durumquality_flagsiçinde işaretlenir. - Persist aşamasında transaction modeli single-row atomic upsert olarak çalışır.
- Önerilen isolation:
READ COMMITTED+ idempotent upsert (yüksek throughput için dengeli varsayılan).
Yazım Sonrası Akış
DB yazımı tamamlandıktan sonra servis:
- Single-writer prensibi uygulanır:
- Varsayılan mimaride Sentez Servisi Redis state'i doğrudan mutate etmez.
- Bunun yerine
synth.state.patch.v1benzeri bir state patch eventi üretir. - State Writer bu patch'i
device_buffer:{device_id}üstüne atomik uygular. - Tek servis modunda (embedded single-writer) aynı süreç içinde doğrudan update yapılabilir.
- Başarılıysa
synth.ready.v1üretir. - Downstream window katmanını tetikler.
Başarısızlıkta:
- Redis'e hata meta bilgisi işlenir (
last_synth_error). synth.failed.v1üretilir.- Hata kodu log + DLQ akışına taşınır.
- Tekrar işleme idempotent olarak
stream_idüstünden yapılır.
Not: Window Servisi, yalnız başarılı sentez yazımı olan stream setlerini işlemeye almalıdır.
Topic ve Event Standardı
Bu sayfada kullanılan standart:
- Kafka topic:
cinga.synth.ready,cinga.synth.failed - Event adı:
synth.ready.v1,synth.failed.v1
Not: Topic adı taşıma kanalıdır, event adı payload sözleşmesidir. Doküman genelinde bu ikisi karıştırılmamalıdır.
Event Sözleşmeleri
synth.ready.v1
{
"event": "synth.ready.v1",
"meta": {
"schema_version": 1,
"trace_id": "9f3f...",
"producer_service": "synth-service",
"produced_at": "2026-03-11T15:22:10.160Z",
"process_ms": 18
},
"context": {
"device_id": "400000011D081B70",
"stream_id": 9823412,
"device_time": "2026-03-11T15:22:06Z",
"stream_time": "2026-03-11T15:22:10Z"
},
"data": {
"rule_hash": "7b6f...",
"calc_version": 1,
"quality_flags": {
"skipped_rules": [
"THD_I_EQ"
]
}
},
"error": null
}
synth.failed.v1
{
"event": "synth.failed.v1",
"meta": {
"schema_version": 1,
"trace_id": "9f3f...",
"producer_service": "synth-service",
"produced_at": "2026-03-11T15:22:12.020Z",
"process_ms": 18
},
"context": {
"device_id": "400000011D081B70",
"stream_id": 9823412
},
"error": {
"failed_stage": "synthesis",
"error_code": "SYNTH_DB_WRITE_FAIL",
"error_message": "energy_synth_results upsert failed",
"retryable": true,
"failed_at": "2026-03-11T15:22:12Z"
}
}
retryable karar matrisi:
SYNTH_DB_WRITE_FAIL: true (geçici DB hatası olabilir)SYNTH_CALC_TRANSIENT: true (geçici state/bağımlılık eksikliği)SYNTH_CALC_DETERMINISTIC_FAIL: false (aynı input+rule ile tekrar hep başarısız)SYNTH_INPUT_MISSING: falseSYNTH_RULE_INVALID: falseSYNTH_RULE_MISS: false
Hata Kodları
SYNTH_RULE_MISSSYNTH_RULE_INVALIDSYNTH_INPUT_MISSINGSYNTH_DB_WRITE_FAILSYNTH_CALC_TRANSIENTSYNTH_CALC_DETERMINISTIC_FAIL
Index
UNIQUE(stream_id)(device_id, device_time DESC)(device_id, stream_time DESC)
Çıktı
Sentez Servisinin çıktısı:
energy_synth_resultstablosunda kalıcı sentez verisi- Redis'te
synth_buffergüncellemesi - Kafka'da
synth.ready.v1(veya hata durumundasynth.failed.v1)
Window Servisi synth.ready.v1 eventini tüketerek pencere hesaplarını başlatır.