Window Servisi
Topoloji referansı: /projects/cinga/backend#sistem-işleyiş-akışı
Window Servisi, synth.ready.v1 eventini tüketip zaman ölçekli istatistik ve trend kayıtlarını energy_windows tablosuna yazan mikroservistir.
Bu servis sentez hesabı yapmaz; yalnızca pencere (fixed + rolling) güncellemelerini yürütür ve analiz katmanını güncel tutar.
Sorumluluk
synth.ready.v1eventini consume etmek- Girdi setini Redis
device_buffer+ DB fallback ile çözmek - Sabit pencereleri (
1D,1W,1M) güncellemek/finalize etmek - Kayan pencereleri (
1D_Last,1W_Last,1M_Last) grid hizalı güncellemek - Sonuçları
energy_windowstablosuna idempotent upsert etmek - Başarıda
window.ready.v1, hatadawindow.failed.v1üretmek
İşlem Akışı
Girdi Kaynakları
Window servisi girdileri üç kaynaktan çözer:
- Redis (
device_buffer)synth_buffer(hızlı pencere güncelleme için)raw_buffer(eksik sentez alanı için)
- DB (birincil doğrulama/fallback)
energy_synth_results- gerektiğinde
energy_*_measurements
- Policy/Config
window_types,grid_step,late_tolerance,finalize_delay
Alan çözümleme sırası (deterministic):
synth_buffer- Eksik alan için
energy_synth_results - Hâlâ eksikse
raw_buffer/energy_*_measurements
Not: Redis miss veya eksik alan durumunda DB fallback zorunludur.
Pencere Tipleri ve Finalize Kuralları
Sabit pencereler:
1D: takvim günü1W: hafta başlangıç grid'i1M: ay başlangıç grid'i
Kayan pencereler:
1D_Last: son 24 saat1W_Last: son 7 gün1M_Last: son 30 gün
Finalize kuralları:
- Sabit pencerede
window_endgeçildikten velate_tolerancedolduktan sonrafinalized=trueset edilir. - Rolling pencereler varsayılan olarak
finalized=falsekalır (sürekli güncellenir). - Grid hizalama zorunludur (
anchor_time), aksi kayıtWINDOW_GRID_MISALIGNEDile reddedilir.
Final Buffer + Hesaplama Politikası (Karar)
Bu sayfada kilitlenen final yaklaşım:
- Redis raw/synth buffer en fazla 48 saat tutulur.
- Rolling hesaplar ham uzun geçmişten değil, mümkün olduğunca incremental state + bucket rollup ile yürütülür.
p10/p50/p90yalnızca sabit pencere kapanışında hesaplanır; rolling pencerelerde percentile hesaplanmaz.- Sabit pencere hesapları dönem sonunda Window Servisi tarafından tetiklenir:
- Gün sonu ->
1D - Hafta sonu ->
1W - Ay sonu ->
1M
- Gün sonu ->
Bu modelin sonucu:
- Redis şişmez (1 ay ham sample tutulmaz)
- DB her eventte sorgulanmaz
- Sabit dönem kapanışlarında tek/toplu finalize sorguları ile doğru hesap korunur
Büyük Pencere Hesabı (1W / 1M)
1W ve 1M pencereler mümkün olduğunca rollup ile hesaplanır:
- Önce
1D/1D_Lastpencerelerini güncelle. 1Wiçin ilgili 1D kayıtları birleştir.1Miçin ilgili ay içi 1D kayıtları birleştir.- Gap varsa yalnız eksik aralığı ham kaynaktan tamamla.
Bu model DB yükünü azaltır ve büyük pencere hesaplarını stabil tutar.
Hesaplama Yöntemi Akış Diyagramı
energy_windows Persist Tablosu
| Kolon | Tip | Zorunluluk | Not |
|---|---|---|---|
id | bigint PK | Zorunlu | |
device_id | varchar(21) | Zorunlu | |
variable_id | varchar(30) | Zorunlu | |
window_type | varchar(16) | Zorunlu | fixed/rolling |
window_start | timestamptz | Zorunlu | |
window_end | timestamptz | Zorunlu | |
anchor_time | timestamptz | Önerilen | grid anchor |
finalized | boolean | Zorunlu | |
calc_version | integer | Zorunlu | |
sample_count | integer | Zorunlu | |
expected_sample_count | integer | Zorunlu | |
completeness_ratio | double precision | Zorunlu | |
quality_flags | jsonb | Zorunlu | |
sum, sum_sq, min, max | double precision | Zorunlu | |
mean, stddev | double precision | Zorunlu | |
p10, p50, p90 | double precision | Zorunlu | V1 core |
sum_t, sum_v, sum_tv, sum_t2 | double precision | Zorunlu | trend altyapısı |
slope | double precision | Zorunlu | |
r2 | double precision | Zorunlu (V1) | trend uyum katsayısı |
first_value, last_value, delta_value | double precision | Sayaçta zorunlu | |
counter_reset_count | integer | Sayaçta zorunlu | |
counter_rollover_count | integer | Sayaçta zorunlu | |
created_at, updated_at | timestamptz | Zorunlu |
Yazım Kuralları
- Upsert anahtarı:
UNIQUE(device_id, variable_id, window_type, window_start) - Aynı pencere tekrar işlenirse idempotent upsert uygulanır.
finalized=trueolmuş sabit pencereye veri değişikliği yalnız Replay Worker tarafından,replay_reasonvereplay_job_idalanları ile izlenebilir biçimde izinlidir; normal worker akışında update reddedilir.READ COMMITTED+ idempotent upsert varsayılan isolation modelidir.
Yazım Sonrası Akış
DB yazımı tamamlandıktan sonra servis:
- Single-writer prensibi ile state patch üretir:
window.state.patch.v1benzeri event ile patch taşınır.- State Writer patch'i
device_buffer:{device_id}.window_bufferüstüne atomik uygular. - Embedded single-writer modunda aynı süreçte doğrudan update yapılabilir.
- Başarılıysa
window.ready.v1üretir. - Opsiyonel skor katmanını tetikler.
Başarısızlıkta:
window.failed.v1üretilir.- Hata kodu log + DLQ akışına taşınır.
- Tekrar işleme idempotent pencere anahtarı üstünden yapılır.
Topic ve Event Standardı
Bu sayfada kullanılan standart:
- Kafka topic:
cinga.window.ready,cinga.window.failed - Event adı:
window.ready.v1,window.failed.v1
Not: Topic taşıma kanalıdır, event payload sözleşmesidir.
Event Sözleşmeleri
window.ready.v1
{
"event": "window.ready.v1",
"meta": {
"schema_version": 1,
"trace_id": "9f3f...",
"producer_service": "window-service",
"produced_at": "2026-03-11T15:22:15.040Z",
"process_ms": 27
},
"context": {
"device_id": "400000011D081B70",
"stream_id": 9823412
},
"data": {
"calc_version": 1,
"window_types_updated": [
"1D_Last",
"1W_Last",
"1M_Last"
],
"finalized_windows": [
"1D"
]
},
"error": null
}
window_types_updated enum kümesi:
1D1W1M1D_Last1W_Last1M_Last
window.failed.v1
{
"event": "window.failed.v1",
"meta": {
"schema_version": 1,
"trace_id": "9f3f...",
"producer_service": "window-service",
"produced_at": "2026-03-11T15:22:15.070Z",
"process_ms": 27
},
"context": {
"device_id": "400000011D081B70",
"stream_id": 9823412
},
"error": {
"failed_stage": "window",
"error_code": "WINDOW_DB_WRITE_FAIL",
"error_message": "energy_windows upsert failed",
"retryable": true,
"failed_at": "2026-03-11T15:22:15Z"
}
}
retryable karar matrisi:
WINDOW_DB_WRITE_FAIL: trueWINDOW_INPUT_TRANSIENT: true (geçici state/lag)WINDOW_GRID_MISALIGNED: falseWINDOW_POLICY_INVALID: falseWINDOW_INPUT_MISSING: false
Hata Kodları
WINDOW_INPUT_MISSINGWINDOW_INPUT_TRANSIENTWINDOW_POLICY_INVALIDWINDOW_GRID_MISALIGNEDWINDOW_DB_WRITE_FAIL
İstatistik Field Hesaplama Rehberi
Aşağıdaki bölümde V1 alanları için nedir / nasıl hesaplanır / neye ihtiyaç duyar formatı kullanılmıştır.
V1 (Aktif)
1) Kalite Alanları
sample_count- Nedir: Pencereye giren geçerli örnek sayısı.
- Nasıl hesaplanır: Validasyon geçen örneklerin adedi.
- Neye ihtiyaç duyar:
window_start,window_end, valid örnek listesi.
expected_sample_count- Nedir: Bu pencere için beklenen teorik örnek sayısı.
- Nasıl hesaplanır:
window_duration / sample_period. - Neye ihtiyaç duyar: Pencere süresi, cihaz örnekleme periyodu.
completeness_ratio- Nedir: Veri doluluk oranı.
- Nasıl hesaplanır:
sample_count / max(expected_sample_count, 1). - Neye ihtiyaç duyar:
sample_count,expected_sample_count.
quality_flags- Nedir: Gap/reset/rollover/outlier gibi kalite işaretleri.
- Nasıl hesaplanır: Kural kontrollerinden üretilen flag seti (
jsonb). - Neye ihtiyaç duyar: Ham/sentez akışı kalite olayları, policy eşikleri.
2) Dağılım Alanları
sum- Nedir: Toplam değer.
- Nasıl hesaplanır:
Σ x_i. - Neye ihtiyaç duyar: Pencere örnekleri.
sum_sq- Nedir: Kareler toplamı.
- Nasıl hesaplanır:
Σ x_i^2. - Neye ihtiyaç duyar: Pencere örnekleri.
min,max- Nedir: Pencere içi alt/üst uç.
- Nasıl hesaplanır:
min(x_i),max(x_i). - Neye ihtiyaç duyar: Pencere örnekleri.
mean- Nedir: Ortalama.
- Nasıl hesaplanır:
sum / max(sample_count, 1). - Neye ihtiyaç duyar:
sum,sample_count.
stddev- Nedir: Standart sapma.
- Nasıl hesaplanır:
sqrt(max(sum_sq/n - mean^2, 0)),n=sample_count. - Neye ihtiyaç duyar:
sum_sq,sample_count,mean.
p10,p50,p90- Nedir: Alt/orta/üst percentile göstergeleri.
- Nasıl hesaplanır: Sıralı veri üzerinden percentile fonksiyonu (veya sketch).
- Neye ihtiyaç duyar: Pencere örnek dağılımı (ham veya sketch state).
3) Trend Alanları
sum_t- Nedir: Zaman indeks toplamı.
- Nasıl hesaplanır:
Σ t_i. - Neye ihtiyaç duyar: Grid-hizalı zaman indeksleri.
sum_v- Nedir: Değer toplamı (trend hesabı için).
- Nasıl hesaplanır:
Σ v_i. - Neye ihtiyaç duyar: Pencere değerleri.
sum_tv- Nedir: Zaman*değer toplamı.
- Nasıl hesaplanır:
Σ (t_i * v_i). - Neye ihtiyaç duyar: Zaman indeksleri + değerler.
sum_t2- Nedir: Zaman kare toplamı.
- Nasıl hesaplanır:
Σ (t_i^2). - Neye ihtiyaç duyar: Zaman indeksleri.
slope- Nedir: Lineer trend eğimi.
- Nasıl hesaplanır:
(n*sum_tv - sum_t*sum_v) / max(n*sum_t2 - sum_t^2, EPS). - Neye ihtiyaç duyar:
n,sum_t,sum_v,sum_tv,sum_t2.
r2- Nedir: Trend uyum katsayısı.
- Nasıl hesaplanır:
1 - SSE/SST(SST=0 iser2=1). - Neye ihtiyaç duyar: Regresyon tahmin hataları veya eşdeğer ara toplamlar.
4) Sayaç Alanları (Counter Variables)
first_value- Nedir: Pencere başlangıcındaki sayaç.
- Nasıl hesaplanır: Pencereye giren ilk geçerli örnek.
- Neye ihtiyaç duyar: Zaman sıralı sayaç örnekleri.
last_value- Nedir: Pencere sonundaki sayaç.
- Nasıl hesaplanır: Pencereye giren son geçerli örnek.
- Neye ihtiyaç duyar: Zaman sıralı sayaç örnekleri.
delta_value- Nedir: Pencere net tüketim/değişim değeri.
- Nasıl hesaplanır:
last_value - first_value(reset/rollover düzeltmeleri policy’ye göre). - Neye ihtiyaç duyar:
first_value,last_value, reset/rollover tespiti.
counter_reset_count- Nedir: Sayaç reset sayısı.
- Nasıl hesaplanır: Ani negatif büyük sıçrama + reset pattern eşleşmesi.
- Neye ihtiyaç duyar: Ardışık sayaç örnekleri, reset eşik/policy.
counter_rollover_count- Nedir: Sayaç taşma (rollover) sayısı.
- Nasıl hesaplanır: Modül üst sınırını aşan geçişlerin tespiti.
- Neye ihtiyaç duyar: Sayaç bit genişliği/modulus bilgisi, ardışık örnekler.
V2 (Deferred)
V2’de Eklenecek İstatistikler
- Geniş percentile seti:
p01,p05,p95,p99 - Ek regresyon alanı:
intercept - Geniş event/maruziyet alanları (threshold süreleri, event breakdown)
Index
UNIQUE(device_id, variable_id, window_type, window_start)(device_id, variable_id, window_type, window_end DESC)(device_id, window_type, window_start DESC)
Çıktı
Window Servisinin çıktısı:
energy_windowstablosunda kalıcı pencere verisi- Redis
window_bufferstate güncellemesi (state-writer üzerinden) - Kafka'da
window.ready.v1(veya hata durumundawindow.failed.v1)