Первый трай фикса celery
This commit is contained in:
38
Makefile
38
Makefile
@@ -2,14 +2,26 @@
|
|||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "Доступные команды:"
|
@echo "Доступные команды:"
|
||||||
|
@echo ""
|
||||||
|
@echo "Development:"
|
||||||
@echo " make dev-up - Запустить development окружение"
|
@echo " make dev-up - Запустить development окружение"
|
||||||
@echo " make dev-down - Остановить development окружение"
|
@echo " make dev-down - Остановить development окружение"
|
||||||
@echo " make dev-build - Пересобрать development контейнеры"
|
@echo " make dev-build - Пересобрать development контейнеры"
|
||||||
@echo " make dev-logs - Показать логи development"
|
@echo " make dev-logs - Показать логи development"
|
||||||
|
@echo ""
|
||||||
|
@echo "Production:"
|
||||||
@echo " make prod-up - Запустить production окружение"
|
@echo " make prod-up - Запустить production окружение"
|
||||||
@echo " make prod-down - Остановить production окружение"
|
@echo " make prod-down - Остановить production окружение"
|
||||||
@echo " make prod-build - Пересобрать production контейнеры"
|
@echo " make prod-build - Пересобрать production контейнеры"
|
||||||
@echo " make prod-logs - Показать логи production"
|
@echo " make prod-logs - Показать логи production"
|
||||||
|
@echo ""
|
||||||
|
@echo "Celery (Production):"
|
||||||
|
@echo " make prod-worker-logs - Логи Celery worker"
|
||||||
|
@echo " make prod-beat-logs - Логи Celery beat"
|
||||||
|
@echo " make prod-celery-status - Статус Celery"
|
||||||
|
@echo " make prod-celery-test - Тест Celery подключения"
|
||||||
|
@echo ""
|
||||||
|
@echo "Django:"
|
||||||
@echo " make shell - Открыть Django shell"
|
@echo " make shell - Открыть Django shell"
|
||||||
@echo " make migrate - Выполнить миграции"
|
@echo " make migrate - Выполнить миграции"
|
||||||
@echo " make createsuperuser - Создать суперпользователя"
|
@echo " make createsuperuser - Создать суперпользователя"
|
||||||
@@ -97,3 +109,29 @@ status:
|
|||||||
|
|
||||||
prod-status:
|
prod-status:
|
||||||
docker-compose -f docker-compose.prod.yaml ps
|
docker-compose -f docker-compose.prod.yaml ps
|
||||||
|
|
||||||
|
# Celery команды для production
|
||||||
|
prod-worker-logs:
|
||||||
|
docker-compose -f docker-compose.prod.yaml logs -f worker
|
||||||
|
|
||||||
|
prod-beat-logs:
|
||||||
|
docker-compose -f docker-compose.prod.yaml logs -f beat
|
||||||
|
|
||||||
|
prod-celery-status:
|
||||||
|
docker-compose -f docker-compose.prod.yaml exec web uv run celery -A dbapp inspect active
|
||||||
|
|
||||||
|
prod-celery-test:
|
||||||
|
docker-compose -f docker-compose.prod.yaml exec web uv run python test_celery.py
|
||||||
|
|
||||||
|
prod-redis-test:
|
||||||
|
docker-compose -f docker-compose.prod.yaml exec web uv run python check_redis.py
|
||||||
|
|
||||||
|
# Celery команды для development
|
||||||
|
celery-status:
|
||||||
|
cd dbapp && uv run celery -A dbapp inspect active
|
||||||
|
|
||||||
|
celery-test:
|
||||||
|
cd dbapp && uv run python test_celery.py
|
||||||
|
|
||||||
|
redis-test:
|
||||||
|
cd dbapp && uv run python check_redis.py
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ COPY --from=builder /app /app
|
|||||||
ENV PYTHONUNBUFFERED=1 \
|
ENV PYTHONUNBUFFERED=1 \
|
||||||
PATH="/usr/local/bin:$PATH"
|
PATH="/usr/local/bin:$PATH"
|
||||||
|
|
||||||
# Делаем entrypoint.sh исполняемым
|
# Делаем entrypoint скрипты исполняемыми
|
||||||
RUN chmod +x /app/entrypoint.sh
|
RUN chmod +x /app/entrypoint.sh /app/entrypoint-celery.sh
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
|
|||||||
96
dbapp/check_redis.py
Normal file
96
dbapp/check_redis.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
Скрипт для проверки подключения к Redis.
|
||||||
|
Запуск: python check_redis.py
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
import redis
|
||||||
|
except ImportError:
|
||||||
|
print("❌ Redis библиотека не установлена")
|
||||||
|
print("Установите: pip install redis")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def check_redis():
|
||||||
|
"""Проверка подключения к Redis"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("ПРОВЕРКА REDIS")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Получаем URL из переменных окружения
|
||||||
|
broker_url = os.getenv("CELERY_BROKER_URL", "redis://localhost:6379/0")
|
||||||
|
cache_url = os.getenv("REDIS_URL", "redis://localhost:6379/1")
|
||||||
|
|
||||||
|
print(f"\n1. Broker URL: {broker_url}")
|
||||||
|
print(f"2. Cache URL: {cache_url}")
|
||||||
|
|
||||||
|
# Проверка broker (database 0)
|
||||||
|
print("\n3. Проверка Celery Broker (db 0)...")
|
||||||
|
try:
|
||||||
|
r_broker = redis.from_url(broker_url)
|
||||||
|
r_broker.ping()
|
||||||
|
print(" ✓ Подключение успешно")
|
||||||
|
|
||||||
|
# Проверка ключей
|
||||||
|
keys = r_broker.keys("*")
|
||||||
|
print(f" ✓ Ключей в базе: {len(keys)}")
|
||||||
|
|
||||||
|
# Проверка очереди celery
|
||||||
|
queue_length = r_broker.llen("celery")
|
||||||
|
print(f" ✓ Задач в очереди 'celery': {queue_length}")
|
||||||
|
|
||||||
|
except redis.ConnectionError as e:
|
||||||
|
print(f" ✗ Ошибка подключения: {e}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Ошибка: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Проверка cache (database 1)
|
||||||
|
print("\n4. Проверка Django Cache (db 1)...")
|
||||||
|
try:
|
||||||
|
r_cache = redis.from_url(cache_url)
|
||||||
|
r_cache.ping()
|
||||||
|
print(" ✓ Подключение успешно")
|
||||||
|
|
||||||
|
# Проверка ключей
|
||||||
|
keys = r_cache.keys("*")
|
||||||
|
print(f" ✓ Ключей в базе: {len(keys)}")
|
||||||
|
|
||||||
|
except redis.ConnectionError as e:
|
||||||
|
print(f" ✗ Ошибка подключения: {e}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Ошибка: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Тест записи/чтения
|
||||||
|
print("\n5. Тест записи/чтения...")
|
||||||
|
try:
|
||||||
|
test_key = "test:celery:connection"
|
||||||
|
test_value = "OK"
|
||||||
|
|
||||||
|
r_broker.set(test_key, test_value, ex=10) # TTL 10 секунд
|
||||||
|
result = r_broker.get(test_key)
|
||||||
|
|
||||||
|
if result and result.decode() == test_value:
|
||||||
|
print(f" ✓ Запись/чтение работает")
|
||||||
|
r_broker.delete(test_key)
|
||||||
|
else:
|
||||||
|
print(f" ✗ Ошибка: ожидалось '{test_value}', получено '{result}'")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Ошибка: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("✓ ВСЕ ПРОВЕРКИ ПРОЙДЕНЫ")
|
||||||
|
print("=" * 60)
|
||||||
|
return True
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
success = check_redis()
|
||||||
|
sys.exit(0 if success else 1)
|
||||||
@@ -160,5 +160,14 @@ LOGGING = {
|
|||||||
"level": "INFO",
|
"level": "INFO",
|
||||||
"propagate": False,
|
"propagate": False,
|
||||||
},
|
},
|
||||||
|
"celery.worker": {
|
||||||
|
"handlers": ["console", "celery_file"],
|
||||||
|
"level": "INFO",
|
||||||
|
"propagate": False,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Force Celery to log to stdout for Docker
|
||||||
|
CELERY_WORKER_REDIRECT_STDOUTS = True
|
||||||
|
CELERY_WORKER_REDIRECT_STDOUTS_LEVEL = "INFO"
|
||||||
|
|||||||
26
dbapp/entrypoint-celery.sh
Normal file
26
dbapp/entrypoint-celery.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "Starting Celery Worker..."
|
||||||
|
|
||||||
|
# Ждем PostgreSQL
|
||||||
|
echo "Waiting for PostgreSQL..."
|
||||||
|
until PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" -c '\q' 2>/dev/null; do
|
||||||
|
echo "PostgreSQL is unavailable - sleeping"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo "PostgreSQL started"
|
||||||
|
|
||||||
|
# Ждем Redis
|
||||||
|
echo "Waiting for Redis..."
|
||||||
|
until redis-cli -h redis ping 2>/dev/null; do
|
||||||
|
echo "Redis is unavailable - sleeping"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo "Redis started"
|
||||||
|
|
||||||
|
# Создаем директорию для логов
|
||||||
|
mkdir -p /app/logs
|
||||||
|
|
||||||
|
# Запускаем команду (celery worker или beat)
|
||||||
|
exec "$@"
|
||||||
68
dbapp/test_celery.py
Normal file
68
dbapp/test_celery.py
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
Скрипт для тестирования Celery подключения и задач.
|
||||||
|
Запуск: python test_celery.py
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import django
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dbapp.settings.production')
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
from celery import current_app
|
||||||
|
from dbapp.celery import debug_task
|
||||||
|
|
||||||
|
def test_celery_connection():
|
||||||
|
"""Проверка подключения к Celery"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("ТЕСТ CELERY ПОДКЛЮЧЕНИЯ")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Проверка конфигурации
|
||||||
|
print(f"\n1. Broker URL: {current_app.conf.broker_url}")
|
||||||
|
print(f"2. Result Backend: {current_app.conf.result_backend}")
|
||||||
|
|
||||||
|
# Проверка подключения к брокеру
|
||||||
|
try:
|
||||||
|
inspect = current_app.control.inspect()
|
||||||
|
stats = inspect.stats()
|
||||||
|
|
||||||
|
if stats:
|
||||||
|
print(f"\n3. ✓ Активные workers: {list(stats.keys())}")
|
||||||
|
for worker, info in stats.items():
|
||||||
|
print(f" - {worker}: {info}")
|
||||||
|
else:
|
||||||
|
print("\n3. ✗ Нет активных workers!")
|
||||||
|
print(" Убедитесь, что Celery worker запущен:")
|
||||||
|
print(" docker-compose -f docker-compose.prod.yaml logs worker")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n3. ✗ Ошибка подключения к брокеру: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Проверка зарегистрированных задач
|
||||||
|
registered_tasks = list(current_app.tasks.keys())
|
||||||
|
print(f"\n4. Зарегистрированные задачи ({len(registered_tasks)}):")
|
||||||
|
for task in sorted(registered_tasks):
|
||||||
|
if not task.startswith('celery.'):
|
||||||
|
print(f" - {task}")
|
||||||
|
|
||||||
|
# Тест простой задачи
|
||||||
|
print("\n5. Тестирование задачи...")
|
||||||
|
try:
|
||||||
|
result = debug_task.delay()
|
||||||
|
print(f" Task ID: {result.id}")
|
||||||
|
print(f" Waiting for result...")
|
||||||
|
output = result.get(timeout=10)
|
||||||
|
print(f" ✓ Результат: {output}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Ошибка выполнения задачи: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("✓ ВСЕ ТЕСТЫ ПРОЙДЕНЫ")
|
||||||
|
print("=" * 60)
|
||||||
|
return True
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_celery_connection()
|
||||||
@@ -21,14 +21,14 @@ services:
|
|||||||
image: https://registry.geraltserv.ru/geolocation:latest
|
image: https://registry.geraltserv.ru/geolocation:latest
|
||||||
env_file:
|
env_file:
|
||||||
- .env.prod
|
- .env.prod
|
||||||
#entrypoint: []
|
entrypoint: ["/app/entrypoint-celery.sh"]
|
||||||
command: ["uv", "run", "celery", "-A", "dbapp", "worker", "--loglevel=INFO"]
|
command: ["uv", "run", "celery", "-A", "dbapp", "worker", "--loglevel=INFO", "--concurrency=2"]
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
- redis
|
- redis
|
||||||
- web
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./logs:/app/logs
|
- ./logs:/app/logs
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:7-alpine
|
image: redis:7-alpine
|
||||||
|
|||||||
Reference in New Issue
Block a user