99 wait_fixed ,
1010 retry ,
1111)
12- from pydantic import BaseModel , ValidationError
12+ from pydantic import ValidationError
1313from pymongo .errors import PyMongoError
1414from pymongo .server_api import ServerApi
1515from 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-
8265class 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