Skip to content

Commit 4d3d978

Browse files
Refactors project document update for clarity and atomicity
Streamlines the workflow for updating project documents by separating workbench updates from document and version increment logic. Improves atomicity and clarity in concurrent operations, ensuring that project documents and their versions remain consistent. Enhances maintainability and reduces potential race conditions during project modifications.
1 parent a68c91e commit 4d3d978

File tree

2 files changed

+26
-26
lines changed

2 files changed

+26
-26
lines changed

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

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -958,36 +958,33 @@ async def _update_project_workbench_with_lock_and_notify(
958958
async with self.engine.acquire() as conn:
959959
user_primary_gid = await self._get_user_primary_group_gid(conn, user_id)
960960

961-
# 10 concurrent calls
961+
# Update the workbench
962+
updated_project, changed_entries = await self._update_project_workbench(
963+
partial_workbench_data,
964+
user_id=user_id,
965+
project_uuid=f"{project_uuid}",
966+
product_name=product_name,
967+
allow_workbench_changes=allow_workbench_changes,
968+
)
969+
962970
@exclusive(
963971
get_redis_lock_manager_client_sdk(self._app),
964972
lock_key=PROJECT_DB_UPDATE_REDIS_LOCK_KEY.format(project_uuid),
965973
blocking=True,
966974
blocking_timeout=None, # NOTE: this is a blocking call, a timeout has undefined effects
967975
)
968-
async def _update_workbench_and_notify() -> (
969-
tuple[ProjectDict, dict[NodeIDStr, Any], ProjectDocument, int]
976+
async def _build_project_document_and_increment_version() -> (
977+
tuple[ProjectDocument, int]
970978
):
971979
"""This function is protected because
972980
- the project document and its version must be kept in sync
973981
"""
974-
# Update the workbench work since it's atomic
975-
updated_project, changed_entries = await self._update_project_workbench(
976-
partial_workbench_data,
977-
user_id=user_id,
978-
project_uuid=f"{project_uuid}",
979-
product_name=product_name,
980-
allow_workbench_changes=allow_workbench_changes,
981-
)
982-
# the update project with last_modified timestamp latest is the last
983-
984982
# Get the full project with workbench for document creation
985983
project_with_workbench = (
986984
await _projects_repository.get_project_with_workbench(
987985
app=self._app, project_uuid=project_uuid
988986
)
989987
)
990-
991988
# Create project document
992989
project_document = ProjectDocument(
993990
uuid=project_with_workbench.uuid,
@@ -1006,21 +1003,19 @@ async def _update_workbench_and_notify() -> (
10061003
ProjectTemplateType, project_with_workbench.template_type
10071004
),
10081005
)
1009-
10101006
# Increment document version
10111007
redis_client_sdk = get_redis_document_manager_client_sdk(self._app)
10121008
document_version = await increment_and_return_project_document_version(
10131009
redis_client=redis_client_sdk, project_uuid=project_uuid
10141010
)
10151011

1016-
return updated_project, changed_entries, project_document, document_version
1012+
return project_document, document_version
10171013

10181014
(
1019-
updated_project,
1020-
changed_entries,
10211015
project_document,
10221016
document_version,
1023-
) = await _update_workbench_and_notify()
1017+
) = await _build_project_document_and_increment_version()
1018+
10241019
await notify_project_document_updated(
10251020
app=self._app,
10261021
project_id=project_uuid,

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -203,21 +203,24 @@ async def patch_project_and_notify_users(
203203
thread-safe operations on the project document.
204204
"""
205205

206+
await _projects_repository.patch_project(
207+
app=app,
208+
project_uuid=project_uuid,
209+
new_partial_project_data=patch_project_data,
210+
)
211+
206212
@exclusive(
207213
get_redis_lock_manager_client_sdk(app),
208214
lock_key=PROJECT_DB_UPDATE_REDIS_LOCK_KEY.format(project_uuid),
209215
blocking=True,
210216
blocking_timeout=None, # NOTE: this is a blocking call, a timeout has undefined effects
211217
)
212-
async def _patch_and_create_project_document() -> tuple[ProjectDocument, int]:
218+
async def _build_project_document_and_increment_version() -> (
219+
tuple[ProjectDocument, int]
220+
):
213221
"""This function is protected because
214222
- the project document and its version must be kept in sync
215223
"""
216-
await _projects_repository.patch_project(
217-
app=app,
218-
project_uuid=project_uuid,
219-
new_partial_project_data=patch_project_data,
220-
)
221224
project_with_workbench = await _projects_repository.get_project_with_workbench(
222225
app=app, project_uuid=project_uuid
223226
)
@@ -244,7 +247,9 @@ async def _patch_and_create_project_document() -> tuple[ProjectDocument, int]:
244247
)
245248
return project_document, document_version
246249

247-
project_document, document_version = await _patch_and_create_project_document()
250+
project_document, document_version = (
251+
await _build_project_document_and_increment_version()
252+
)
248253
await notify_project_document_updated(
249254
app=app,
250255
project_id=project_uuid,

0 commit comments

Comments
 (0)