Я пытаюсь запустить бесконечный рабочий поток (демон) изнутри Django - PullRequest
1 голос
/ 09 июля 2019

У меня есть рабочий поток, единственная задача которого - запрашивать список активных пользователей каждые 10 минут из базы данных и отправлять им SMS-сообщения, если выполняется определенное условие (которое проверяется каждую минуту); также рабочий поток вообще не мешает основному приложению.

Пока мне удалось настроить поток и запустить его, и отправка SMS тоже работает отлично. Однако, по некоторым причинам поток останавливается / убивается через некоторое случайное время (часы). Я запускаю попытку: за исключением исключения как e: в течение некоторого времени True, чтобы отловить возникающие ошибки. Кроме того, я печатаю сообщения о том, какая ошибка произошла.

Ну, я никогда не вижу сообщений, и поток определенно не работает. Поэтому я подозреваю, что Ганикорн или Джанго грациозно убили мою нить.

Я поместил выражения log и print по всему коду, но не нашел ничего, что указывало бы на то, что мой поток был убит.

Моя функция wsgi.py, где я вызываю функцию для запуска моей темы

"""
WSGI config for django_web project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application


os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_web.settings')

application = get_wsgi_application()

'''
Start background services
Import has to happen after "get_wsgi_application()"; otherwise docker container crashes
'''
try:
    from threading import Thread
    from timesheet.admin import runWorkmateServices

    runWorkmateServices()

except Exception as exp:
    print(exp)

Функция, которая вызывается из wsgi.py. Я дважды проверяю, был ли запущен поток, чтобы избежать запуска и запуска двух.

def runWorkmateServices(request=None):
    service_name = 'TimeKeeperWorkMateReminderService'

    thread_found = False
    for thread in threading.enumerate():
        if service_name in thread.name:
            thread_found = True
            break  # Leave loop now

    if thread_found:
        print(f'Service has already been started: {service_name}')
        if request:
            messages.add_message(request, messages.ERROR, f'Service has already been started:: {service_name}')
    else:
        Thread(target=WorkMateReminders, args=(), name=service_name, daemon=True).start()
        print(f'Started Service: {service_name}')
        if request:
            messages.add_message(request, messages.SUCCESS, f'Started Service: {service_name}')

Сам рабочий поток

def WorkMateReminders():
    print('Thread Started: WorkMateReminders')
    timer = 0
    employees = User.objects.none()

    while True:

        try:
            # Update user list every n * sleep time (10 minutes)
            if timer % 10 == 0:
                timer = 0
                # Get active employees
                employees = User.objects.filter(is_active=True, profile__workmate_sms_reminders_activated=True)
                print(f'Employees updated at {datetime.now().date()} - {datetime.now().time()}: {employees}')

            WorkMateCheckClockOffTimes(employees=employees)

            WorkMateClockOnReminder(employees=employees)

            WorkMateEndOfBreakReminder(employees=employees)

            timer += 1  # increment timer

        except Exception as exp:
            print(f'Error: {exp}')

        time.sleep(60 * 1)

Моя цель - запустить этот рабочий поток, пока работает Django.

1 Ответ

1 голос
/ 09 июля 2019

Большинство серверов WSGI порождают рабочих, которых регулярно убивают / перерабатывают, порождая потоки этих работников, не лучшее решение вашей проблемы. Есть несколько способов сделать это

Крон

Создайте команду управления , которая делает то, что вам нужно, и настройте cron для запуска каждые 10 минут

Сельдерей / Celerybeat

Настройка celery worker. Это процесс, который асинхронно запускается в вашем приложении Django, и с помощью celerybeat вы можете запускать задачи с интервалами

...