fix: валидация настроек обмена PositiveInt/NonNegativeInt (M-4)
OUTBOX_POLL_SECONDS и ACK_TIMEOUT_SECONDS — PositiveInt, OUTBOX_MAX_REPUBLISH — NonNegativeInt: 0 и отрицательные значения периода и таймаута, отрицательное число повторов отвергаются при старте. Значения по умолчанию прежние. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
3d31c1eac5
commit
7a6a7fb36b
@ -1,5 +1,6 @@
|
||||
import os
|
||||
|
||||
from pydantic import NonNegativeInt, PositiveInt
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
@ -68,9 +69,12 @@ class Settings(BaseSettings):
|
||||
|
||||
# NATS и outbox/inbox обмена recognition_job
|
||||
NATS_ENABLED: bool = False
|
||||
OUTBOX_POLL_SECONDS: int = 5 # период опроса outbox
|
||||
ACK_TIMEOUT_SECONDS: int = 30 # ожидание ack сервиса распознавания до повторной публикации
|
||||
OUTBOX_MAX_REPUBLISH: int = 3 # число повторных публикаций до перевода в dlq
|
||||
# 0 и отрицательные значения отвергаются при старте: период 0 — горячий цикл, ack-таймаут 0 — повтор каждый проход
|
||||
OUTBOX_POLL_SECONDS: PositiveInt = 5 # период опроса outbox
|
||||
ACK_TIMEOUT_SECONDS: PositiveInt = 30 # ожидание ack сервиса распознавания до повторной публикации
|
||||
OUTBOX_MAX_REPUBLISH: NonNegativeInt = (
|
||||
3 # число повторных публикаций до перевода в dlq (0 — сразу dlq без повторов)
|
||||
)
|
||||
|
||||
model_config = SettingsConfigDict(
|
||||
extra="ignore",
|
||||
|
||||
@ -4,6 +4,7 @@ import os
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from src.core.config import Settings
|
||||
|
||||
@ -67,3 +68,40 @@ def test_empty_nats_seed_and_jwt_allowed(clean_env: pytest.MonkeyPatch) -> None:
|
||||
assert s.OPENBAO.NATS.NATS_JWT == ""
|
||||
assert s.NATS_ENABLED is True
|
||||
assert s.OPENBAO.SMB.SMB_HOST == ""
|
||||
|
||||
|
||||
REQUIRED_ENV = {
|
||||
"OPENBAO__DATABASE__DATABASE_URL": "postgresql+asyncpg://u:p@localhost:5432/d",
|
||||
"OPENBAO__MINIO__MINIO_URL": "localhost:9000",
|
||||
"OPENBAO__MINIO__MINIO_ADMIN_LOGIN": "login",
|
||||
"OPENBAO__MINIO__MINIO_ADMIN_PASSWORD": "password",
|
||||
"OPENBAO__MINIO__MINIO_BUCKET": "bucket",
|
||||
"OPENBAO__NATS__NATS_URL": "nats://localhost:4222",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("key", "value"),
|
||||
[
|
||||
("OUTBOX_POLL_SECONDS", "0"),
|
||||
("OUTBOX_POLL_SECONDS", "-1"),
|
||||
("ACK_TIMEOUT_SECONDS", "0"),
|
||||
("ACK_TIMEOUT_SECONDS", "-5"),
|
||||
("OUTBOX_MAX_REPUBLISH", "-1"),
|
||||
],
|
||||
)
|
||||
def test_exchange_settings_reject_invalid(clean_env: pytest.MonkeyPatch, key: str, value: str) -> None:
|
||||
"""Период опроса и ack-таймаут — строго положительные, число повторов — неотрицательное (финальное ревью M-4)."""
|
||||
for name, required in REQUIRED_ENV.items():
|
||||
clean_env.setenv(name, required)
|
||||
clean_env.setenv(key, value)
|
||||
with pytest.raises(ValidationError, match=key):
|
||||
Settings(_env_file=None) # type: ignore[call-arg]
|
||||
|
||||
|
||||
def test_zero_republish_allowed(clean_env: pytest.MonkeyPatch) -> None:
|
||||
"""OUTBOX_MAX_REPUBLISH=0 допустим: без повторов, сразу dlq после ack-таймаута."""
|
||||
for name, required in REQUIRED_ENV.items():
|
||||
clean_env.setenv(name, required)
|
||||
clean_env.setenv("OUTBOX_MAX_REPUBLISH", "0")
|
||||
assert Settings(_env_file=None).OUTBOX_MAX_REPUBLISH == 0 # type: ignore[call-arg]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user