Files
mostovik-backend/tests/apps/parsers/test_vacancy_progress_race.py
Aleksandr Meshchryakov 49cbfd265c
All checks were successful
Mostovik Backend CI/CD / Tests and lint (push) Successful in 9m37s
Mostovik Backend CI/CD / Build linux/amd64 release images (push) Successful in 4m18s
Mostovik Backend CI/CD / Deploy and verify internal main (push) Has been skipped
Mostovik Backend CI/CD / Deploy customer main (push) Has been skipped
Mostovik Backend CI/CD / Deploy dev (push) Successful in 1m48s
feat(registries): add SME and budget imports and fix source API workflows
2026-09-13 23:13:47 +02:00

114 lines
3.4 KiB
Python

"""Запоздалые контрольные точки вакансий не меняют актуальное состояние задачи."""
from unittest.mock import patch
import pytest
from apps.core.models import BackgroundJob
from apps.parsers.models import ParserLoadLog
from apps.parsers.tasks import (
_find_resumable_vacancy_job,
_update_vacancy_registry_checkpoint,
)
def _checkpoint(job, load_log, *, processed):
with patch("apps.parsers.tasks._vacancy_batch_records_count", return_value=17):
return _update_vacancy_registry_checkpoint(
job=job,
load_log=load_log,
batch_id=load_log.batch_id,
processed=processed,
total=100,
failed=0,
targets_signature="test-targets",
)
@pytest.fixture
def vacancy_run(db):
job = BackgroundJob.objects.create(
task_id="vacancy-checkpoint",
task_name="apps.parsers.tasks.parse_trudvsem_vacancies",
meta={"source_card": "labor-vacancies"},
)
load_log = ParserLoadLog.objects.create(
source=ParserLoadLog.Source.TRUDVSEM,
batch_id=1,
status=ParserLoadLog.Status.IN_PROGRESS,
)
return job, load_log
def test_lower_stale_vacancy_checkpoint_preserves_progress_message_and_meta(
vacancy_run,
):
job, load_log = vacancy_run
stale = BackgroundJob.objects.get(pk=job.pk)
assert _checkpoint(job, load_log, processed=75) == 17
expected = (job.progress, job.progress_message, job.meta)
assert _checkpoint(stale, load_log, processed=25) == 17
job.refresh_from_db()
assert (job.progress, job.progress_message, job.meta) == expected
assert job.meta["next_offset"] == 75
assert job.meta["source_card"] == "labor-vacancies"
load_log.refresh_from_db()
assert load_log.records_count == 17
assert load_log.status == ParserLoadLog.Status.IN_PROGRESS
@pytest.mark.parametrize("terminal", ["complete", "fail", "revoke"])
def test_terminal_vacancy_job_ignores_late_checkpoint(vacancy_run, terminal):
job, load_log = vacancy_run
_checkpoint(job, load_log, processed=65)
stale = BackgroundJob.objects.get(pk=job.pk)
if terminal == "fail":
job.fail("Ошибка источника")
else:
getattr(job, terminal)()
expected = (
job.status,
job.progress,
job.progress_message,
job.meta,
job.completed_at,
)
assert _checkpoint(stale, load_log, processed=90) == 17
job.refresh_from_db()
assert (
job.status,
job.progress,
job.progress_message,
job.meta,
job.completed_at,
) == expected
@pytest.mark.parametrize("saved_records", [0, 17])
def test_zero_cursor_resumes_only_when_batch_has_saved_records(
vacancy_run, saved_records
):
job, load_log = vacancy_run
job.meta.update(
batch_id=load_log.batch_id,
next_offset=0,
total_organizations=100,
targets_signature="test-targets",
)
job.save(update_fields=["meta"])
job.revoke()
with patch(
"apps.parsers.tasks._vacancy_batch_records_count", return_value=saved_records
):
result = _find_resumable_vacancy_job(
exclude_task_id="new-run",
targets_signature="test-targets",
targets_count=100,
)
assert result == ((job, load_log) if saved_records else (None, None))