Andrey Epifancev e8453159e8 Срез 0 [7.1]: горячие папки — набор *.json ответа, готовность по settle, служебный каталог Tmp
- HotFolder.poll(job_id) -> list[AnswerFile] | None: все *.json каталога <output>/<job_id>/ по возрастанию
  имени, когда набор не пуст и имена/размеры не менялись SCAN_SETTLE_SECONDS (SettleTracker: состояние по
  job_id, внедряемые часы, сброс при выдаче/опустении, предел 1024 задания, потокобезопасно);
- put: временный .<name>.part в <корень>/<SCAN_TMP_DIR>/ (создаётся), rename в Input (Local и SMB);
- настройки SCAN_TMP_DIR (Tmp) и SCAN_SETTLE_SECONDS (2, >= 0); в .env.test settle = 0 (R-23);
- воркер: переходная прослойка — берётся первый файл набора (склейка всех — Task 3, R-22).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 14:01:39 +04:00

85 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Фикстуры unit-тестов: окружение воркера шлюза `make_env` (обвязка — `tests/worker_helpers.py`)."""
import json
from collections.abc import AsyncIterator, Awaitable, Callable
from datetime import datetime
from pathlib import Path
from typing import Any
import pytest
from src.core.config import get_settings
from src.core.nats import NatsGateway
from src.core.worker import Worker
from src.gateway.hotfolder import LocalHotFolder
from src.normalizer import NullNormalizer
from tests.worker_helpers import SUCCESS_ANSWER, Env, EnvFactory, FakeNatsClient, FakeStorage, SpyHotFolder
@pytest.fixture
async def make_env(tmp_path: Path) -> AsyncIterator[EnvFactory]:
"""Фабрика окружений воркера на `tmp_path`: настройки — `get_settings()` с короткими опросом и тайм-аутом
(`**overrides` — поверх), подмены `normalizer`, `clock`, `sleep` (пауза между опросами горячей папки).
Воркер запущен (`start()`); после теста все созданные воркеры останавливаются.
"""
created: list[Env] = []
async def build(
*,
normalizer: Any = None,
root_exists: bool = True,
clock: Callable[[], datetime] | None = None,
sleep: Callable[[float], Awaitable[None]] | None = None,
**overrides: Any,
) -> Env:
root = tmp_path / f"hotfolder-{len(created)}"
if root_exists:
root.mkdir()
fixtures = tmp_path / "fixtures"
fixtures.mkdir(exist_ok=True)
(fixtures / "ok_doc.json").write_text(json.dumps(SUCCESS_ANSWER, ensure_ascii=False), encoding="utf-8")
settings = get_settings().model_copy(
update={
"SCAN_HOTFOLDER_PATH": str(root),
"SCAN_POLL_SECONDS": 0.01,
"SCAN_TIMEOUT_SECONDS": 5,
"SCAN_SETTLE_SECONDS": 0, # R-23: набор ответа готов сразу, тесты не ждут стабилизации
"PUBLISH_RETRIES": 1,
**overrides,
}
)
events: list[tuple[str, str]] = []
storage = FakeStorage(events)
client = FakeNatsClient(events)
gateway = NatsGateway(settings, client_factory=lambda: client, retry_delay=0)
await gateway.connect()
local = LocalHotFolder(
root,
settings.SCAN_INPUT_DIR,
settings.SCAN_OUTPUT_DIR,
settings.SCAN_TMP_DIR,
settle_seconds=settings.SCAN_SETTLE_SECONDS,
)
hotfolder = SpyHotFolder(local, events)
kwargs: dict[str, Any] = {}
if clock is not None:
kwargs["clock"] = clock
if sleep is not None:
kwargs["sleep"] = sleep
worker = Worker(
settings,
storage=storage,
publisher=gateway,
hotfolder=hotfolder,
normalizer=normalizer or NullNormalizer(),
**kwargs,
)
worker.start()
env = Env(settings, root, fixtures, events, storage, client, gateway, hotfolder, worker)
created.append(env)
return env
yield build
for env in created:
await env.worker.stop()