fix(liste): üretim sonrası sunucu yanıt vermezse 502 sayfasına gidilmiyor

iPad raporu: liste üretildikten sonra ekran "Bad Gateway" gösterdi ve
tarayıcı `listem.txt` indirdi. Sıra şu: liste DB'ye yazıldı → `router.replace`
→ Next'in RSC isteği ters vekilden 502 aldı → Next tam-sayfa gezinmeye düştü
(WebKit düz metin cevabı dosya olarak kaydetti) → 6 sn'lik emniyet supabı
`window.location.replace` ile aynı 502'yi ekrana getirdi.

Üç değişiklik:

- Dockerfile runner katmanına `--max-old-space-size=768`. V8 cgroup sınırını
  görmez, heap üst sınırını host RAM'ine göre seçer; `mem_limit: 1g` ile
  birleşince V8 daha GC yapmadan konteyner OOM ile ölüyor ve açık istek 502'ye
  düşüyor. Sınır builder katmanında vardı, runner'a miras kalmıyordu.
- `/api/saglik`: DB/oturum/AI'ya dokunmayan en ucuz uç. Dockerfile HEALTHCHECK
  bunu yokluyor — süreç ölüp açılırken `docker ps` "unhealthy" gösterir, bir
  sonraki 502'nin kaynağı tahmine kalmaz.
- Emniyet supabı tam-sayfa gezinmeden önce sunucuyu yokluyor. Sunucu yoksa
  ekranda kalınıp "listen oluşturuldu ve kaydedildi, kredin yeniden harcanmaz"
  ekranı + sunucuyu yeniden yoklayan buton gösteriliyor; `liste_uretim_hata
  {kod:"SUNUCUYA_ULASILAMIYOR"}` olayı düşüyor. Sunucu yokken `router.refresh`
  de aynı tuzağa düştüğü için o dalda atlanıyor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-22 01:08:18 +03:00
parent cc46244206
commit d41120c3ce
3 changed files with 128 additions and 3 deletions

View File

@@ -48,6 +48,15 @@ WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# V8, cgroup bellek sınırını GÖRMEZ: heap üst sınırını konteynerin değil host'un
# RAM'ine göre seçer (host 4 GB ise ~2 GB). docker-compose'daki mem_limit=1g ile
# birleşince sonuç, V8 daha GC yapmadan kernel'ın konteyneri OOM ile öldürmesi
# olur; o anda açık olan istek ters vekilde 502 "Bad Gateway" olarak düşer
# (22 Eyl 2026: liste üretiminin hemen ardından alınan 502 raporu). Sınır elle
# verilir: mem_limit'in ~%75'i; kalanı native taraf (better-sqlite3, mmap'lı
# SQLite sayfaları, Node'un kendi RSS'i) için ayrılır. mem_limit değişirse bu
# sayı da değişmeli.
ENV NODE_OPTIONS="--max-old-space-size=768"
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
@@ -81,4 +90,11 @@ EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
# Konteyner gerçekten istek karşılıyor mu (alpine'de curl yok, Node 20'nin
# global fetch'i kullanılır). Uç bilerek en ucuz olanı: app/api/saglik DB'ye,
# oturuma, AI'ya dokunmaz. Süreç OOM ile ölüp yeniden açılırken `docker ps`
# durumu "unhealthy" gösterir — 502'lerin kaynağı tahmine kalmaz.
HEALTHCHECK --interval=30s --timeout=5s --start-period=45s --retries=3 \
CMD node -e "fetch('http://127.0.0.1:3000/api/saglik').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
CMD ["/app/docker-entrypoint.sh"]