Пытаемся угомонить превьюшки
All checks were successful
Deploy MES Core / deploy (push) Successful in 10s
All checks were successful
Deploy MES Core / deploy (push) Successful in 10s
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
import sys
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import close_old_connections
|
||||
@@ -56,11 +58,25 @@ class Command(BaseCommand):
|
||||
job.started_at = timezone.now()
|
||||
job.finished_at = None
|
||||
job.last_message = ""
|
||||
job.save(update_fields=["status", "started_at", "finished_at", "last_message"])
|
||||
try:
|
||||
job.pid = os.getpid()
|
||||
job.save(update_fields=["status", "started_at", "finished_at", "last_message", "pid"])
|
||||
except Exception:
|
||||
job.save(update_fields=["status", "started_at", "finished_at", "last_message"])
|
||||
|
||||
logger = logging.getLogger('dxf_preview_job')
|
||||
if not logger.handlers:
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s', '%Y-%m-%d %H:%M:%S'))
|
||||
logger.addHandler(handler)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
logger.info('start job=%s pid=%s', job_id, os.getpid())
|
||||
|
||||
# Берём настройки таймаута из БД.
|
||||
settings, _ = DxfPreviewSettings.objects.get_or_create(pk=1)
|
||||
per_task_timeout = int(getattr(settings, 'per_task_timeout_sec', 45) or 45)
|
||||
per_task_timeout = max(10, min(50, per_task_timeout))
|
||||
|
||||
deal_statuses = ["lead", "work"]
|
||||
qs = ProductionTask.objects.select_related("deal").filter(deal__status__in=deal_statuses)
|
||||
@@ -79,9 +95,7 @@ class Command(BaseCommand):
|
||||
skipped = 0
|
||||
errors = 0
|
||||
|
||||
# Таймаут обработки одной детали (сек).
|
||||
# Если конкретный DXF «залип» — задача не должна блокироваться навсегда.
|
||||
per_task_timeout = 45
|
||||
logger.info('per_task_timeout=%ss', per_task_timeout)
|
||||
|
||||
try:
|
||||
for task in qs.iterator(chunk_size=50):
|
||||
@@ -106,7 +120,8 @@ class Command(BaseCommand):
|
||||
return
|
||||
|
||||
# Обрабатываем одну деталь в отдельном процессе и ждём не больше per_task_timeout.
|
||||
close_old_connections()
|
||||
# Важно: НЕ вызываем close_old_connections() внутри qs.iterator(), иначе Django может закрыть курсор,
|
||||
# и итерация по QuerySet упадёт с ошибкой "cursor already closed".
|
||||
q: multiprocessing.Queue = multiprocessing.Queue(maxsize=1)
|
||||
p = multiprocessing.Process(target=_run_one_task_preview, args=(task.id, q))
|
||||
p.start()
|
||||
@@ -137,8 +152,7 @@ class Command(BaseCommand):
|
||||
skipped += 1
|
||||
else:
|
||||
errors += 1
|
||||
|
||||
close_old_connections()
|
||||
logger.error('error task=%s name=%s deal=%s: %s', task.id, task.drawing_name, task.deal.number, payload)
|
||||
|
||||
DxfPreviewJob.objects.filter(pk=job_id).update(
|
||||
processed=processed,
|
||||
@@ -153,10 +167,11 @@ class Command(BaseCommand):
|
||||
last_message=f"Готово. Обновлены: {updated}. Пропущено: {skipped}. Ошибок: {errors}.",
|
||||
)
|
||||
except Exception:
|
||||
logger.exception('fatal error')
|
||||
DxfPreviewJob.objects.filter(pk=job_id).update(
|
||||
status="failed",
|
||||
finished_at=timezone.now(),
|
||||
last_message="Задача завершилась с ошибкой (см. логи процесса).",
|
||||
last_message="Задача завершилась с ошибкой (см. лог на странице обслуживания).",
|
||||
)
|
||||
finally:
|
||||
close_old_connections()
|
||||
Reference in New Issue
Block a user