feat(chat): add presence metadata and improve web chat core
Some checks failed
CI / test (push) Failing after 22s
Some checks failed
CI / test (push) Failing after 22s
- add user last_seen_at with alembic migration and persist on realtime disconnect - extend chat serialization with private online/last_seen, group members/online, channel subscribers - add Redis batch presence lookup helper - update web chat list/header to display status counters and last-seen labels - improve delivery receipt handling using last_delivered/last_read boundaries - include chat info panel and related API/type updates
This commit is contained in:
@@ -9,12 +9,14 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.chats.repository import list_user_chat_ids
|
||||
from app.chats.service import ensure_chat_membership
|
||||
from app.database.session import AsyncSessionLocal
|
||||
from app.messages.schemas import MessageCreateRequest, MessageRead, MessageStatusUpdateRequest
|
||||
from app.messages.service import create_chat_message, mark_message_status
|
||||
from app.realtime.models import ConnectionContext
|
||||
from app.realtime.presence import mark_user_offline, mark_user_online
|
||||
from app.realtime.repository import RedisRealtimeRepository
|
||||
from app.realtime.schemas import ChatEventPayload, MessageStatusPayload, OutgoingRealtimeEvent, SendMessagePayload
|
||||
from app.users.repository import update_user_last_seen_now
|
||||
|
||||
|
||||
class RealtimeGateway:
|
||||
@@ -76,6 +78,7 @@ class RealtimeGateway:
|
||||
if not subscribers:
|
||||
self._chat_subscribers.pop(chat_id, None)
|
||||
await mark_user_offline(user_id)
|
||||
await self._persist_last_seen(user_id)
|
||||
|
||||
async def handle_send_message(self, db: AsyncSession, user_id: int, payload: SendMessagePayload) -> None:
|
||||
message = await create_chat_message(
|
||||
@@ -197,6 +200,7 @@ class RealtimeGateway:
|
||||
if not subscribers:
|
||||
self._chat_subscribers.pop(chat_id, None)
|
||||
await mark_user_offline(user_id)
|
||||
await self._persist_last_seen(user_id)
|
||||
|
||||
@staticmethod
|
||||
def _extract_chat_id(channel: str) -> int | None:
|
||||
@@ -207,5 +211,13 @@ class RealtimeGateway:
|
||||
return None
|
||||
return int(chat_id)
|
||||
|
||||
async def _persist_last_seen(self, user_id: int) -> None:
|
||||
try:
|
||||
async with AsyncSessionLocal() as db:
|
||||
await update_user_last_seen_now(db, user_id=user_id)
|
||||
await db.commit()
|
||||
except Exception:
|
||||
return
|
||||
|
||||
|
||||
realtime_gateway = RealtimeGateway()
|
||||
|
||||
Reference in New Issue
Block a user