fix(parsers): close stale source jobs
This commit is contained in:
@@ -6,12 +6,14 @@ They are easily testable and can manage transactions.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
from typing import Any, Generic, TypeVar
|
||||
|
||||
import django
|
||||
from apps.core.exceptions import NotFoundError
|
||||
from django.db import models, transaction
|
||||
from django.db.models import QuerySet
|
||||
from django.db.models import Q, QuerySet
|
||||
from django.utils import timezone
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -678,3 +680,37 @@ class BackgroundJobService(BaseReadOnlyService):
|
||||
.delete()
|
||||
)
|
||||
return deleted
|
||||
|
||||
@classmethod
|
||||
def mark_stale_active_jobs_failed(
|
||||
cls,
|
||||
*,
|
||||
max_age_minutes: int,
|
||||
task_names: set[str] | None = None,
|
||||
meta_sources: set[str] | None = None,
|
||||
) -> int:
|
||||
"""Mark old active jobs as failed after worker restarts or hard kills."""
|
||||
from apps.core.models import JobStatus
|
||||
|
||||
cutoff = timezone.now() - timedelta(minutes=max_age_minutes)
|
||||
queryset = cls.get_queryset().filter(
|
||||
status__in=[JobStatus.PENDING, JobStatus.STARTED, JobStatus.RETRY],
|
||||
updated_at__lt=cutoff,
|
||||
)
|
||||
if task_names:
|
||||
queryset = queryset.filter(task_name__in=task_names)
|
||||
if meta_sources:
|
||||
source_filter = Q()
|
||||
for source in meta_sources:
|
||||
source_filter |= Q(meta__source=source)
|
||||
queryset = queryset.filter(source_filter)
|
||||
|
||||
stale_message = (
|
||||
"Stale background job was marked failed after "
|
||||
f"{max_age_minutes} minutes without progress."
|
||||
)
|
||||
updated = 0
|
||||
for job in queryset.order_by("created_at"):
|
||||
job.fail(error=stale_message)
|
||||
updated += 1
|
||||
return updated
|
||||
|
||||
Reference in New Issue
Block a user