Как предотвратить повторный вызов представления Django, несмотря на длительное время выполнения?

У меня есть представление Django, которое запускает подпроцесс и возвращает JsonResponse обратно пользователю:

def process_images(request, id):
    log.debug("Processing images view...")
    start = perf_counter()
    result = subprocess.run(["ssh", "<REMOTE SERVER>", "bash", "process_images.sh"],
        capture_output = True,
        text = True) # Run backend processing
        
    log.debug("Result stdout:\n" + result.stdout)
    
    with open(f"{settings.MEDIA_ROOT}/{id}/image.json", "r") as f:
        response_data = json.load(f)
        
    time_took = perf_counter() - start
    log.debug(f"View time took {time_took} seconds")
    return JsonResponse(response_data, status=201)

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('<id>/process', views.process_images, name='process'),
    path('<id>/', views.model, name='model')
]

app_name = "render"

Однако когда я пытаюсь получить доступ к render/ID/process ONCE, меня встречает:

[Oct 25, 2022 07:30:13 PM] DEBUG [render.views:49] Processing images view...
[Oct 25, 2022 07:31:24 PM] DEBUG [render.views:55] Result stdout:
Backend processing...

[Oct 25, 2022 07:31:24 PM] DEBUG [render.views:61] View time took 70.49786422774196 seconds
[Oct 25, 2022 07:31:24 PM] DEBUG [render.views:49] Processing images view...
[Oct 25, 2022 07:32:16 PM] DEBUG [render.views:55] Result stdout:
Backend processing...
[Oct 25, 2022 07:32:16 PM] DEBUG [render.views:61] View time took 52.54661420173943 seconds
[Oct 25, 2022 07:32:16 PM] DEBUG [render.views:49] Processing images view...
[Oct 25, 2022 07:33:08 PM] DEBUG [render.views:55] Result stdout:
Backend processing...

[Oct 25, 2022 07:33:08 PM] DEBUG [render.views:61] View time took 51.900153297930956 seconds

прежде чем он наконец вернет ожидаемый JsonResponse (показывающий, что представление было вызвано несколько раз).

Однако, если я уменьшу обработку бэкенда так, чтобы она стала намного быстрее, а затем снова обращусь к нему, я получу только следующий результат:

[Oct 25, 2022 07:42:41 PM] DEBUG [render.views:49] Processing images view...
[Oct 25, 2022 07:42:44 PM] DEBUG [render.views:55] Result stdout:
Backend processing...

[Oct 25, 2022 07:42:44 PM] DEBUG [render.views:61] View time took 3.0603290796279907 seconds

где он вызывается только один раз (как и ожидалось), и с соответствующим JsonResponse.

Вопрос: Как сделать так, чтобы представление вызывалось только один раз, несмотря на большое время выполнения?

  • Я бы не хотел использовать Celery или любые другие библиотеки/планировщики для помощи в работе с автономными/асинхронными представлениями

Я посмотрел этот вопрос, но единственный ответ на него специфичен для этого вопроса.

Хотя я не понимаю источник этой ошибки, я смог избежать ее, используя subprocess.Popen, а не subprocess.run, чтобы запустить ее в фоновом режиме и немедленно вернуть представление (избегая длительного времени выполнения):

def process_images(request, id):
    result = subprocess.Popen(["ssh", "<REMOTE SERVER>",
                               "bash", "process_images.sh"]) # UPDATED LINE   
        
    return JsonResponse({}, status=201)

Затем я использовал ajax-запросы, чтобы проверить, завершилась ли обработка бэкенда, и возвращал результаты туда.

Вернуться на верх