2026-03-15
Uzun süren scraping job'larını arka planda yönetmek
Bir fiyat scraping job'ı 30 saniye ile 3 dakika arası sürebiliyor. Bunu senkron API endpoint'inde yapamazsın, timeout yersin. Arka planda çalıştırıp sonucu sonradan almak lazım.
Job lifecycle
Her scraping isteği bir "search job". Durumlar basit:
PENDING → RUNNING → COMPLETED veya FAILED
Client job'ı oluşturuyor, bir ID alıyor, sonra o ID ile sonucu sorguluyor.
Event-driven akış
Spring'in ApplicationEventPublisher'ını kullanıyorum:
1. Job oluştur → SearchJobCreatedEvent
2. Listener scraping başlatır → RawResultReceivedEvent
3. Listener parse eder → RawResultParsedEvent
4. Listener özetler → job COMPLETED
Her adım @Async method'da çalışıyor. Biri patlarsa diğerlerini etkilemiyor.
Önemli detay: @TransactionalEventListener(phase = AFTER_COMMIT) kullanıyorum. Event ancak DB transaction commit olduktan sonra tetikleniyor. Yoksa listener henüz commit olmamış veriyi okumaya çalışıyor.
Thread pool
var executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(6);
executor.setMaxPoolSize(16);
executor.setQueueCapacity(100);
4 core sunucuda 16 max thread makul. Queue 100 job tutuyor.
Takılan job'ları temizle
Bazen job takılıyor, site cevap vermiyor veya captcha döngüsüne giriyor. Scheduled task ile temizliyorum:
@Scheduled(fixedRate = 60000) // her dakika kontrol
public void failStaleJobs() {
// 30 dakikadır PENDING veya RUNNING olanları FAILED yap
}
JSONB ile parametre saklama
Her job'ın arama parametreleri PostgreSQL JSONB olarak duruyor:
{
"STATEINC": "1",
"CHECKIN": "2026-04-15",
"NIGHTS": "7",
"CURRENCY": "EUR"
}
Her operatörün farklı parametreleri var, hepsini ayrı kolon yapmak yerine JSONB kullanmak daha esnek. Debug için de güzel: aynı parametrelerle job'ı replay edebiliyorsun.
Parametre validasyonu
Her operatörün desteklediği değerler farklı. Birisi EUR kabul eder, diğeri sadece USD. Yanlış parametre boş sonuç döndürüyor.
operator_search_param tablosunda her operatörün geçerli değerleri kayıtlı. Job oluşturulmadan önce kontrol ediliyor, geçersizse 400.
Queue'ya geçiş hazırlığı
Şu an Spring event'leri kullanıyorum ama mimari queue-ready. ApplicationEventPublisher yerine @KafkaListener veya @RabbitListener koysan aynı şekilde çalışır. Event class'ları değişmez, sadece transport değişir. Baştan event-driven yazmak scale gelince büyük refactor'ı engelliyor.