1- import datetime
21import logging
3- from asyncio .log import logger
42from collections .abc import AsyncIterator
53from contextlib import asynccontextmanager
6- from typing import Final
74
8- import redis
95from aiohttp import web
106from models_library .projects import ProjectID
117from models_library .projects_access import Owner
128from models_library .projects_state import ProjectLocked , ProjectStatus
13- from redis .asyncio .lock import Lock
14- from servicelib .background_task import periodic_task
15- from servicelib .logging_utils import log_context
9+
10+ # from .exceptions import ProjectLockError
11+ from servicelib .project_lock import PROJECT_LOCK_TIMEOUT , PROJECT_REDIS_LOCK_KEY
12+ from servicelib .project_lock import lock_project as common_lock_project
1613
1714from ..redis import get_redis_lock_manager_client
1815from ..users .api import FullNameDict
19- from .exceptions import ProjectLockError
2016
2117_logger = logging .getLogger (__name__ )
2218
23- PROJECT_REDIS_LOCK_KEY : str = "project_lock:{}"
24- PROJECT_LOCK_TIMEOUT : Final [datetime .timedelta ] = datetime .timedelta (seconds = 10 )
25- ProjectLock = Lock
26-
27-
28- async def _auto_extend_project_lock (project_lock : Lock ) -> None :
29- # NOTE: the background task already catches anything that might raise here
30- await project_lock .reacquire ()
31-
3219
3320@asynccontextmanager
3421async def lock_project (
@@ -48,42 +35,12 @@ async def lock_project(
4835 PROJECT_REDIS_LOCK_KEY .format (project_uuid ),
4936 timeout = PROJECT_LOCK_TIMEOUT .total_seconds (),
5037 )
51- try :
52- if not await redis_lock .acquire (
53- blocking = False ,
54- token = ProjectLocked (
55- value = True ,
56- owner = Owner (user_id = user_id , ** user_fullname ), # type: ignore[arg-type]
57- status = status ,
58- ).json (),
59- ):
60- msg = f"Lock for project { project_uuid !r} user { user_id !r} could not be acquired"
61- raise ProjectLockError (msg )
62-
63- with log_context (
64- _logger ,
65- logging .DEBUG ,
66- msg = f"with lock for { user_id = } :{ user_fullname = } :{ project_uuid = } :{ status = } " ,
67- ):
68- async with periodic_task (
69- _auto_extend_project_lock ,
70- interval = 0.6 * PROJECT_LOCK_TIMEOUT ,
71- task_name = f"{ PROJECT_REDIS_LOCK_KEY .format (project_uuid )} _lock_auto_extend" ,
72- project_lock = redis_lock ,
73- ):
74- yield
38+ owner = Owner (user_id = user_id , ** user_fullname ) # type: ignore[arg-type]
7539
76- finally :
77- # let's ensure we release that stuff
78- try :
79- if await redis_lock .owned ():
80- await redis_lock .release ()
81- except (redis .exceptions .LockError , redis .exceptions .LockNotOwnedError ) as exc :
82- logger .warning (
83- "releasing %s unexpectedly raised an exception: %s" ,
84- f"{ redis_lock = !r} " ,
85- f"{ exc } " ,
86- )
40+ async with common_lock_project (
41+ redis_lock , project_uuid = project_uuid , status = status , owner = owner
42+ ):
43+ yield
8744
8845
8946async def is_project_locked (
0 commit comments