Как предотвратить повторный вызов представления 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-запросы, чтобы проверить, завершилась ли обработка бэкенда, и возвращал результаты туда.