Реализация на отдельных двух машинах с протестированным взаимодействием по проверке сообщений
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import uuid
|
||||
from datetime import UTC, datetime
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
from pydantic import TypeAdapter, ValidationError
|
||||
@@ -14,7 +17,12 @@ from app.schemas import (
|
||||
decode_cursor,
|
||||
encode_cursor,
|
||||
)
|
||||
from app.services import MESSAGE_SAFETY_REPLIES, safety_reply_message
|
||||
from app.services import (
|
||||
MESSAGE_SAFETY_REPLIES,
|
||||
ensure_delivery_outbox,
|
||||
safety_reply_message,
|
||||
safety_task_recovery_at,
|
||||
)
|
||||
|
||||
|
||||
def test_asyncpg_receives_libpq_dsn_without_sqlalchemy_driver() -> None:
|
||||
@@ -67,6 +75,41 @@ def test_message_safety_business_replies_are_content_specific() -> None:
|
||||
assert reply.delivery_status == "delivered"
|
||||
|
||||
|
||||
def test_safety_recovery_starts_after_synchronous_polling_window() -> None:
|
||||
now = datetime(2026, 8, 19, tzinfo=UTC)
|
||||
settings = SimpleNamespace(
|
||||
message_safety_task_poll_max_sec=300,
|
||||
message_safety_task_poll_interval_sec=2,
|
||||
)
|
||||
|
||||
assert (safety_task_recovery_at(now, settings) - now).total_seconds() == 307
|
||||
|
||||
|
||||
async def test_delivery_outbox_returns_concurrent_insert_winner() -> None:
|
||||
existing = object()
|
||||
session = SimpleNamespace(
|
||||
execute=AsyncMock(
|
||||
side_effect=[
|
||||
SimpleNamespace(scalar_one_or_none=lambda: None),
|
||||
SimpleNamespace(scalar_one=lambda: existing),
|
||||
]
|
||||
),
|
||||
get=AsyncMock(),
|
||||
)
|
||||
|
||||
result = await ensure_delivery_outbox(
|
||||
session,
|
||||
message_id=uuid.uuid4(),
|
||||
external_chat_id=uuid.uuid4(),
|
||||
payload_json={"message_id": "test"},
|
||||
next_attempt_at=datetime(2026, 8, 19, tzinfo=UTC),
|
||||
)
|
||||
|
||||
assert result is existing
|
||||
assert session.execute.await_count == 2
|
||||
session.get.assert_not_awaited()
|
||||
|
||||
|
||||
def test_fingerprint_is_canonical_and_user_scoped() -> None:
|
||||
user = uuid.uuid4()
|
||||
first = canonical_fingerprint("post", "/dialogs/{id}", {"id": "1"}, {"b": 2, "a": 1}, user)
|
||||
|
||||
Reference in New Issue
Block a user