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

@@ -411,6 +411,31 @@ class ParserLoadLogServiceTest(TestCase):
self.assertEqual(updated, 0)
self.assertEqual(log.status, ParserLoadLog.Status.IN_PROGRESS)
def test_mark_stale_in_progress_failed_closes_precreated_job_without_batch(self):
"""Pre-created source-card jobs without batch_id are still linked by source."""
log = ParserLoadLogFactory(
source=ParserLoadLog.Source.INDUSTRIAL_PRODUCTS,
batch_id=2,
status=ParserLoadLog.Status.IN_PROGRESS,
)
job = BackgroundJob.objects.create(
task_id="precreated-source-card-task",
task_name="apps.parsers.tasks.parse_industrial_products",
status=JobStatus.STARTED,
meta={"source": log.source, "source_card": "manufacturers-and-products"},
)
old_timestamp = timezone.now() - timedelta(hours=3)
ParserLoadLog.objects.filter(pk=log.pk).update(updated_at=old_timestamp)
BackgroundJob.objects.filter(pk=job.pk).update(updated_at=old_timestamp)
updated = ParserLoadLogService.mark_stale_in_progress_failed(max_age_minutes=90)
log.refresh_from_db()
job.refresh_from_db()
self.assertEqual(updated, 1)
self.assertEqual(log.status, ParserLoadLog.Status.FAILED)
self.assertEqual(job.status, JobStatus.FAILURE)
class IndustrialCertificateServiceTest(TestCase):
"""Tests for IndustrialCertificateService."""

View File

@@ -1,5 +1,6 @@
from __future__ import annotations
from datetime import timedelta
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
@@ -10,6 +11,7 @@ from apps.parsers.source_cards import (
)
from django.http import Http404
from django.test import SimpleTestCase
from django.utils import timezone
from rest_framework.exceptions import ValidationError
@@ -249,6 +251,19 @@ class SourceCardServiceUnitTest(SimpleTestCase):
),
"in_progress",
)
stale_in_progress_load = SimpleNamespace(
status="in_progress",
updated_at=timezone.now() - timedelta(hours=3),
)
self.assertEqual(
SourceCardService._get_status(
definition=SourceCardService.get_definition("financial-indicators"),
active_tasks=[],
latest_load=stale_in_progress_load,
last_updated_at=None,
),
"error",
)
self.assertEqual(
SourceCardService._get_status(
definition=SourceCardService.get_definition("financial-indicators"),

View File

@@ -12,6 +12,7 @@ from types import SimpleNamespace
from unittest.mock import patch
from urllib.parse import urlparse
from apps.core.services import BackgroundJobService
from apps.parsers import tasks as parser_tasks
from apps.parsers.clients.base import HTTPError
from apps.parsers.clients.minpromtorg.industrial import (
@@ -285,14 +286,46 @@ class GenericSourceFetchTestCase(TestCase):
ParserLoadLogService,
"mark_stale_in_progress_failed",
return_value=2,
) as cleanup_mock:
) as cleanup_mock, patch.object(
BackgroundJobService,
"mark_stale_active_jobs_failed",
return_value=3,
) as jobs_cleanup_mock:
result = parser_tasks.cleanup_stale_parser_loads(max_age_minutes=45)
cleanup_mock.assert_called_once_with(max_age_minutes=45)
jobs_cleanup_mock.assert_called_once()
self.assertEqual(jobs_cleanup_mock.call_args.kwargs["max_age_minutes"], 45)
self.assertEqual(result["status"], "success")
self.assertEqual(result["marked_failed"], 2)
self.assertEqual(result["marked_jobs_failed"], 3)
self.assertEqual(result["max_age_minutes"], 45)
def test_get_or_create_background_job_merges_meta_for_precreated_job(self):
BackgroundJobService.create_job(
task_id="precreated-task",
task_name="apps.parsers.tasks.parse_industrial_products",
user_id=None,
meta={
"source": ParserLoadLog.Source.INDUSTRIAL_PRODUCTS,
"source_card": "manufacturers-and-products",
},
)
job = parser_tasks._get_or_create_background_job(
task_id="precreated-task",
task_name="apps.parsers.tasks.parse_industrial_products",
source=ParserLoadLog.Source.INDUSTRIAL_PRODUCTS,
batch_id=7,
requested_by_id=42,
meta={"source_key": "mpt_products"},
)
self.assertEqual(job.user_id, 42)
self.assertEqual(job.meta["source_card"], "manufacturers-and-products")
self.assertEqual(job.meta["source_key"], "mpt_products")
self.assertEqual(job.meta["batch_id"], 7)
@override_settings(
CELERY_TASK_ALWAYS_EAGER=True,