fix(parsers): close stale source jobs
Some checks failed
CI/CD Pipeline / Quality Gate (push) Failing after 2m4s
CI/CD Pipeline / Build and Push Images (push) Has been skipped
CI/CD Pipeline / Deploy Dev in Dokploy (push) Has been skipped
CI/CD Pipeline / Internal Notify (push) Successful in 1s

This commit is contained in:
2026-04-28 21:38:00 +02:00
parent 26f0669670
commit d96b76d32f
9 changed files with 262 additions and 18 deletions

View File

@@ -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