Skip to main content

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.v1 eventini 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_results tablosuna idempotent upsert etmek
  • Başarıda synth.ready.v1, hatada synth.failed.v1 üretmek

İşlem Akışı

Girdi Kaynakları

Sentez servisi girdi setini iki kaynaktan çözer:

  1. Redis (device_buffer)
    • assembly.payload_merged (kalibre edilmiş güncel set)
    • raw_buffer (gerekli kısa geçmiş)
  2. DB fallback
    • energy_*_measurements tabloları

Alan çözümleme sırası (deterministic):

  1. assembly.payload_merged
  2. Eksik kalan alanlar için raw_buffer
  3. 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:

  1. Cihaz özel kural
  2. Global kural
  3. 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

KolonTipNot
idbigint PK
stream_idbigint FK UNIQUEstreams.id
device_idvarchar(21)
device_timetimestamptz
stream_timetimestamptz
calc_versioninteger
rule_hashvarchar(64)
quality_flagsjsonbskip/hata/warning
created_at, updated_attimestamptz

V1 Sentez Kolonları (28)

KolonTipNot
vrms_adouble precisionFaz RMS gerilim ortalaması
v_eqdouble precisionEşdeğer RMS gerilim
vrms_maxdouble precisionFaz RMS gerilim maksimumu
vrms_mindouble precisionFaz RMS gerilim minimumu
v_imbdouble precisionGerilim dengesizlik oranı (%)
v_srdouble precisionFaz gerilim yayılım oranı (%)
irms_adouble precisionFaz RMS akım ortalaması
i_eqdouble precisionEşdeğer RMS akım
irms_maxdouble precisionFaz RMS akım maksimumu
irms_mindouble precisionFaz RMS akım minimumu
ipeak_maxdouble precisionFaz tepe akım maksimumu
i_imbdouble precisionAkım dengesizlik oranı (%)
ipeak_ratiodouble precisionTepe/RMS oranı
vharm_ratiodouble precisionGerilim harmonik oranı (%)
iharm_ratiodouble precisionAkım harmonik oranı (%)
pf_calcdouble precisionHesaplanmış güç faktörü
q_ratiodouble precisionReaktif güç oranı
pharm_ratiodouble precisionHarmonik aktif güç oranı (%)
qharm_ratiodouble precisionHarmonik reaktif güç oranı (%)
s_calcdouble precisionHesaplanmış görünür güç
p_unb_pctdouble precisionAktif güç dengesizliği (%)
q_unb_pctdouble precisionReaktif güç dengesizliği (%)
s_unb_pctdouble precisionGörünür güç dengesizliği (%)
f_devdouble precisionFrekans sapması
thd_v_eqdouble precisionEşdeğer gerilim THD
thd_i_eqdouble precisionEşdeğer akım THD
q_modevarchar(16)LEAD/LAG/NEUTRAL
energy_dirvarchar(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_eq gibi).
  • V_R/S/T = VRMS_R/VRMS_S/VRMS_T
  • I_R/S/T = IRMS_R/IRMS_S/IRMS_T
  • P_R/S/T, Q_R/S/T, S_R/S/T faz güçleri
  • P_TOT=P_R+P_S+P_T, Q_TOT=Q_R+Q_S+Q_T, S_TOT=S_R+S_S+S_T
  • AVG(x,y,z) = (x+y+z)/3
  • MAX3(x,y,z) ve MIN3(x,y,z) üçlü max/min
  • EPS = 1e-9 (sıfıra bölmeyi engellemek için)
DeğişkenAçıklamaReferans Formül (V1)
VRMS_AFaz RMS gerilim ortalamasıAVG(V_R, V_S, V_T)
V_EQEşdeğer RMS gerilimsqrt((V_R^2 + V_S^2 + V_T^2) / 3)
VRMS_MAXFaz RMS gerilim maksimumuMAX3(V_R, V_S, V_T)
VRMS_MINFaz RMS gerilim minimumuMIN3(V_R, V_S, V_T)
V_IMBGerilim dengesizlik oranı (%)100 * MAX(abs(V_R-VRMS_A), abs(V_S-VRMS_A), abs(V_T-VRMS_A)) / max(VRMS_A, EPS)
V_SRGerilim yayılım oranı (%)100 * (VRMS_MAX - VRMS_MIN) / max(VRMS_A, EPS)
IRMS_AFaz RMS akım ortalamasıAVG(I_R, I_S, I_T)
I_EQEşdeğer RMS akımsqrt((I_R^2 + I_S^2 + I_T^2) / 3)
IRMS_MAXFaz RMS akım maksimumuMAX3(I_R, I_S, I_T)
IRMS_MINFaz RMS akım minimumuMIN3(I_R, I_S, I_T)
IPEAK_MAXFaz tepe akım maksimumuMAX3(IPEAK_R, IPEAK_S, IPEAK_T)
I_IMBAkı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_RATIOTepe/RMS oranıIPEAK_MAX / max(IRMS_MAX, EPS)
VHARM_RATIOGerilim harmonik oranı (%)100 * AVG(VHARM_R, VHARM_S, VHARM_T) / max(VRMS_A, EPS)
IHARM_RATIOAkım harmonik oranı (%)100 * AVG(IHARM_R, IHARM_S, IHARM_T) / max(IRMS_A, EPS)
PF_CALCHesaplanmış güç faktörüP_TOT / max(S_TOT, EPS)
Q_RATIOReaktif güç oranıabs(Q_TOT) / max(abs(P_TOT), EPS)
PHARM_RATIOHarmonik aktif güç oranı (%)100 * PHARM_TOT / max(abs(P_TOT), EPS)
QHARM_RATIOHarmonik reaktif güç oranı (%)100 * QHARM_TOT / max(abs(Q_TOT), EPS)
S_CALCHesaplanmış görünür güçsqrt(P_TOT^2 + Q_TOT^2)
P_UNB_PCTAktif 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_PCTReaktif 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_PCTGö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_DEVFrekans sapmasıFREQ - F_NOM; V1 varsayılan F_NOM=50.0 Hz
THD_V_EQEşdeğer gerilim THD (%)100 * sqrt(sum_h(V_h^2)) / max(VFUND_EQ, EPS)
THD_I_EQEşdeğer akım THD (%)100 * sqrt(sum_h(I_h^2)) / max(IFUND_EQ, EPS)
Q_MODEReaktif güç yön moduQ_TOT > +Q_TH => LEAD, Q_TOT < -Q_TH => LAG, aksi NEUTRAL
ENERGY_DIREnerji 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_EQ ve IFUND_EQ, faz temel bileşenlerinin RMS eşdeğeridir (sqrt((X_R^2+X_S^2+X_T^2)/3)).
  • Q_TH ve E_TH eşikleri rule setinden okunur; default sabitler yalnız fallback içindir.
  • Formula değişikliği veya eşik güncellemesi rule_hash değişimiyle izlenmelidir.

Yazım Kuralları

  • Yazım anahtarı stream_id'dir.
  • Aynı stream_id tekrar işlenirse idempotent upsert uygulanır.
  • Rule hesaplaması sırasında bir değişken üretilemezse ilgili alan NULL bırakılabilir; bu durum quality_flags iç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:

  1. Single-writer prensibi uygulanır:
    • Varsayılan mimaride Sentez Servisi Redis state'i doğrudan mutate etmez.
    • Bunun yerine synth.state.patch.v1 benzeri 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.
  2. Başarılıysa synth.ready.v1 üretir.
  3. Downstream window katmanını tetikler.

Başarısızlıkta:

  1. Redis'e hata meta bilgisi işlenir (last_synth_error).
  2. synth.failed.v1 üretilir.
  3. Hata kodu log + DLQ akışına taşınır.
  4. 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: false
  • SYNTH_RULE_INVALID: false
  • SYNTH_RULE_MISS: false

Hata Kodları

  • SYNTH_RULE_MISS
  • SYNTH_RULE_INVALID
  • SYNTH_INPUT_MISSING
  • SYNTH_DB_WRITE_FAIL
  • SYNTH_CALC_TRANSIENT
  • SYNTH_CALC_DETERMINISTIC_FAIL

Index

  • UNIQUE(stream_id)
  • (device_id, device_time DESC)
  • (device_id, stream_time DESC)

Çıktı

Sentez Servisinin çıktısı:

  • energy_synth_results tablosunda kalıcı sentez verisi
  • Redis'te synth_buffer güncellemesi
  • Kafka'da synth.ready.v1 (veya hata durumunda synth.failed.v1)

Window Servisi synth.ready.v1 eventini tüketerek pencere hesaplarını başlatır.