Add JSON representation of composer.json structure with nodes and edges
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# تشخیص «ریاستارت» سرور روی Coolify + رفع نویز لاگ + بررسی خطای ACME
|
||||
|
||||
## پروژه
|
||||
|
||||
`clinicpro` (فقط فایلهای deploy — بدون تغییر در کد PHP/React)
|
||||
|
||||
## زمینه
|
||||
|
||||
کاربر در لاگهای production (Coolify روی Ubuntu) میبیند که workerها مدام exit/spawn میشوند و نگران است سرور down میشود. تحلیل لاگ ارائهشده:
|
||||
|
||||
```
|
||||
2026-07-08 07:40:54,435 INFO exited: worker-scheduler (exit status 0; expected)
|
||||
2026-07-08 07:40:54,457 INFO spawned: 'worker-scheduler' with pid 1464
|
||||
2026-07-08 07:40:54,460 INFO exited: worker-async (exit status 0; expected)
|
||||
2026-07-08 07:40:54,468 INFO spawned: 'worker-async' with pid 1465
|
||||
2026-07-08 07:40:55,674 INFO success: worker-async entered RUNNING state ...
|
||||
```
|
||||
|
||||
**این crash نیست.** این رفتار طراحیشده است:
|
||||
|
||||
- `docker/supervisord.conf` هر دو worker را با `--time-limit=3600` اجرا میکند → هر worker دقیقاً هر ۱ ساعت با exit code 0 خارج میشود (به همین دلیل supervisor مینویسد `expected`).
|
||||
- supervisord با `autorestart=true` در کمتر از ۱ ثانیه دوباره spawn میکند.
|
||||
- در تمام مدت لاگ، `GET /health` هر ۱۵ ثانیه `200` برگردانده — یعنی nginx + php-fpm (وبسرور اصلی) هرگز down نبوده.
|
||||
- recycle ساعتیِ consumer الگوی استاندارد Symfony Messenger است (جلوگیری از نشت حافظه و connection کهنه به DB/Redis). مستندات Coolify هم healthcheck/restart policy را همینطور توصیه میکند.
|
||||
|
||||
**اما یک مشکل واقعی در لاگ هست** که میتواند در آینده باعث «down شدن» واقعی (خطای TLS) شود:
|
||||
|
||||
```
|
||||
GET /.well-known/acme-challenge/hb1abFQX9d-... HTTP/1.1" 404
|
||||
"Mozilla/5.0 (compatible; Let's Encrypt validation server; ...)"
|
||||
```
|
||||
|
||||
سرور validation لتسانکریپت برای دامنه `clinic-pro.ir` چالش HTTP-01 فرستاده و به جای اینکه Traefik (پراکسی Coolify) خودش جواب بدهد، درخواست به کانتینر app رسیده و 404 گرفته. اگر این وضع ادامه پیدا کند تمدید گواهی شکست میخورد و بعد از انقضای cert فعلی، سایت با خطای TLS از دسترس خارج میشود — کاربر آن را «سرور down شد» میبیند.
|
||||
|
||||
## فایلهای مرتبط
|
||||
|
||||
| فایل | نقش |
|
||||
|------|-----|
|
||||
| `docker/supervisord.conf` | supervisor داخل کانتینر: nginx + php-fpm + دو worker با `--time-limit=3600 -v` |
|
||||
| `docker-compose.yml` | حالت Compose در Coolify: app + دو worker بهصورت سرویس جدا، همان `--time-limit=3600 -v` |
|
||||
| `supervisor.conf` | نسخه Liara — همان الگو |
|
||||
| `docker/healthcheck.sh` | healthcheck کانتینر: `GET /health` → exit 0/1 |
|
||||
| `Dockerfile` | `HEALTHCHECK --interval=15s --retries=5 --start-period=60s` |
|
||||
| `docs/` | مقصد runbook جدید |
|
||||
|
||||
## وضعیت فعلی
|
||||
|
||||
`docker/supervisord.conf`:
|
||||
|
||||
```ini
|
||||
[program:worker-async]
|
||||
command=php bin/console messenger:consume async --time-limit=3600 --memory-limit=128M -v
|
||||
autorestart=true
|
||||
|
||||
[program:worker-scheduler]
|
||||
command=php bin/console messenger:consume scheduler_default --time-limit=3600 -v
|
||||
autorestart=true
|
||||
```
|
||||
|
||||
فلگ `-v` باعث میشود هر بار restart شدن worker، بنر چندخطی «[OK] Consuming messages…» و «The worker will automatically exit…» در stdout چاپ شود — همین بنرها لاگ را شلوغ و «ریاستارت» را ترسناکتر از واقعیت نشان میدهند.
|
||||
|
||||
## وظایف
|
||||
|
||||
### ۱. کاهش نویز لاگ workerها (بدون تغییر رفتار)
|
||||
|
||||
فلگ `-v` را از هر چهار محل حذف کن (دو program در `docker/supervisord.conf`، دو service در `docker-compose.yml`، دو program در `supervisor.conf`). `--time-limit=3600` و `--memory-limit=128M` را **دست نزن** — recycle ساعتی عمداً وجود دارد و باید بماند.
|
||||
|
||||
```ini
|
||||
command=php bin/console messenger:consume async --time-limit=3600 --memory-limit=128M
|
||||
```
|
||||
|
||||
خطاهای واقعی worker همچنان از طریق monolog (stderr) دیده میشوند؛ `-v` فقط verbosity کنسول بود.
|
||||
|
||||
### ۲. Runbook تشخیص «restart واقعی» از «recycle عادی»
|
||||
|
||||
فایل `docs/ops-restarts.md` بساز (فارسی) با این محتوا:
|
||||
|
||||
- توضیح اینکه `exited (exit status 0; expected)` + spawn فوری = recycle عادی و بیضرر است؛ نشانههای مشکل واقعی: `exit status` غیرصفر، `entered FATAL state`، `too many start retries`، یا گپ در لاگهای `/health`.
|
||||
- دستورهای تشخیص روی سرور:
|
||||
|
||||
```bash
|
||||
# آیا خودِ کانتینر ریاستارت شده؟ (uptime کانتینر vs uptime پروسه)
|
||||
docker ps --format 'table {{.Names}}\t{{.Status}}' # Status باید Up X hours (healthy) باشد
|
||||
docker inspect --format '{{.RestartCount}} {{.State.StartedAt}}' <container>
|
||||
docker events --since 24h --filter event=restart --filter event=die
|
||||
```
|
||||
|
||||
- اگر `RestartCount` صفر است و `StartedAt` قدیمی → هیچ ریاستارت واقعیای در کار نیست؛ فقط recycle داخلی worker است.
|
||||
- بخش Coolify: فعالکردن Notifications (Telegram/Email) در Coolify برای event های container stop/unhealthy، تا down شدن واقعی بلافاصله اطلاع داده شود. ارجاع به مستندات: `https://coolify.io/docs/knowledge-base/notifications` و `https://coolify.io/docs/knowledge-base/health-checks`.
|
||||
|
||||
### ۳. بررسی و مستندسازی خطای ACME (مهمترین ریسک down شدن واقعی)
|
||||
|
||||
در همان `docs/ops-restarts.md` بخش «تمدید گواهی TLS» اضافه کن:
|
||||
|
||||
- علامت مشکل: `GET /.well-known/acme-challenge/... → 404` در access log کانتینر app. چالش HTTP-01 باید توسط Traefik خود Coolify جواب داده شود و اصلاً نباید به app برسد؛ رسیدنش یعنی صدور/تمدید cert برای آن دامنه دارد شکست میخورد.
|
||||
- چکلیست رفع روی سرور Coolify:
|
||||
1. در Coolify → resource مربوط به app → تب Domains: مطمئن شو دامنه `clinic-pro.ir` (و `www` اگر لازم است) دقیقاً با schema `https://` روی سرویس `app` ثبت شده باشد. دامنهای که در Coolify ثبت نشده ولی DNS آن به سرور اشاره میکند، همین الگوی 404 را میسازد.
|
||||
2. وضعیت فعلی cert را چک کن: `echo | openssl s_client -connect clinic-pro.ir:443 -servername clinic-pro.ir 2>/dev/null | openssl x509 -noout -dates`
|
||||
3. لاگ Traefik/proxy در Coolify (Servers → Proxy → Logs) را برای خطای acme بررسی کن.
|
||||
- ارجاع: `https://coolify.io/docs/knowledge-base/proxy/traefik/overview` و بخش Domains در مستندات Coolify.
|
||||
|
||||
### ۴. سازگاری healthcheck
|
||||
|
||||
فقط بررسی (بدون تغییر مگر مغایرت پیدا شد): `Dockerfile` مقادیر `interval=15s, retries=5, start-period=60s` دارد و `docker-compose.yml` سرویس app همان مقادیر را — مطمئن شو یکسان بمانند. healthcheck های worker در compose (`ps | grep messenger:consume`) در لحظه exit ساعتیِ worker ممکن است یک بار fail شوند؛ چون `retries: 3` و `interval: 30s` است، سه شکست پیاپی لازم است و restart کانتینر (که Coolify آن را event میکند) رخ نمیدهد مگر worker واقعاً بالا نیاید — این را در runbook هم ذکر کن.
|
||||
|
||||
## نکات مهم
|
||||
|
||||
- **هیچ تغییری در رفتار runtime نده** جز حذف `-v`. `--time-limit` و `autorestart` عمدی و صحیحاند.
|
||||
- این پرامپت فایل PHP/React را لمس نمیکند → migration و بهروزرسانی `docs/api/` لازم ندارد.
|
||||
- `docs/ops-restarts.md` فارسی نوشته شود (زبان محصول)، ولی دستورها و خروجیهای shell انگلیسی بمانند.
|
||||
- سه فایل config (`docker/supervisord.conf`، `docker-compose.yml`، `supervisor.conf`) باید بعد از تغییر همچنان آینه هم بمانند — کامنتهای بالای هر فایل همین را میگویند.
|
||||
- بعد از merge، اعمال روی سرور نیاز به redeploy در Coolify دارد؛ در runbook یادآوری کن.
|
||||
Reference in New Issue
Block a user