AOY
TR EN
← Yazılar

21 il boş kaldı: koruma bozuk veriyi engellemedi, kendi geçmişine takıldı

31 Ağustos 2026· 3 dk okuma· Canlı olay

Gelen veri baştan beri sağlıklıydı. Yazılmasını engelleyen şey, korumanın bir gün önceki kendi çıktısıydı.

Belirti tek cümleydi: “bugün İstanbul’daki hiçbir eczane kaydı yok.” Nöbet saatlerinde. Ölçüldüğünde 21 il boştu — İstanbul, Ankara, İzmir, Antalya ve Bursa dahil. Kullanıcı “Kayıt bulunamadı” görüyordu.

İlk eleme kolaydı: kalan 61 il normaldi. Sağlayıcı çökseydi hepsi boş olurdu. Yani sorun bizim tarafımızdaydı.

Koruma neden vardı

Veri il eczacı odalarının listelerinden günlük çekimle geliyor ve sağlayıcı bazen yarım liste döndürüyor. Yarım listeyi yazmak, gerçekte nöbetçi olan bir eczaneyi listeden düşürmek demek — bu yüzden bir koruma var: gelen kayıt sayısı referansın yarısının altındaysa o gün için yazma atlanıyor.

Referans olarak “son gün” alınıyordu. Sorun oradaydı.

Kök neden

Bir gün önce 30 Ağustos Zafer Bayramıydı ve iki şey üst üste geldi:

  • Gün içinde iki çekim koştu (06:15 ve 16:45).
  • Bayramda nöbet vardiyası gün içinde dönüyor; iki ayrı vardiya aynı nöbet tarihine yazıldı.

Sonuç: İstanbul’un o günkü kayıt sayısı 130 yerine 285 oldu. Ertesi gün gelen normal 131 kayıt bu şişmiş referansın %50 eşiğinin altında kaldı, “yarıya düştü” sanıldı ve atlandı.

İstanbul’un son beş günü şöyleydi: 130 · 130 · 130 · 131 · 129. Yani gelen veri baştan beri sağlıklıydı.

Asıl problem

Koruma bozuk veriyi engellemedi. Kendi geçmişindeki tek günlük bir anomaliye takıldı ve doğru veriyi engelledi.

Tek örneğe dayanan her eşik, er ya da geç gerçeğe karşı korumaya başlar.

Acil müdahale — veri, kod değil

Kod düzeltmesi beklemeden önce canlı düzelmeliydi. 30 Ağustos’un sabah partisi (691 satır / 21 il) yedek tabloya alındı, silindi, çekim damgası temizlendi ve çekim zorlandı.

Sonuç: 1332 kayıt / 82 il, atlanan yok. Canlı API’den doğrulandı — İstanbul 131, Ankara 49, İzmir 72, Antalya 39, Bursa 34.

Kalıcı düzeltme — referans son beş günün medyanı

const recentDays = await prisma.dutyEntry.groupBy({
  by: ['dutyDate'],
  where: { provinceCode: code, dutyDate: { lt: dutyDate } },
  _count: { _all: true },
  orderBy: { dutyDate: 'desc' },
  take: 5,
});
const counts = recentDays.map((d) => d._count._all).sort((a, b) => a - b);
const lastCount = counts.length > 0 ? counts[Math.floor(counts.length / 2)] : 0;
Karar · medyan, ortalama değil

Medyan tek günlük anomaliyi tamamen yutuyor: çift çekim, sağlayıcı hıçkırığı, bayram rotasyonu. Ortalama ise şişmeyi beşte bir oranında taşımaya devam ederdi — yani problemi küçültür ama çözmezdi.

Koruma hâlâ çalışıyor: gerçekten yarım gelen bir liste, beş günün medyanına göre de düşük kalır.

Doğrulama için silinen parti yedekten geri kuruldu ve olay birebir yeniden üretildi:

İlGelenEski referansYeni referansEski kuralYeni kural
34131285130atlanırdıgeçer
357214771atlanırdıgeçer
064910451atlanırdıgeçer

Bu olayın en kötü yanı sessiz olmasıydı

Worker “atlandı” diye log yazıp başarıyla bitiyor. Hata alarmı çalmıyor, izleme yeşil kalıyor, ölçümler normal görünüyor. Teşhis tamamen birinin uygulamayı açıp fark etmesine kaldı.

Doğru izleme noktası şu: büyük illerde (34/06/35) kayıt sayısı sıfırsa uyar. “İş başarıyla bitti” ile “iş doğru şeyi yaptı” aynı şey değil.


Çıkarılacak dersler

  • Tek örneğe dayanan eşik kullanma. Dün, bugünün ne olması gerektiğinin güvenilir bir ölçüsü değil.
  • Bayram ve özel günler çift vardiya riski taşıyor. Bir tarihe iki vardiya yazıldıysa veri hatalı değildir — ama sayıya dayanan hiçbir koruma o günü referans almamalı.
  • Korumanın kendi çıktısını referans alması bir geri besleme döngüsüdür. Bugünkü çıktı yarınki eşiği belirliyorsa, bir kez şişen sayı ertesi günü de bozar.
  • “Atlandı” bir hata değildir, bir karardır — ve kararlar loglanmakla kalmaz, izlenir. Sessizce doğru şeyi yapmayan bir sistem, gürültülü şekilde yanlış yapan bir sistemden daha tehlikeli.

İlgili proje

Diğer yazılar

hepsi