Dönem kapanıyor. 2.000 daire için faturalar hesaplandı. Şimdi hepsinin PDF’i lazım — yazdırılacak, zarflanacak, dağıtılacak.
Eski akış şöyleydi: bir butona basılır, tarayıcı bekler, sunucu üretmeye başlar. Dört dakika sonra bağlantı düşer. Kimse kaç faturanın üretildiğini bilmez. Baştan denenir.
Önce nerede takıldığını ölçtüm
“Yavaş” yeterli bir teşhis değil. Adımları ayrı ayrı ölçtüm:
| adım | fatura başına | toplamın yüzdesi |
|---|---|---|
| Veritabanı sorguları | ~0,002 sn | %2,5 |
| Şablon derleme | ihmal edilebilir | — |
| PDF render | 0,11 sn | %97 |
Yani sorgu optimizasyonu yapsam, toplam sürenin en fazla %2,5’ini kazanacaktım. Darboğaz tamamen PDF üretiminde.
Ve PDF render’ı hızlandırmanın yolu yok — kütüphane ne kadar sürüyorsa o kadar sürüyor. Geriye tek seçenek kalıyor: işi hızlandırma, beklemeyi kaldır.
Tek istekte bu süre, web sunucusunun da tarayıcının da sabrının üstünde. Ama arka planda çalışan bir süreç için tamamen normal bir süre.
İş kuyruğu
Her ağır iş artık bir kayıt. Tabloda duruyor, durumu var, ilerlemesi var.
iş #4471
tür : fatura_toplu_pdf
durum : çalışıyor
ilerleme : 1.284 / 2.000
başlangıç : 14:02:11
nabız : 14:09:38 ← işçi hâlâ hayatta mı?
kontrol : — ← durdur / devam / iptal buraya yazılır
Kullanıcı butona bastığında iş yaratılıyor ve sayfa hemen dönüyor. Arka planda bir işçi başlıyor. Panelde ilerleme çubuğu var.
Kuyruk neden ana veritabanında
Bu sistemde faturalar dönem veritabanlarında duruyor — her fatura dönemi kendi veritabanı. İşçi de doğal olarak o döneme bağlanıyor.
Ama iş kaydını oraya koyarsan, ana paneldeki “çalışan işler” listesi hangi döneme bakacağını bilemez. Bu yüzden kuyruk tablosu ayarlar veritabanında, tam nitelikli adla yazılıyor. İşçi hangi döneme bağlı olursa olsun, ilerlemesini oraya yazabiliyor.
Küçük bir karar gibi görünüyor; “tüm işleri tek ekranda görebilmek” özelliğinin tamamı buna bağlı.
Durdur ve devam et
En çok istenen özellik buydu. Yanlış dönemi seçip 2.000 faturalık bir iş başlattığında, bitmesini beklemek istemiyorsun.
İşçi her N faturada bir iki şey yapıyor: ilerlemesini kaydediyor ve kontrol kanalına bakıyor.
her 25 faturada:
ilerlemeyi yaz
kontrol kanalını oku
"durdur" → ZIP'i kapat, durumu 'duraklatıldı' yap, temiz çık
"iptal" → temizle ve çık
(boş) → devam
Devam edildiğinde işçi kaldığı yerden başlıyor ve ZIP dosyasına ekleme yapıyor — yeniden yazmıyor. 1.284 fatura üretilmişse o 1.284 fatura tekrar üretilmiyor.
Ölü işçileri toplamak
Bir işçi çökebilir. Sunucu yeniden başlayabilir. İş kaydı “çalışıyor” durumunda kalır ve sonsuza kadar öyle kalır.
Bu yüzden nabız var: işçi düzenli aralıklarla “hâlâ buradayım” diyor. Nabzı belirli bir süredir gelmeyen işler toplanıyor — durumları “ölü işçi” olarak işaretleniyor ve yeniden başlatılabilir hale geliyorlar.
Sistemde eşzamanlı çalışan iş sayısı sınırlı. “Çalışıyor” görünen ama aslında ölmüş bir iş, o kotadan bir yer işgal eder. Üç dört tanesi birikince kuyruk tamamen tıkanır ve hiçbir yeni iş başlamaz — üstelik ekranda her şey normal görünür.
Nabız, bir sistemin kendi yalanını yakalama mekanizması.
Ve sonra genelleşti
İş tipini en baştan serbest bıraktım: job_type bir metin alanı. İlk kullanım toplu PDF’ti ama hemen arkasından geldiler:
- Excel dışa aktarım
- Termal yazıcı çıktısı (58 / 80 / 90 / 120 mm)
- Toplu mail gönderimi
- Veri içe aktarma
Dördü de aynı kuyruğu, aynı paneli, aynı durdur/devam mekanizmasını kullanıyor. Yazılan tek şey işin kendisi oldu.
Ne öğrendim
“Yavaş” bir teşhis değil, bir şikâyet. Ölçünce darboğazın %97’sinin tek bir yerde olduğu çıktı — ve orası optimize edilemeyen bir yerdi.
O noktada doğru hamle daha hızlı yapmak değil, beklemeyi ortadan kaldırmaktı. Kullanıcı için 3 dakika 40 saniye artık yok; iş başlatılıyor ve o başka şey yapıyor.