From 47ab492231fe08de00baa78d227e5e473348dae2 Mon Sep 17 00:00:00 2001 From: coder-bot Date: Tue, 18 Aug 2026 16:46:52 +0000 Subject: [PATCH] Fix StatusUpdate field annotation and is_online batch-call mismatch - status_message: str | Field(...) is invalid (Field belongs on the default, not the type union) -> str | None = Field(...) - router called is_online(ids) with a list and treated the bool result as a collection (uid in online_ids would TypeError on the first real call) -> added is_online_batch() using MGET, one round trip, tested against a live Redis instance --- backend/app/routers/presence.py | 4 ++-- backend/app/services/presence.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/backend/app/routers/presence.py b/backend/app/routers/presence.py index 361c1ca..769c669 100644 --- a/backend/app/routers/presence.py +++ b/backend/app/routers/presence.py @@ -43,7 +43,7 @@ class PresenceResponse(BaseModel): class StatusUpdate(BaseModel): - status_message: str | Field(default=None, max_length=_STATUS_MAX_LEN) + status_message: str | None = Field(default=None, max_length=_STATUS_MAX_LEN) @field_validator("status_message") @classmethod @@ -107,7 +107,7 @@ async def get_presence( ) # Check Redis for online status - online_ids = await _presence_store.is_online(ids) + online_ids = await _presence_store.is_online_batch(ids) # Fetch DB records for last_seen_at and status_message result = await db.execute( diff --git a/backend/app/services/presence.py b/backend/app/services/presence.py index a7df2ca..2faa2dc 100644 --- a/backend/app/services/presence.py +++ b/backend/app/services/presence.py @@ -95,6 +95,16 @@ class PresenceStore: exists = await self.client.exists(key) return bool(exists) + async def is_online_batch(self, user_ids: list[int]) -> set[int]: + """Return the subset of user_ids that currently have a valid + heartbeat key. Uses MGET (one round trip) rather than one EXISTS + per user.""" + if not user_ids: + return set() + keys = [self._heartbeat_key(uid) for uid in user_ids] + values = await self.client.mget(keys) + return {uid for uid, v in zip(user_ids, values) if v is not None} + # ------------------------------------------------------------------ # Presence lookup # ------------------------------------------------------------------