Skip to content

Commit 442983a

Browse files
CHORE: simplify repository initialization locks
1 parent f229eb0 commit 442983a

1 file changed

Lines changed: 28 additions & 65 deletions

File tree

src/repositories/interface.py

Lines changed: 28 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
wait_fixed,
1010
retry,
1111
)
12-
from pydantic import BaseModel, ValidationError
12+
from pydantic import ValidationError
1313
from pymongo.errors import PyMongoError
1414
from pymongo.server_api import ServerApi
1515
from motor.motor_asyncio import AsyncIOMotorClient
@@ -62,23 +62,6 @@ async def wrapper(self, *args, **kwargs):
6262
return wrapper
6363

6464

65-
class RepoInstances(BaseModel):
66-
instance: object
67-
prospecting: int = 0
68-
69-
def add_prospecting(self):
70-
self.prospecting += 1
71-
72-
def remove_prospecting(self):
73-
self.prospecting -= 1
74-
75-
def get_prospecting(self):
76-
return self.prospecting
77-
78-
def get_instance(self):
79-
return self.instance
80-
81-
8265
class RepositoryInterface:
8366
"""
8467
Interface class for all repositories (singleton)
@@ -94,30 +77,14 @@ class RepositoryInterface:
9477
"""
9578

9679
_global_instances = {}
97-
_global_thread_lock = threading.RLock()
98-
_global_async_lock = asyncio.Lock()
80+
_global_thread_lock = threading.Lock()
9981

10082
def __new__(cls, *args, **kwargs):
101-
with (
102-
cls._global_thread_lock
103-
): # Ensure thread safety for singleton instance creation
83+
with cls._global_thread_lock:
10484
if cls not in cls._global_instances:
105-
instance = super(RepositoryInterface, cls).__new__(cls)
106-
cls._global_instances[cls] = RepoInstances(instance=instance)
107-
else:
108-
cls._global_instances[cls].add_prospecting()
109-
return cls._global_instances[cls].get_instance()
110-
111-
@classmethod
112-
def _stop_prospecting(cls):
113-
if cls in cls._global_instances:
114-
cls._global_instances[cls].remove_prospecting()
115-
116-
@classmethod
117-
def _get_instance_prospecting(cls):
118-
if cls in cls._global_instances:
119-
return cls._global_instances[cls].get_prospecting()
120-
return 0
85+
instance = super().__new__(cls)
86+
cls._global_instances[cls] = instance
87+
return cls._global_instances[cls]
12188

12289
def __init__(self, model: ApiBaseModel, *, max_pool_size: int = 3):
12390
if not getattr(self, '_initialized', False):
@@ -128,37 +95,33 @@ def __init__(self, model: ApiBaseModel, *, max_pool_size: int = 3):
12895

12996
@retry(stop=stop_after_attempt(5), wait=wait_fixed(0.2))
13097
async def _async_init(self):
131-
async with (
132-
self._global_async_lock
133-
): # Hybrid safe locks for initialization
134-
with self._global_thread_lock:
135-
try:
136-
self._initialize_connection()
137-
self._initialized = True
138-
except Exception as e:
139-
logger.error("Initialization failed: %s", e, exc_info=True)
140-
self._initialized = False
141-
142-
def _on_init_done(self, future):
143-
try:
144-
future.result()
145-
finally:
98+
if getattr(self, '_initialized', False):
99+
return
100+
101+
if not hasattr(self, '_init_lock'):
102+
self._init_lock = asyncio.Lock()
103+
104+
async with self._init_lock:
105+
if getattr(self, '_initialized', False):
106+
return
107+
108+
try:
109+
self._initialize_connection()
110+
except Exception as e:
111+
logger.error("Initialization failed: %s", e, exc_info=True)
112+
self._initialized = False
113+
raise
114+
115+
self._initialized = True
146116
self._initialized_event.set()
147117

148118
def _initialize(self):
149-
if not asyncio.get_event_loop().is_running():
119+
try:
120+
loop = asyncio.get_running_loop()
121+
except RuntimeError:
150122
asyncio.run(self._async_init())
151123
else:
152-
loop = asyncio.get_event_loop()
153-
loop.create_task(self._async_init()).add_done_callback(
154-
self._on_init_done
155-
)
156-
157-
def __del__(self):
158-
with self._global_thread_lock:
159-
self._global_instances.pop(self.__class__, None)
160-
self._initialized = False
161-
self._stop_prospecting()
124+
loop.create_task(self._async_init())
162125

163126
async def __aenter__(self):
164127
await self._initialized_event.wait() # Ensure initialization is complete

0 commit comments

Comments
 (0)