Skip to content

Commit 04110d4

Browse files
Removes project documents with no active users
Introduces an admin cleanup function that scans project documents in the Redis database and deletes those associated with projects that do not have any connected users via socketio. Helps reduce unnecessary storage and maintains data consistency.
1 parent 22cae1b commit 04110d4

File tree

1 file changed

+73
-1
lines changed

1 file changed

+73
-1
lines changed

services/web/server/src/simcore_service_webserver/projects/_project_document_service.py

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
This module contains common utilities for building and versioning project documents.
44
"""
55

6+
import logging
7+
import re
68
from typing import cast
79

810
from aiohttp import web
911
from models_library.api_schemas_webserver.projects import (
1012
ProjectDocument,
1113
ProjectDocumentVersion,
1214
)
15+
from models_library.api_schemas_webserver.socketio import SocketIORoomStr
1316
from models_library.projects import ProjectID, ProjectTemplateType
1417
from models_library.projects import ProjectType as ProjectTypeAPI
1518
from servicelib.redis import (
@@ -22,8 +25,11 @@
2225
get_redis_document_manager_client_sdk,
2326
get_redis_lock_manager_client_sdk,
2427
)
28+
from ..socketio._utils import get_socket_server
2529
from . import _projects_repository
2630

31+
_logger = logging.getLogger(__name__)
32+
2733

2834
async def create_project_document_and_increment_version(
2935
app: web.Application, project_uuid: ProjectID
@@ -86,4 +92,70 @@ async def _create_project_document_and_increment_version() -> (
8692
return await _create_project_document_and_increment_version()
8793

8894

89-
async def remove_project_documents_as_admin(app: web.Application) -> None: ...
95+
async def remove_project_documents_as_admin(app: web.Application) -> None:
96+
"""Admin function to clean up project documents for projects with no connected users.
97+
98+
This function scans through all project documents in the Redis DOCUMENTS database,
99+
checks if there are any users currently connected to the project room via socketio,
100+
and removes documents that have no connected users.
101+
"""
102+
# Get Redis document manager client to access the DOCUMENTS database
103+
redis_client = get_redis_document_manager_client_sdk(app)
104+
105+
# Pattern to match project document keys - looking for keys that contain project UUIDs
106+
project_document_pattern = "projects:*:version"
107+
108+
# Get socketio server instance
109+
sio = get_socket_server(app)
110+
111+
projects_removed = 0
112+
113+
# Scan through all project document keys
114+
async for key in redis_client.redis.scan_iter(
115+
match=project_document_pattern, count=1000
116+
):
117+
# Extract project UUID from the key pattern "projects:{project_uuid}:version"
118+
key_str = key.decode("utf-8") if isinstance(key, bytes) else key
119+
match = re.match(r"projects:([0-9a-f-]+):version", key_str)
120+
121+
if not match:
122+
continue
123+
124+
project_uuid_str = match.group(1)
125+
project_uuid = ProjectID(project_uuid_str)
126+
project_room = SocketIORoomStr.from_project_id(project_uuid)
127+
128+
# Check if there are any users connected to this project room
129+
try:
130+
# Get all session IDs (socket IDs) in the project room
131+
room_sessions = list(
132+
sio.manager.get_participants(namespace="/", room=project_room)
133+
)
134+
135+
# If no users are connected to this project room, remove the document
136+
if not room_sessions:
137+
await redis_client.redis.delete(key_str)
138+
projects_removed += 1
139+
_logger.info(
140+
"Removed project document for project %s (no connected users)",
141+
project_uuid,
142+
)
143+
else:
144+
_logger.debug(
145+
"Project %s has %d connected users, keeping document",
146+
project_uuid,
147+
len(room_sessions),
148+
)
149+
150+
except (KeyError, AttributeError, ValueError) as e:
151+
_logger.warning(
152+
"Failed to check room participants for project %s: %s",
153+
project_uuid,
154+
str(e),
155+
)
156+
continue
157+
158+
_logger.info(
159+
"Project document cleanup completed: removed %d project documents",
160+
projects_removed,
161+
)

0 commit comments

Comments
 (0)