Проблема с redis/celery, почему некоторые задачи вызывают Errno 111, а другие нет?
В настоящее время я создаю веб-приложение на django. Я использую redis и celery для отправки электронных писем для различных целей. У меня есть фоновый рабочий, который проверяет мою базу данных на наличие писем для отправки каждые 5 с (очень коротко для целей тестирования), если он находит письма, помеченные как неотправленные, то он отправляет их, эта часть работает как положено. Однако когда я вызываю тот же метод непосредственно из одного из моих представлений (чтобы отправить письмо для создания учетной записи), у меня возникает ошибка Errno 111.
Вот мой файл celery.py:
import os
from celery import Celery
from celery.signals import after_setup_logger
import logging.config
from inscriptionsIff import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'inscriptionsIff.settings')
app = Celery('inscriptionsIff')
app.config_from_object('django.conf:settings', namespace='CELERY')
@after_setup_logger.connect
def setup_loggers(logger, *args, **kwargs):
logging.config.dictConfig(settings.LOGGING)
app.conf.beat_schedule = {
'send-emails-every-x-seconds': {
'task': 'inscriptionsIff.tasks.process_and_send_emails',
'schedule': 5, # Replace 'x' with the number of seconds
},
}
app.autodiscover_tasks()
Вот мой файл tasks.py:
from celery import shared_task
from django.core.mail import send_mail
from .models import Submission
from django.urls import reverse
from django.contrib.sites.shortcuts import get_current_site
import hashlib
from django.conf import settings
@shared_task
def send_email_task(email, subject, message):
send_mail(
subject,
message,
'yourgmailaddress@gmail.com',
[email],
fail_silently=False,
)
def hash_input(input_to_hash):
# Use Django's SECRET_KEY to add a layer of unpredictability to the hash
salted_id = str(input_to_hash) + settings.SECRET_KEY
return hashlib.sha256(salted_id.encode()).hexdigest()
@shared_task
def process_and_send_emails():
# Get the current site domain for constructing absolute URLs
# current_site = get_current_site(None)
for record in Submission.objects.filter(mail_sent=False).only('email', 'id').iterator():
# Generate the hashed ID
submission_hash = hash_input(record.id)
# Build the absolute confirmation URL
path = reverse('confirm-reception', kwargs={'submission_hash': submission_hash})
confirm_url = f'http://127.0.0.1:8080{path}'
# Construct the email message with the confirmation link
message = f'TEST : \n{confirm_url}'
# Send the email
send_email_task.delay(
email=record.email,
subject='Journée de formation SNCF & Moi',
message=message,
)
# Mark the email as sent
record.mail_sent = True
record.save(update_fields=['mail_sent'])
И наконец, вот представление, которое создает моего пользователя:
@csrf_exempt
def create_super_user(request):
if request.method == 'POST':
email = request.POST.get('email')
password = request.POST.get('password')
if not email or not password:
return HttpResponse('Email and password are required.', status=400)
if CustomUser.objects.filter(email=email).exists():
return HttpResponse('A user with this email already exists.', status=400)
# Create the Account instance first
account = Account.objects.create()
super_user = CustomUser.objects.create_user(
email=email,
password=password,
is_superuser=True,
is_active=True,
account_id=account.id,
)
confirmation_hash = hash_input(email)
path = reverse('verify_email', kwargs={'confirmation_hash': confirmation_hash})
confirm_url = f'http://127.0.0.1:8080{path}'
send_email_task.delay(email=email, message=confirm_url, subject='Test')
return HttpResponse('Super user and account created successfully.')
else:
return render(request, 'account_creation.html')
После тестирования я уверен, что ошибку вызывает send_email_task.delay внутри представления, но не понимаю, почему, ведь фоновая почтовая задача работает совершенно нормально.
Мой url брокера определен следующим образом:
CELERY_BROKER_URL = 'redis://localhost:6379/0'
Вот полный журнал ошибок :
Я запускаю свое приложение с помощью следующего сценария оболочки :
#!/bin/bash
# Function to stop all background processes
cleanup() {
echo "Stopping Django development server..."
kill $DJANGO_PID
echo "Stopping Celery worker..."
kill $CELERY_WORKER_PID
echo "Stopping Celery Beat..."
kill $CELERY_BEAT_PID
echo "Stopping Redis server..."
redis-cli shutdown
}
# Trap SIGINT (Ctrl+C) and SIGTERM signals to cleanup before exiting
trap cleanup SIGINT SIGTERM
# Start Redis server in the background
echo "Starting Redis server..."
redis-server &
# Start Django development server in the background and save its PID
echo "Starting Django development server..."
python manage.py runserver 8080 &
DJANGO_PID=$!
# Start Celery worker in the background and save its PID
echo "Starting Celery worker..."
celery -A inscriptionsIff worker --loglevel=info &
CELERY_WORKER_PID=$!
# Start Celery Beat in the background and save its PID
echo "Starting Celery Beat..."
celery -A inscriptionsIff beat --loglevel=info &
CELERY_BEAT_PID=$!
# Wait for all background processes to finish
wait $DJANGO_PID $CELERY_WORKER_PID $CELERY_BEAT_PID
Это полная
загадка, я проверил, что сервер redis отвечает правильно после запуска приложения, как и фоновая служба отправки почты работает правильно, я понятия не имею, почему вызов этой задачи из одного из моих представлений вызывает такую ошибку. Есть ли у кого-нибудь идеи?