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
50 lines
1.4 KiB
Python
50 lines
1.4 KiB
Python
from redis.exceptions import RedisError
|
|
|
|
from app.utils.redis_client import get_redis_client
|
|
|
|
|
|
async def mark_user_online(user_id: int) -> None:
|
|
try:
|
|
redis = get_redis_client()
|
|
key = f"presence:user:{user_id}"
|
|
count = await redis.incr(key)
|
|
if count == 1:
|
|
await redis.expire(key, 3600)
|
|
except RedisError:
|
|
return
|
|
|
|
|
|
async def mark_user_offline(user_id: int) -> None:
|
|
try:
|
|
redis = get_redis_client()
|
|
key = f"presence:user:{user_id}"
|
|
value = await redis.decr(key)
|
|
if value <= 0:
|
|
await redis.delete(key)
|
|
except RedisError:
|
|
return
|
|
|
|
|
|
async def is_user_online(user_id: int) -> bool:
|
|
try:
|
|
redis = get_redis_client()
|
|
value = await redis.get(f"presence:user:{user_id}")
|
|
return bool(value and str(value).isdigit() and int(value) > 0)
|
|
except RedisError:
|
|
return False
|
|
|
|
|
|
async def get_users_online_map(user_ids: list[int]) -> dict[int, bool]:
|
|
if not user_ids:
|
|
return {}
|
|
try:
|
|
redis = get_redis_client()
|
|
keys = [f"presence:user:{user_id}" for user_id in user_ids]
|
|
values = await redis.mget(keys)
|
|
return {
|
|
user_id: bool(value and str(value).isdigit() and int(value) > 0)
|
|
for user_id, value in zip(user_ids, values, strict=False)
|
|
}
|
|
except RedisError:
|
|
return {user_id: False for user_id in user_ids}
|