67 lines
2.3 KiB
Python
67 lines
2.3 KiB
Python
"""In-memory notification store used when Postgres is not configured.
|
|
|
|
Mirrors MockEventStore's role for BaseEventStore: keeps the feature usable in
|
|
local dev and in tests without a live database, and matches
|
|
DOCUMENT_REPOSITORY_BACKEND's existing Mock/Postgres split.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
|
|
from app.infrastructure.perception.base_notification_store import BaseNotificationStore
|
|
|
|
|
|
class MockNotificationStore(BaseNotificationStore):
|
|
"""Dict-backed notification store. Data does not survive a process restart."""
|
|
|
|
def __init__(self) -> None:
|
|
"""Start with an empty feed and no read receipts."""
|
|
self._notifications: list[dict] = []
|
|
self._next_id = 1
|
|
# (notification_id, user_id) pairs — presence means read.
|
|
self._reads: set[tuple[int, str]] = set()
|
|
|
|
def create(
|
|
self,
|
|
*,
|
|
event_id: str,
|
|
kind: str,
|
|
title: str,
|
|
impact_level: str | None,
|
|
summary: str | None,
|
|
) -> None:
|
|
"""Append a notification with an auto-incrementing id."""
|
|
self._notifications.append({
|
|
"id": self._next_id,
|
|
"event_id": event_id,
|
|
"kind": kind,
|
|
"title": title,
|
|
"impact_level": impact_level,
|
|
"summary": summary,
|
|
"created_at": datetime.now(UTC).isoformat(),
|
|
})
|
|
self._next_id += 1
|
|
|
|
def list_for_user(self, user_id: str, limit: int = 20) -> list[dict]:
|
|
"""Return the newest `limit` notifications with this user's read state."""
|
|
ordered = sorted(self._notifications, key=lambda n: n["id"], reverse=True)
|
|
return [
|
|
{**n, "read": (n["id"], user_id) in self._reads}
|
|
for n in ordered[:limit]
|
|
]
|
|
|
|
def unread_count(self, user_id: str) -> int:
|
|
"""Count notifications this user has not yet read."""
|
|
return sum(1 for n in self._notifications if (n["id"], user_id) not in self._reads)
|
|
|
|
def mark_all_read(self, user_id: str) -> int:
|
|
"""Add a read receipt for every currently-unread notification."""
|
|
marked = 0
|
|
for n in self._notifications:
|
|
key = (n["id"], user_id)
|
|
if key not in self._reads:
|
|
self._reads.add(key)
|
|
marked += 1
|
|
return marked
|