2
2
import logging
3
3
from contextlib import suppress
4
4
from itertools import chain
5
- from typing import Dict , List , Tuple
5
+ from typing import Dict , List , Optional , Tuple
6
6
7
+ import psycopg2
7
8
from aiohttp import web
8
- from aiopg .sa .result import RowProxy
9
9
from aioredlock import Aioredlock
10
-
11
10
from servicelib .observer import emit
12
11
from servicelib .utils import logged_gather
13
12
from simcore_service_webserver import users_exceptions
52
51
logger = logging .getLogger (__name__ )
53
52
54
53
55
- async def setup_garbage_collector_task (app : web .Application ):
56
- loop = asyncio .get_event_loop ()
57
- app [APP_GARBAGE_COLLECTOR_KEY ] = loop .create_task (garbage_collector_task (app ))
54
+ async def _setup_garbage_collector_task (app : web .Application ):
55
+
56
+ app [APP_GARBAGE_COLLECTOR_KEY ] = asyncio .create_task (
57
+ garbage_collector_task (app ), name = "garbage-collector"
58
+ )
59
+
58
60
yield
59
- task = app [APP_GARBAGE_COLLECTOR_KEY ]
60
- task .cancel ()
61
- await task
61
+
62
+ with suppress (asyncio .CancelledError ):
63
+ task = app [APP_GARBAGE_COLLECTOR_KEY ]
64
+ task .cancel ()
65
+ await task
62
66
63
67
64
68
def setup_garbage_collector (app : web .Application ):
65
- app .cleanup_ctx .append (setup_garbage_collector_task )
69
+ app .cleanup_ctx .append (_setup_garbage_collector_task )
66
70
67
71
68
72
async def garbage_collector_task (app : web .Application ):
69
- keep_alive = True
70
73
71
- while keep_alive :
74
+ while True :
72
75
logger .info ("Starting garbage collector..." )
73
76
try :
74
77
interval = get_garbage_collector_interval (app )
75
78
while True :
76
79
await collect_garbage (app )
77
80
await asyncio .sleep (interval )
78
81
79
- except asyncio .CancelledError :
80
- keep_alive = False
81
- logger . info ( "Garbage collection task was cancelled, it will not restart!" )
82
+ except asyncio .CancelledError : # pylint: disable=try-except-raise
83
+ # do not catch this
84
+ raise
82
85
83
86
except Exception : # pylint: disable=broad-except
84
87
logger .warning (
@@ -254,12 +257,10 @@ async def remove_disconnected_user_resources(
254
257
resource_name ,
255
258
keys_to_update ,
256
259
)
257
- with suppress (asyncio .CancelledError ):
258
- on_released_tasks = [
259
- registry .remove_resource (key , resource_name )
260
- for key in keys_to_update
261
- ]
262
- await logged_gather (* on_released_tasks , reraise = False )
260
+ on_released_tasks = [
261
+ registry .remove_resource (key , resource_name ) for key in keys_to_update
262
+ ]
263
+ await logged_gather (* on_released_tasks , reraise = False )
263
264
264
265
# NOTE:
265
266
# - if releasing a resource (1) fails, annotations in registry allows GC to try in next round
@@ -375,11 +376,12 @@ async def remove_guest_user_with_all_its_resources(
375
376
try :
376
377
await remove_all_projects_for_user (app = app , user_id = user_id )
377
378
await remove_user (app = app , user_id = user_id )
378
- except Exception as e : # pylint: disable=broad-except
379
- logger . warning ( "%s" , e )
379
+
380
+ except psycopg2 . DatabaseError :
380
381
logger .warning (
381
382
"Could not remove GUEST with id=%s. Check the logs above for details" ,
382
383
user_id ,
384
+ exc_info = True ,
383
385
)
384
386
385
387
@@ -405,7 +407,7 @@ async def remove_all_projects_for_user(app: web.Application, user_id: int) -> No
405
407
user_id ,
406
408
)
407
409
return
408
- user_primary_gid : str = str (project_owner ["primary_gid" ])
410
+ user_primary_gid = int (project_owner ["primary_gid" ])
409
411
410
412
# fetch all projects for the user
411
413
user_project_uuids = await app [
@@ -472,8 +474,8 @@ async def get_new_project_owner_gid(
472
474
project_uuid : str ,
473
475
user_id : int ,
474
476
user_primary_gid : int ,
475
- project : RowProxy ,
476
- ) -> str :
477
+ project : Dict ,
478
+ ) -> Optional [ int ] :
477
479
"""Goes through the access rights and tries to find a new suitable owner.
478
480
The first viable user is selected as a new owner.
479
481
In order to become a new owner the user must have write access right.
@@ -533,7 +535,7 @@ async def get_new_project_owner_gid(
533
535
534
536
async def fetch_new_project_owner_from_groups (
535
537
app : web .Application , standard_groups : Dict , user_id : int
536
- ) -> int :
538
+ ) -> Optional [ int ] :
537
539
"""Iterate over all the users in a group and if the users exists in the db
538
540
return its gid"""
539
541
@@ -554,6 +556,7 @@ async def fetch_new_project_owner_from_groups(
554
556
"Could not find new owner '%s' will try a new one" ,
555
557
possible_user_id ,
556
558
)
559
+
557
560
return None
558
561
559
562
@@ -562,17 +565,19 @@ async def replace_current_owner(
562
565
project_uuid : str ,
563
566
user_primary_gid : int ,
564
567
new_project_owner_gid : str ,
565
- project : RowProxy ,
568
+ project : Dict ,
566
569
) -> None :
567
570
try :
568
571
new_project_owner_id = await get_user_id_from_gid (
569
572
app = app , primary_gid = int (new_project_owner_gid )
570
573
)
571
- except Exception : # pylint: disable=broad-except
574
+
575
+ except psycopg2 .DatabaseError :
572
576
logger .exception (
573
577
"Could not recover new user id from gid %s" , new_project_owner_gid
574
578
)
575
579
return
580
+
576
581
# the result might me none
577
582
if new_project_owner_id is None :
578
583
logger .warning (
@@ -588,13 +593,14 @@ async def replace_current_owner(
588
593
str (new_project_owner_gid )
589
594
] = ProjectAccessRights .OWNER .value
590
595
logger .error ("Syncing back project %s" , project )
596
+
591
597
# syncing back project data
592
598
try :
593
599
await app [APP_PROJECT_DBAPI ].update_project_without_enforcing_checks (
594
600
project_data = project ,
595
601
project_uuid = project_uuid ,
596
602
)
597
- except Exception : # pylint: disable=broad-except
603
+ except psycopg2 . DatabaseError :
598
604
logger .exception (
599
605
"Could not remove old owner and replaced it with user %s" ,
600
606
new_project_owner_id ,
@@ -605,7 +611,7 @@ async def remove_user(app: web.Application, user_id: int) -> None:
605
611
"""Tries to remove a user, if the users still exists a warning message will be displayed"""
606
612
try :
607
613
await delete_user (app , user_id )
608
- except Exception : # pylint: disable=broad-except
614
+ except psycopg2 . DatabaseError :
609
615
logger .warning (
610
616
"User '%s' still has some projects, could not be deleted" , user_id
611
617
)
0 commit comments