kin: BATON-ARCH-013 Добавить keep-alive механизм для предотвращения cold start

This commit is contained in:
Gros Frumos 2026-03-20 21:14:32 +02:00
parent 5435d2006f
commit 12abac74f0
3 changed files with 837 additions and 0 deletions

173
tests/test_arch_004.py Normal file
View file

@ -0,0 +1,173 @@
"""
Tests for BATON-ARCH-004: Переименование ADR-002-offline-pattern.md.
Acceptance criteria:
1. No file named ADR-002-offline-pattern*.md exists in docs/adr/.
2. No references to 'ADR-002-offline-pattern' anywhere in docs/ and ARCHITECTURE.md.
3. No dangling bare 'ADR-002' references in docs/, ARCHITECTURE.md, or tests/.
4. ADR-007-offline-queue-v2.md exists in docs/adr/.
5. tech_report.md references ADR-007 (not ADR-002).
6. ADR-006 references ADR-007 (not ADR-002).
7. ARCHITECTURE.md references ADR-007 (not ADR-002) for offline-related rows.
"""
from __future__ import annotations
import re
from pathlib import Path
PROJECT_ROOT = Path(__file__).parent.parent
ADR_DIR = PROJECT_ROOT / "docs" / "adr"
ARCHITECTURE_MD = PROJECT_ROOT / "ARCHITECTURE.md"
TECH_REPORT_MD = PROJECT_ROOT / "docs" / "tech_report.md"
ADR_006 = ADR_DIR / "ADR-006-offline-ios-constraints.md"
ADR_007 = ADR_DIR / "ADR-007-offline-queue-v2.md"
# ---------------------------------------------------------------------------
# Criterion 1 — old ADR-002-offline-pattern file must not exist
# ---------------------------------------------------------------------------
def test_adr_002_offline_pattern_file_does_not_exist() -> None:
"""Файл ADR-002-offline-pattern*.md не должен существовать в docs/adr/."""
matches = list(ADR_DIR.glob("ADR-002-offline-pattern*.md"))
assert len(matches) == 0, (
f"Старый файл ADR-002-offline-pattern найден: {matches}"
)
# ---------------------------------------------------------------------------
# Criterion 2 — no 'ADR-002-offline-pattern' textual references
# ---------------------------------------------------------------------------
def _all_md_in_docs() -> list[Path]:
return list((PROJECT_ROOT / "docs").rglob("*.md"))
def test_no_adr_002_offline_pattern_in_docs() -> None:
"""Ни один файл в docs/ не должен содержать строку 'ADR-002-offline-pattern'."""
for path in _all_md_in_docs():
content = path.read_text(encoding="utf-8")
assert "ADR-002-offline-pattern" not in content, (
f"Найдена устаревшая ссылка 'ADR-002-offline-pattern' в {path.relative_to(PROJECT_ROOT)}"
)
def test_no_adr_002_offline_pattern_in_architecture_md() -> None:
"""ARCHITECTURE.md не должен содержать строку 'ADR-002-offline-pattern'."""
content = ARCHITECTURE_MD.read_text(encoding="utf-8")
assert "ADR-002-offline-pattern" not in content, (
"Найдена устаревшая ссылка 'ADR-002-offline-pattern' в ARCHITECTURE.md"
)
# ---------------------------------------------------------------------------
# Criterion 3 — no dangling bare ADR-002 references
# ---------------------------------------------------------------------------
def test_no_bare_adr_002_in_docs() -> None:
"""Ни один файл в docs/ не должен содержать голую метку 'ADR-002' (без корректного имени файла)."""
pattern = re.compile(r"\bADR-002\b")
for path in _all_md_in_docs():
content = path.read_text(encoding="utf-8")
assert not pattern.search(content), (
f"Найдена висячая ссылка 'ADR-002' в {path.relative_to(PROJECT_ROOT)}"
)
def test_no_bare_adr_002_in_architecture_md() -> None:
"""ARCHITECTURE.md не должен содержать голую метку 'ADR-002'."""
content = ARCHITECTURE_MD.read_text(encoding="utf-8")
assert not re.search(r"\bADR-002\b", content), (
"Найдена висячая ссылка 'ADR-002' в ARCHITECTURE.md"
)
def test_no_bare_adr_002_in_tests() -> None:
"""Файлы тестов (кроме этого самого файла) не должны содержать голую метку 'ADR-002'."""
pattern = re.compile(r"\bADR-002\b")
this_file = Path(__file__).resolve()
for path in (PROJECT_ROOT / "tests").glob("*.py"):
if path.resolve() == this_file:
continue # этот файл документирует задачу и легитимно упоминает ADR-002
content = path.read_text(encoding="utf-8")
assert not pattern.search(content), (
f"Найдена висячая ссылка 'ADR-002' в {path.relative_to(PROJECT_ROOT)}"
)
# ---------------------------------------------------------------------------
# Criterion 4 — ADR-007-offline-queue-v2.md exists
# ---------------------------------------------------------------------------
def test_adr_007_offline_queue_file_exists() -> None:
"""Файл ADR-007-offline-queue-v2.md должен существовать в docs/adr/."""
assert ADR_007.is_file(), (
f"Переименованный файл ADR-007-offline-queue-v2.md не найден в {ADR_DIR}"
)
# ---------------------------------------------------------------------------
# Criterion 5 — tech_report.md references ADR-007
# ---------------------------------------------------------------------------
def test_tech_report_references_adr_007() -> None:
"""docs/tech_report.md должен содержать ссылку на ADR-007."""
content = TECH_REPORT_MD.read_text(encoding="utf-8")
assert "ADR-007" in content, (
"tech_report.md не ссылается на ADR-007 (переименованный offline-pattern)"
)
# ---------------------------------------------------------------------------
# Criterion 6 — ADR-006 references ADR-007 (not ADR-002)
# ---------------------------------------------------------------------------
def test_adr_006_references_adr_007() -> None:
"""ADR-006-offline-ios-constraints.md должен ссылаться на ADR-007."""
content = ADR_006.read_text(encoding="utf-8")
assert "ADR-007" in content, (
"ADR-006 не содержит ссылки на ADR-007"
)
def test_adr_006_has_no_adr_002_references() -> None:
"""ADR-006-offline-ios-constraints.md не должен ссылаться на ADR-002."""
content = ADR_006.read_text(encoding="utf-8")
assert not re.search(r"\bADR-002\b", content), (
"ADR-006 всё ещё содержит ссылку 'ADR-002'"
)
# ---------------------------------------------------------------------------
# Criterion 7 — ARCHITECTURE.md references ADR-007 for offline rows
# ---------------------------------------------------------------------------
def test_architecture_md_references_adr_007_for_service_worker() -> None:
"""ARCHITECTURE.md должен ссылаться на ADR-007 в строке Service Worker."""
content = ARCHITECTURE_MD.read_text(encoding="utf-8")
sw_line = next(
(line for line in content.splitlines() if "Service Worker" in line), None
)
assert sw_line is not None, "Строка 'Service Worker' не найдена в ARCHITECTURE.md"
assert "ADR-007" in sw_line, (
f"Строка Service Worker в ARCHITECTURE.md не содержит ADR-007: {sw_line!r}"
)
def test_architecture_md_references_adr_007_for_offline() -> None:
"""ARCHITECTURE.md должен ссылаться на ADR-007 в строке Offline."""
content = ARCHITECTURE_MD.read_text(encoding="utf-8")
offline_line = next(
(line for line in content.splitlines() if line.startswith("| Offline")), None
)
assert offline_line is not None, "Строка '| Offline' не найдена в ARCHITECTURE.md"
assert "ADR-007" in offline_line, (
f"Строка Offline в ARCHITECTURE.md не содержит ADR-007: {offline_line!r}"
)