feat(registries): add SME and budget imports and fix source API workflows
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

This commit is contained in:
Aleksandr Meshchryakov
2026-09-13 23:13:47 +02:00
parent c863563851
commit 49cbfd265c
50 changed files with 5021 additions and 452 deletions

View File

@@ -0,0 +1,80 @@
"""Real row-lock coverage for admission and asynchronous progress events."""
from concurrent.futures import ThreadPoolExecutor
from threading import Barrier
from unittest.mock import MagicMock
import pytest
from apps.core.exceptions import ConflictError
from apps.core.models import BackgroundJob
from apps.parsers.source_cards import SourceCardService
from django.db import close_old_connections, connection
pytestmark = pytest.mark.django_db(transaction=True)
def _parallel(actions):
barrier = Barrier(len(actions))
def run(action):
close_old_connections()
try:
barrier.wait(timeout=10)
return action()
finally:
close_old_connections()
with ThreadPoolExecutor(max_workers=len(actions)) as executor:
return list(executor.map(run, actions))
@pytest.mark.parametrize(
"slug,source",
[
("sme-support-recipients-registry", "fns_sme_support_recipients"),
("budget-process-registry", "budget_ubpandnubp"),
],
)
def test_two_simultaneous_refreshes_dispatch_exactly_one_task(slug, source):
if connection.vendor != "postgresql":
pytest.skip("Requires PostgreSQL row locks")
task = MagicMock()
definition = SourceCardService.get_definition(slug)
def refresh():
try:
SourceCardService._enqueue_refresh_group(
definition,
[(task, f"parsers.{source}.refresh", source)],
requested_by_id=None,
kwargs={},
)
return "queued"
except ConflictError:
return "conflict"
assert sorted(_parallel([refresh, refresh])) == ["conflict", "queued"]
assert task.apply_async.call_count == 1
assert BackgroundJob.objects.count() == 1
def test_concurrent_progress_preserves_maximum_and_terminal_result():
if connection.vendor != "postgresql":
pytest.skip("Requires PostgreSQL concurrent updates")
job = BackgroundJob.objects.create(
task_id="concurrent-progress", task_name="test.task"
)
def progress(value):
return lambda: BackgroundJob.objects.get(pk=job.pk).update_progress(value)
_parallel([progress(value) for value in [10, 85, 30, 55]])
job.refresh_from_db()
assert job.progress == 85
_parallel([lambda: job.fail("Source unavailable"), progress(25)])
job.refresh_from_db()
assert (job.status, job.progress, job.error) == (
"failure",
85,
"Source unavailable",
)