fix: SSE timeout during social proof collection

Ne yaptık:
- time.sleep() → await asyncio.sleep() ile event loop bloklanması engellendi
- Sosyal kanıt batch size 5 → 20 (1115 istek → 279 istek, %75 azalma)
- SSE keepalive heartbeat eklendi (her 10 batch'te bir)
- Nginx proxy timeout 180s → 600s (10 dakika)
- Rate limit sleep süreleri optimize edildi (2s→1.5s, 0.5s→0.3s)

Neden yaptık:
- Kadın kategorisi gibi büyük raporlarda (82 yaprak kategori, 5576 ürün)
  sosyal kanıt aşamasında SSE bağlantısı kopuyordu. Kök neden:
  senkron time.sleep() async generator içinde event loop'u blokluyor,
  proxy idle timeout'a takılıyor ve bağlantıyı kesiyordu.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
furkanyigit34
2026-03-27 17:01:14 +03:00
parent f5562e2135
commit dc1f8fcfb2
2 changed files with 9 additions and 7 deletions

View File

@@ -37,8 +37,8 @@ server {
# Timeouts for long-running operations # Timeouts for long-running operations
proxy_connect_timeout 60s; proxy_connect_timeout 60s;
proxy_send_timeout 180s; proxy_send_timeout 600s;
proxy_read_timeout 180s; proxy_read_timeout 600s;
# Disable buffering for streaming responses # Disable buffering for streaming responses
proxy_buffering off; proxy_buffering off;

View File

@@ -1567,8 +1567,8 @@ async def create_report(
yield f"data: {json_module.dumps({'type': 'error', 'message': f'{cat_name} - Hata: {str(e)}', 'progress': progress})}\n\n" yield f"data: {json_module.dumps({'type': 'error', 'message': f'{cat_name} - Hata: {str(e)}', 'progress': progress})}\n\n"
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
# Rate limiting # Rate limiting (non-blocking)
time.sleep(2.0) await asyncio.sleep(1.5)
# ============================================ # ============================================
# Sosyal Kanıt Verilerini Topla # Sosyal Kanıt Verilerini Topla
@@ -1630,7 +1630,7 @@ async def create_report(
social_proof_data = {} social_proof_data = {}
total_products = len(all_product_ids) total_products = len(all_product_ids)
processed = 0 processed = 0
batch_size = 5 batch_size = 20
# print(f"🔍 DEBUG: Toplam {total_products} ürün ID'si toplandı") # print(f"🔍 DEBUG: Toplam {total_products} ürün ID'si toplandı")
# print(f"🔍 DEBUG: İlk 5 ürün ID'si: {all_product_ids[:5] if all_product_ids else 'YOK'}") # print(f"🔍 DEBUG: İlk 5 ürün ID'si: {all_product_ids[:5] if all_product_ids else 'YOK'}")
@@ -1677,8 +1677,10 @@ async def create_report(
processed += len(chunk) processed += len(chunk)
progress_pct = int((processed / total_products) * 5) + 85 # 85-90% progress_pct = int((processed / total_products) * 5) + 85 # 85-90%
yield f"data: {json_module.dumps({'type': 'info', 'message': f'📊 Sosyal kanıt: {processed}/{total_products} ürün', 'progress': progress_pct})}\n\n" yield f"data: {json_module.dumps({'type': 'info', 'message': f'📊 Sosyal kanıt: {processed}/{total_products} ürün', 'progress': progress_pct})}\n\n"
await asyncio.sleep(0.02) # SSE keepalive heartbeat every 10 batches
time.sleep(0.5) # Rate limiting if processed % (batch_size * 10) == 0:
yield f": heartbeat\n\n"
await asyncio.sleep(0.3) # Rate limiting (non-blocking)
# print(f"✅ DEBUG: Sosyal kanıt toplama tamamlandı. Toplanan veri: {len(social_proof_data)} ürün") # print(f"✅ DEBUG: Sosyal kanıt toplama tamamlandı. Toplanan veri: {len(social_proof_data)} ürün")
yield f"data: {json_module.dumps({'type': 'success', 'message': f'✅ Sosyal kanıt verileri toplandı ({len(social_proof_data)} ürün)', 'progress': 90})}\n\n" yield f"data: {json_module.dumps({'type': 'success', 'message': f'✅ Sosyal kanıt verileri toplandı ({len(social_proof_data)} ürün)', 'progress': 90})}\n\n"