diff --git a/backend/open_webui/models/groups.py b/backend/open_webui/models/groups.py index 6597928ce3..7d477f1836 100644 --- a/backend/open_webui/models/groups.py +++ b/backend/open_webui/models/groups.py @@ -253,13 +253,12 @@ async def refresh_group_sessions(user_ids): return # Import lazily to avoid models/socket import cycles. A committed write must not # be reported as failed just because a client has already disconnected. - from open_webui.socket.main import disconnect_user_sessions + from open_webui.socket.main import disconnect_sessions_for_users - for user_id in set(user_ids): - try: - await disconnect_user_sessions(user_id, refresh_access=True) - except Exception: - log.exception('Unable to refresh group access for user %s', user_id) + try: + await disconnect_sessions_for_users(user_ids, refresh_access=True) + except Exception: + log.exception('Unable to refresh group access for %s user(s)', len(user_ids)) async def validate_parent(db, group_id, parent_id): diff --git a/backend/open_webui/socket/main.py b/backend/open_webui/socket/main.py index 09937e9171..a535fb0f51 100644 --- a/backend/open_webui/socket/main.py +++ b/backend/open_webui/socket/main.py @@ -440,11 +440,6 @@ def get_session_ids_from_room(room): return list(members) if members else [] -def get_session_ids_by_user_id(user_id: str) -> list[str]: - """Get known session IDs for a user across the local rooms and shared session pool.""" - return get_session_ids_by_user_ids([user_id]) - - def get_session_ids_by_user_ids(user_ids: list[str]) -> list[str]: """Get known session IDs for users across the local rooms and shared session pool.""" if not user_ids: @@ -517,7 +512,14 @@ async def disconnect_user_sessions(user_id: str, *, refresh_access: bool = False The client will automatically reconnect and re-authenticate with fresh data from the database. """ - session_ids = get_session_ids_by_user_id(user_id) + session_ids = await disconnect_sessions_for_users([user_id], refresh_access=refresh_access) + if session_ids: + log.info('Requested disconnect of %s session(s) for user %s', len(session_ids), user_id) + + +async def disconnect_sessions_for_users(user_ids: list[str], *, refresh_access: bool = False) -> list[str]: + """Disconnect all Socket.IO sessions belonging to these users and return their session IDs.""" + session_ids = get_session_ids_by_user_ids(user_ids) for sid in session_ids: if refresh_access: try: @@ -527,10 +529,8 @@ async def disconnect_user_sessions(user_id: str, *, refresh_access: bool = False try: await sio.disconnect(sid) except Exception: - log.exception('Failed to disconnect session %s for user %s', sid, user_id) - - if session_ids: - log.info('Requested disconnect of %s session(s) for user %s', len(session_ids), user_id) + log.exception('Failed to disconnect session %s', sid) + return session_ids @sio.on('usage')