From 4f7edebe07da85fc0ac1227d3dc6e8c623400498 Mon Sep 17 00:00:00 2001 From: matusdrobuliak66 Date: Tue, 12 Aug 2025 15:28:08 +0200 Subject: [PATCH 1/3] Adds feature flag check for realtime collaboration updates Guards document update notifications with a configuration check to ensure updates are sent only when realtime collaboration is enabled. Prevents unnecessary operations and aligns with feature toggling. --- .../projects/_projects_repository_legacy.py | 29 +++++++++++-------- .../projects/_projects_service.py | 26 +++++++++-------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/services/web/server/src/simcore_service_webserver/projects/_projects_repository_legacy.py b/services/web/server/src/simcore_service_webserver/projects/_projects_repository_legacy.py index a6a051a5595..fdb7364d63d 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_projects_repository_legacy.py +++ b/services/web/server/src/simcore_service_webserver/projects/_projects_repository_legacy.py @@ -75,6 +75,7 @@ from tenacity.asyncio import AsyncRetrying from tenacity.retry import retry_if_exception_type +from ..application_settings import get_application_settings from ..models import ClientSessionID from ..utils import now_str from ._comments_repository import ( @@ -957,19 +958,23 @@ async def _update_project_workbench_with_lock_and_notify( allow_workbench_changes=allow_workbench_changes, ) - ( - project_document, - document_version, - ) = await create_project_document_and_increment_version(self._app, project_uuid) + app_settings = get_application_settings(self._app) + if app_settings.WEBSERVER_REALTIME_COLLABORATION is not None: + ( + project_document, + document_version, + ) = await create_project_document_and_increment_version( + self._app, project_uuid + ) - await notify_project_document_updated( - app=self._app, - project_id=project_uuid, - user_primary_gid=user_primary_gid, - client_session_id=client_session_id, - version=document_version, - document=project_document, - ) + await notify_project_document_updated( + app=self._app, + project_id=project_uuid, + user_primary_gid=user_primary_gid, + client_session_id=client_session_id, + version=document_version, + document=project_document, + ) return updated_project, changed_entries async def _update_project_workbench( diff --git a/services/web/server/src/simcore_service_webserver/projects/_projects_service.py b/services/web/server/src/simcore_service_webserver/projects/_projects_service.py index 55426aa4e72..86fedc7aaf1 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_projects_service.py +++ b/services/web/server/src/simcore_service_webserver/projects/_projects_service.py @@ -205,18 +205,20 @@ async def patch_project_and_notify_users( new_partial_project_data=patch_project_data, ) - ( - project_document, - document_version, - ) = await create_project_document_and_increment_version(app, project_uuid) - await notify_project_document_updated( - app=app, - project_id=project_uuid, - user_primary_gid=user_primary_gid, - client_session_id=client_session_id, - version=document_version, - document=project_document, - ) + app_settings = get_application_settings(app) + if app_settings.WEBSERVER_REALTIME_COLLABORATION is not None: + ( + project_document, + document_version, + ) = await create_project_document_and_increment_version(app, project_uuid) + await notify_project_document_updated( + app=app, + project_id=project_uuid, + user_primary_gid=user_primary_gid, + client_session_id=client_session_id, + version=document_version, + document=project_document, + ) def _is_node_dynamic(node_key: str) -> bool: From c92eb971e24c5a9f24f1bfcc5ee0220109b13e3c Mon Sep 17 00:00:00 2001 From: matusdrobuliak66 Date: Wed, 13 Aug 2025 10:13:31 +0200 Subject: [PATCH 2/3] fix test --- .../server/tests/unit/with_dbs/02/conftest.py | 25 +++++++++++ ..._patch_project_and_notify_users_locking.py | 3 ++ .../02/test_projects_states_handlers.py | 43 +++++++++---------- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/services/web/server/tests/unit/with_dbs/02/conftest.py b/services/web/server/tests/unit/with_dbs/02/conftest.py index 4b5fb923edb..c2191724e84 100644 --- a/services/web/server/tests/unit/with_dbs/02/conftest.py +++ b/services/web/server/tests/unit/with_dbs/02/conftest.py @@ -16,6 +16,7 @@ import pytest from aiohttp.test_utils import TestClient from aioresponses import aioresponses +from common_library.json_serialization import json_dumps from faker import Faker from models_library.api_schemas_directorv2.dynamic_services import DynamicServiceGet from models_library.projects_nodes import Node, NodeID @@ -27,6 +28,8 @@ from pydantic import TypeAdapter from pytest_mock import MockerFixture from pytest_simcore.helpers.assert_checks import assert_status +from pytest_simcore.helpers.monkeypatch_envs import setenvs_from_dict +from pytest_simcore.helpers.typing_env import EnvVarsDict from pytest_simcore.helpers.webserver_projects import NewProject, delete_all_projects from pytest_simcore.helpers.webserver_users import UserInfoDict from settings_library.catalog import CatalogSettings @@ -483,3 +486,25 @@ def workbench_db_column() -> dict[str, Any]: def workbench(workbench_db_column: dict[str, Any]) -> dict[NodeID, Node]: # convert to model return TypeAdapter(dict[NodeID, Node]).validate_python(workbench_db_column) + + +@pytest.fixture +def max_number_of_user_sessions(faker: Faker) -> int: + return faker.pyint(min_value=1, max_value=5) + + +@pytest.fixture +def with_enabled_rtc_collaboration( + app_environment: EnvVarsDict, + with_dev_features_enabled: None, + monkeypatch: pytest.MonkeyPatch, + max_number_of_user_sessions: int, +) -> None: + setenvs_from_dict( + monkeypatch, + { + "WEBSERVER_REALTIME_COLLABORATION": json_dumps( + {"RTC_MAX_NUMBER_OF_USERS": max_number_of_user_sessions} + ) + }, + ) diff --git a/services/web/server/tests/unit/with_dbs/02/test_projects_patch_project_and_notify_users_locking.py b/services/web/server/tests/unit/with_dbs/02/test_projects_patch_project_and_notify_users_locking.py index 80b7ea6fb47..3d82099cd56 100644 --- a/services/web/server/tests/unit/with_dbs/02/test_projects_patch_project_and_notify_users_locking.py +++ b/services/web/server/tests/unit/with_dbs/02/test_projects_patch_project_and_notify_users_locking.py @@ -49,6 +49,7 @@ def user_primary_gid(logged_user: UserInfoDict) -> int: ) async def test_patch_project_and_notify_users_sequential( user_role: UserRole, + with_enabled_rtc_collaboration: None, expected: HTTPStatus, client: TestClient, user_project: ProjectDict, @@ -105,6 +106,7 @@ async def test_patch_project_and_notify_users_sequential( ) async def test_patch_project_and_notify_users_concurrent_locking( user_role: UserRole, + with_enabled_rtc_collaboration: None, expected: HTTPStatus, client: TestClient, user_project: ProjectDict, @@ -155,6 +157,7 @@ async def test_patch_project_and_notify_users_concurrent_locking( ) async def test_patch_project_and_notify_users_concurrent_different_projects( user_role: UserRole, + with_enabled_rtc_collaboration: None, expected: HTTPStatus, client: TestClient, user_project: ProjectDict, diff --git a/services/web/server/tests/unit/with_dbs/02/test_projects_states_handlers.py b/services/web/server/tests/unit/with_dbs/02/test_projects_states_handlers.py index 67845662e0b..22bfe0afe6a 100644 --- a/services/web/server/tests/unit/with_dbs/02/test_projects_states_handlers.py +++ b/services/web/server/tests/unit/with_dbs/02/test_projects_states_handlers.py @@ -22,7 +22,6 @@ import sqlalchemy as sa from aiohttp import ClientResponse from aiohttp.test_utils import TestClient, TestServer -from common_library.json_serialization import json_dumps from faker import Faker from models_library.api_schemas_directorv2.dynamic_services import DynamicServiceGet from models_library.api_schemas_dynamic_scheduler.dynamic_services import ( @@ -54,8 +53,6 @@ from pytest_mock import MockerFixture from pytest_simcore.helpers.assert_checks import assert_status from pytest_simcore.helpers.logging_tools import log_context -from pytest_simcore.helpers.monkeypatch_envs import setenvs_from_dict -from pytest_simcore.helpers.typing_env import EnvVarsDict from pytest_simcore.helpers.webserver_login import LoggedUser, log_client_in from pytest_simcore.helpers.webserver_parametrizations import ( ExpectedResponse, @@ -88,26 +85,26 @@ API_PREFIX = f"/{API_VTAG}" -@pytest.fixture -def max_number_of_user_sessions(faker: Faker) -> int: - return faker.pyint(min_value=1, max_value=5) - - -@pytest.fixture -def with_enabled_rtc_collaboration( - app_environment: EnvVarsDict, - with_dev_features_enabled: None, - monkeypatch: pytest.MonkeyPatch, - max_number_of_user_sessions: int, -) -> None: - setenvs_from_dict( - monkeypatch, - { - "WEBSERVER_REALTIME_COLLABORATION": json_dumps( - {"RTC_MAX_NUMBER_OF_USERS": max_number_of_user_sessions} - ) - }, - ) +# @pytest.fixture +# def max_number_of_user_sessions(faker: Faker) -> int: +# return faker.pyint(min_value=1, max_value=5) + + +# @pytest.fixture +# def with_enabled_rtc_collaboration( +# app_environment: EnvVarsDict, +# with_dev_features_enabled: None, +# monkeypatch: pytest.MonkeyPatch, +# max_number_of_user_sessions: int, +# ) -> None: +# setenvs_from_dict( +# monkeypatch, +# { +# "WEBSERVER_REALTIME_COLLABORATION": json_dumps( +# {"RTC_MAX_NUMBER_OF_USERS": max_number_of_user_sessions} +# ) +# }, +# ) def assert_replaced(current_project, update_data): From 0dceb0bdebaf3becd17bd3ec41c7bf56e911771d Mon Sep 17 00:00:00 2001 From: matusdrobuliak66 Date: Wed, 13 Aug 2025 10:13:50 +0200 Subject: [PATCH 3/3] fix test --- .../02/test_projects_states_handlers.py | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/services/web/server/tests/unit/with_dbs/02/test_projects_states_handlers.py b/services/web/server/tests/unit/with_dbs/02/test_projects_states_handlers.py index 22bfe0afe6a..6ef6429eec9 100644 --- a/services/web/server/tests/unit/with_dbs/02/test_projects_states_handlers.py +++ b/services/web/server/tests/unit/with_dbs/02/test_projects_states_handlers.py @@ -85,28 +85,6 @@ API_PREFIX = f"/{API_VTAG}" -# @pytest.fixture -# def max_number_of_user_sessions(faker: Faker) -> int: -# return faker.pyint(min_value=1, max_value=5) - - -# @pytest.fixture -# def with_enabled_rtc_collaboration( -# app_environment: EnvVarsDict, -# with_dev_features_enabled: None, -# monkeypatch: pytest.MonkeyPatch, -# max_number_of_user_sessions: int, -# ) -> None: -# setenvs_from_dict( -# monkeypatch, -# { -# "WEBSERVER_REALTIME_COLLABORATION": json_dumps( -# {"RTC_MAX_NUMBER_OF_USERS": max_number_of_user_sessions} -# ) -# }, -# ) - - def assert_replaced(current_project, update_data): def _extract(dikt, keys): return {k: dikt[k] for k in keys}