77from models_library .products import ProductName
88from models_library .projects import ProjectID
99from models_library .users import UserID
10+ from simcore_postgres_database .utils_repos import transaction_context
11+ from sqlalchemy .ext .asyncio import AsyncConnection
1012
13+ from ..db .plugin import get_asyncpg_engine
1114from ..projects ._trash_api import trash_project , untrash_project
1215from ..workspaces .api import check_user_workspace_access
1316from . import _folders_db
@@ -55,6 +58,7 @@ async def _check_exists_and_access(
5558
5659async def _folders_db_update (
5760 app : web .Application ,
61+ connection : AsyncConnection | None = None ,
5862 * ,
5963 product_name : ProductName ,
6064 folder_id : FolderID ,
@@ -63,6 +67,7 @@ async def _folders_db_update(
6367 # EXPLICIT un/trash
6468 await _folders_db .update (
6569 app ,
70+ connection ,
6671 folders_id_or_ids = folder_id ,
6772 product_name = product_name ,
6873 trashed_at = trashed_at ,
@@ -73,14 +78,15 @@ async def _folders_db_update(
7378 child_folders : set [FolderID ] = {
7479 f
7580 for f in await _folders_db .get_folders_recursively (
76- app , folder_id = folder_id , product_name = product_name
81+ app , connection , folder_id = folder_id , product_name = product_name
7782 )
7883 if f != folder_id
7984 }
8085
8186 if child_folders :
8287 await _folders_db .update (
8388 app ,
89+ connection ,
8490 folders_id_or_ids = child_folders ,
8591 product_name = product_name ,
8692 trashed_at = trashed_at ,
@@ -104,40 +110,40 @@ async def trash_folder(
104110 # Trash
105111 trashed_at = arrow .utcnow ().datetime
106112
107- _logger .debug (
108- "TODO: Unit of work for all folders and projects and fails if force_stop_first=%s is False" ,
109- force_stop_first ,
110- )
113+ async with transaction_context (get_asyncpg_engine (app )) as connection :
111114
112- # 1. Trash folder and children
113- await _folders_db_update (
114- app ,
115- folder_id = folder_id ,
116- product_name = product_name ,
117- trashed_at = trashed_at ,
118- )
119-
120- # 2. Trash all child projects that I am an owner
121- child_projects : list [
122- ProjectID
123- ] = await _folders_db .get_projects_recursively_only_if_user_is_owner (
124- app ,
125- folder_id = folder_id ,
126- private_workspace_user_id_or_none = user_id if workspace_is_private else None ,
127- user_id = user_id ,
128- product_name = product_name ,
129- )
130-
131- for project_id in child_projects :
132- await trash_project (
115+ # 1. Trash folder and children
116+ await _folders_db_update (
133117 app ,
118+ connection ,
119+ folder_id = folder_id ,
134120 product_name = product_name ,
121+ trashed_at = trashed_at ,
122+ )
123+
124+ # 2. Trash all child projects that I am an owner
125+ child_projects : list [
126+ ProjectID
127+ ] = await _folders_db .get_projects_recursively_only_if_user_is_owner (
128+ app ,
129+ connection ,
130+ folder_id = folder_id ,
131+ private_workspace_user_id_or_none = user_id if workspace_is_private else None ,
135132 user_id = user_id ,
136- project_id = project_id ,
137- force_stop_first = force_stop_first ,
138- explicit = False ,
133+ product_name = product_name ,
139134 )
140135
136+ for project_id in child_projects :
137+ await trash_project (
138+ app ,
139+ # NOTE: this needs to be included in the unit-of-work, i.e. connection,
140+ product_name = product_name ,
141+ user_id = user_id ,
142+ project_id = project_id ,
143+ force_stop_first = force_stop_first ,
144+ explicit = False ,
145+ )
146+
141147
142148async def untrash_folder (
143149 app : web .Application ,
0 commit comments