1- # NOTE: should replace _crud_api_delete.py:delete_project
2-
1+ import asyncio
32import logging
4- from typing import Protocol
3+ import time
4+ from contextlib import contextmanager
5+ from typing import Any , Protocol
56
67from aiohttp import web
78from models_library .projects import ProjectID
9+ from models_library .users import UserID
10+ from servicelib .common_headers import UNDEFINED_DEFAULT_SIMCORE_USER_AGENT_VALUE
811from servicelib .redis ._errors import ProjectLockError
912from simcore_service_director_v2 .core .errors import ProjectNotFoundError
1013from simcore_service_webserver .projects .exceptions import ProjectDeleteError
1114
15+ from ..director_v2 import api as director_v2_service
1216from . import _projects_db as _projects_repository
17+ from . import projects_service
1318
1419_logger = logging .getLogger (__name__ )
1520
1621
22+ @contextmanager
23+ def _monitor_step (steps : dict [str , Any ], * , name : str , elapsed : bool = False ):
24+ # util
25+ start_time = time .perf_counter ()
26+ steps [name ] = {"status" : "starting" }
27+ try :
28+ yield
29+ except Exception as e :
30+ steps [name ]["status" ] = "failed"
31+ steps [name ]["exception" ] = str (e )
32+ raise
33+ else :
34+ steps [name ]["status" ] = "success"
35+ finally :
36+ if elapsed :
37+ steps [name ]["elapsed" ] = time .perf_counter () - start_time
38+
39+
1740class StopServicesCallback (Protocol ):
1841 async def __call__ (self , app : web .Application , project_uuid : ProjectID ) -> None :
1942 ...
2043
2144
45+ async def batch_stop_services_in_project (
46+ app : web .Application , * , user_id : UserID , project_uuid : ProjectID
47+ ) -> None :
48+ await asyncio .gather (
49+ director_v2_service .stop_pipeline (
50+ app , user_id = user_id , project_id = project_uuid
51+ ),
52+ projects_service .remove_project_dynamic_services (
53+ user_id = user_id ,
54+ project_uuid = f"{ project_uuid } " ,
55+ app = app ,
56+ simcore_user_agent = UNDEFINED_DEFAULT_SIMCORE_USER_AGENT_VALUE ,
57+ notify_users = False ,
58+ ),
59+ )
60+
61+
2262async def delete_project_as_admin (
2363 app : web .Application ,
2464 * ,
2565 project_uuid : ProjectID ,
26- stop_project_services_as_admin : StopServicesCallback | None ,
2766):
28- hidden = False
29- stopped = not stop_project_services_as_admin
30- deleted = False
67+
68+ state : dict [str , Any ] = {}
3169
3270 try :
33- # hide
34- await _projects_repository . patch_project (
35- app ,
36- project_uuid = project_uuid ,
37- new_partial_project_data = { "hidden" : True } ,
38- )
39- hidden = True
71+ # 1. hide
72+ with _monitor_step ( state , name = "hide" ):
73+ project = await _projects_repository . patch_project (
74+ app ,
75+ project_uuid = project_uuid ,
76+ new_partial_project_data = { "hidden" : True },
77+ )
4078
41- if stop_project_services_as_admin :
79+ # 2. stop
80+ with _monitor_step (state , name = "stop" , elapsed = True ):
4281 # NOTE: this callback could take long or raise whatever!
43- await stop_project_services_as_admin (app , project_uuid )
44- stopped = True
82+ await batch_stop_services_in_project (
83+ app , user_id = project .prj_owner , project_uuid = project_uuid
84+ )
4585
46- await _projects_repository .delete_project (app , project_uuid = project_uuid )
47- deleted = True
86+ # 3. delete
87+ with _monitor_step (state , name = "delete" ):
88+ await _projects_repository .delete_project (app , project_uuid = project_uuid )
4889
4990 except ProjectNotFoundError as err :
5091 _logger .debug (
@@ -62,5 +103,6 @@ async def delete_project_as_admin(
62103 except Exception as err :
63104 raise ProjectDeleteError (
64105 project_uuid = project_uuid ,
65- reason = f"Unexpected error. Deletion sequence: { hidden = } , { stopped = } , { deleted = } " ,
106+ reason = f"Unexpected error. Deletion sequence: { state = } " ,
107+ state = state ,
66108 ) from err
0 commit comments