Уведомления: непрочитанные не протухают — игрок увидит их при любом заходе
Раньше уведомления удалялись через 72 часа после создания независимо от прочтения: кто не зашёл за 3 дня, не видел их вовсе. Теперь по времени чистятся только прочитанные (72ч после прочтения), а от роста у незаходящих защищает кап MAX_PER_USER=100 — при создании удаляются старейшие сверх лимита. Механика доставки не менялась: запись в БД + pull при заходе, SSE лишь ускоряет обновление открытых вкладок. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -56,23 +56,49 @@ def test_create_list_mark_read(engine):
|
||||
assert after["items"][0]["read_at"] is not None
|
||||
|
||||
|
||||
def test_purge_expired(engine):
|
||||
def test_purge_removes_only_long_read(engine):
|
||||
"""Протухают лишь ПРОЧИТАННЫЕ (спустя 72ч после прочтения): непрочитанное должно
|
||||
дождаться игрока, сколько бы тот ни отсутствовал."""
|
||||
uid = _make_user(engine, "Боб")
|
||||
old = datetime.now(timezone.utc).replace(tzinfo=None) - timedelta(
|
||||
hours=notification_service.RETENTION_HOURS + 1
|
||||
)
|
||||
with Session(engine) as s:
|
||||
n = Notification(user_id=uid, type="test", title="Старое")
|
||||
s.add(n)
|
||||
s.commit()
|
||||
s.refresh(n)
|
||||
# Состарим запись за пределы окна хранения.
|
||||
n.created_at = datetime.now(timezone.utc).replace(tzinfo=None) - timedelta(
|
||||
hours=notification_service.RETENTION_HOURS + 1
|
||||
# Старое непрочитанное, старое давно прочитанное и свежепрочитанное.
|
||||
s.add(Notification(user_id=uid, type="test", title="Непрочитанное", created_at=old))
|
||||
s.add(
|
||||
Notification(
|
||||
user_id=uid, type="test", title="Давно прочитанное", created_at=old, read_at=old
|
||||
)
|
||||
)
|
||||
s.add(
|
||||
Notification(
|
||||
user_id=uid,
|
||||
type="test",
|
||||
title="Свежепрочитанное",
|
||||
created_at=old,
|
||||
read_at=datetime.now(timezone.utc).replace(tzinfo=None),
|
||||
)
|
||||
)
|
||||
s.add(n)
|
||||
s.commit()
|
||||
|
||||
removed = notification_service.purge_expired(s)
|
||||
assert removed == 1
|
||||
assert notification_service.list_for_user(s, uid)["items"] == []
|
||||
titles = {n["title"] for n in notification_service.list_for_user(s, uid)["items"]}
|
||||
assert titles == {"Непрочитанное", "Свежепрочитанное"}
|
||||
|
||||
|
||||
def test_cap_per_user(engine):
|
||||
"""Кап MAX_PER_USER: при создании сверх лимита удаляются старейшие."""
|
||||
uid = _make_user(engine, "Копитель")
|
||||
with Session(engine) as s:
|
||||
for i in range(notification_service.MAX_PER_USER + 5):
|
||||
notification_service.create(s, uid, type="test", title=f"n{i}")
|
||||
data = notification_service.list_for_user(s, uid)
|
||||
assert len(data["items"]) == notification_service.MAX_PER_USER
|
||||
titles = {n["title"] for n in data["items"]}
|
||||
assert "n0" not in titles # старейшие срезаны
|
||||
assert f"n{notification_service.MAX_PER_USER + 4}" in titles # новейшее на месте
|
||||
|
||||
|
||||
def test_notifications_require_auth(client: TestClient):
|
||||
|
||||
Reference in New Issue
Block a user