Files
MathApp/gunicorn.conf.py
Zareian 701d8badcc make streaks and the leaderboard live, and stop three AI chats from freezing the API
Found in a deeper pass over what the frontend's flow actually touches:

- Nothing in the app ever wrote StreakRecord: "days in a row" was 0 forever
  for every real user. Answers and lesson/island completions now record the
  day (Tehran time); a broken chain shows 0. A streak error never fails the
  answer itself.
- /api/leaderboard only changed when someone ran rebuild_leaderboard by
  hand. It is now computed live (60s cache); weekly counts island XP too.
- gunicorn ran 3 sync workers with a 30s timeout, so every "ask Pi" stream
  pinned a whole worker (~10s, GapGPT buffers the answer) and three at once
  queued the entire API. gunicorn.conf.py (read automatically from the
  working directory) switches to gthread, 8 threads, 120s timeout.
- Every /api/ response now says Cache-Control: private, no-store, so turning
  on caching in the ArvanCloud panel can never serve one student another's data.
- /api/user/summary named no active plan ever ("subscription app not
  implemented yet" had long stopped being true).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 06:39:50 +03:30

29 lines
1.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
تنظیماتِ gunicorn — خودِ gunicorn این فایل را از پوشه‌ی کاری
(WorkingDirectory=~/mathapp-v2 در unitِ systemd) خودکار می‌خواند، پس بدونِ
دست زدن به /etc با همان deploy.sh به سرور می‌رسد. آرگومان‌های خطِ فرمانِ
unit (مثلِ `--workers 3` و `--bind`) بر این فایل مقدم‌اند.
چرا لازم شد (۲۰۲۶-۰۹-۲۴): unit با workerهای sync و timeoutِ پیش‌فرضِ ۳۰
ثانیه اجرا می‌شد. هر استریمِ «از پی بپرس» یک worker را تا پایانِ جواب (~۱۰
ثانیه، چون GapGPT خودش تا آماده شدنِ کلِ جواب نگه می‌دارد) اشغال می‌کرد؛ سه
دانش‌آموزِ هم‌زمان با دستیار یعنی بقیه‌ی اپ — نقشه، آزمون، همه‌چیز — در صف.
جوابِ بالای ۳۰ ثانیه هم وسطِ کار کشته می‌شد.
gthread هر worker را چند نخی می‌کند: ۳ worker × ۸ نخ = ۲۴ درخواستِ هم‌زمان.
کدِ جنگو برای نخ امن است و SQLite با `OPTIONS.timeout=20` نوشتنِ هم‌زمان را
تحمل می‌کند. timeout در gthread به ضربانِ خودِ worker است، نه طولِ هر
درخواست، پس استریمِ طولانی دیگر کشته نمی‌شود.
"""
worker_class = 'gthread'
threads = 8
timeout = 120
graceful_timeout = 30
keepalive = 5
# worker بعد از چند هزار درخواست تازه می‌شود تا نشتِ حافظه‌ی احتمالی جمع
# نشود؛ jitter نمی‌گذارد هر سه با هم ری‌استارت شوند.
max_requests = 2000
max_requests_jitter = 200