1515
1616log = RunPodLogger ()
1717
18+
19+ # ----------------------------- Lazy Loading Utilities -------------------------- #
20+ _jobs_progress_instance = None
21+
22+
23+ def get_jobs_progress ():
24+ """Get the global JobsProgress instance with lazy initialization."""
25+ global _jobs_progress_instance
26+ if _jobs_progress_instance is None :
27+ _jobs_progress_instance = JobsProgress ()
28+ return _jobs_progress_instance
29+
30+
31+ def reset_jobs_progress ():
32+ """Reset the lazy-loaded JobsProgress instance (useful for testing)."""
33+ global _jobs_progress_instance
34+ _jobs_progress_instance = None
35+
1836REF_COUNT_ZERO = time .perf_counter () # Used for benchmarking with the debugger.
1937
2038WORKER_ID = os .environ .get ("RUNPOD_POD_ID" , str (uuid .uuid4 ()))
@@ -72,6 +90,8 @@ class JobsProgress:
7290 _shared_data : Optional [Any ] = None
7391 _lock : Optional [Any ] = None
7492 _use_multiprocessing : bool = True
93+ _fallback_jobs : list = []
94+ _fallback_lock : Optional [threading .Lock ] = None
7595
7696 def __new__ (cls ):
7797 if cls ._instance is None :
@@ -99,10 +119,10 @@ def __repr__(self) -> str:
99119 return f"<{ self .__class__ .__name__ } >: { self .get_job_list ()} "
100120
101121 def clear (self ) -> None :
102- if self ._use_multiprocessing :
122+ if self ._use_multiprocessing and self . _lock is not None and self . _shared_data is not None :
103123 with self ._lock :
104124 self ._shared_data ['jobs' ][:] = []
105- else :
125+ elif not self . _use_multiprocessing and self . _fallback_lock is not None :
106126 with self ._fallback_lock :
107127 self ._fallback_jobs .clear ()
108128
@@ -119,12 +139,12 @@ def add(self, element: Any):
119139 else :
120140 raise TypeError ("Only Job objects can be added to JobsProgress." )
121141
122- if self ._use_multiprocessing :
142+ if self ._use_multiprocessing and self . _lock is not None and self . _shared_data is not None :
123143 with self ._lock :
124144 job_list = self ._shared_data ['jobs' ]
125145 if not any (job ['id' ] == job_dict ['id' ] for job in job_list ):
126146 job_list .append (job_dict )
127- else :
147+ elif not self . _use_multiprocessing and self . _fallback_lock is not None :
128148 with self ._fallback_lock :
129149 if not any (job ['id' ] == job_dict ['id' ] for job in self ._fallback_jobs ):
130150 self ._fallback_jobs .append (job_dict )
@@ -144,13 +164,13 @@ def get(self, element: Any) -> Optional[Job]:
144164 else :
145165 raise TypeError ("Only Job objects can be retrieved from JobsProgress." )
146166
147- if self ._use_multiprocessing :
167+ if self ._use_multiprocessing and self . _lock is not None and self . _shared_data is not None :
148168 with self ._lock :
149169 for job_dict in self ._shared_data ['jobs' ]:
150170 if job_dict ['id' ] == search_id :
151171 log .debug (f"JobsProgress | Retrieved job: { job_dict ['id' ]} " )
152172 return Job (** job_dict )
153- else :
173+ elif not self . _use_multiprocessing and self . _fallback_lock is not None :
154174 with self ._fallback_lock :
155175 for job_dict in self ._fallback_jobs :
156176 if job_dict ['id' ] == search_id :
@@ -171,15 +191,15 @@ def remove(self, element: Any):
171191 else :
172192 raise TypeError ("Only Job objects can be removed from JobsProgress." )
173193
174- if self ._use_multiprocessing :
194+ if self ._use_multiprocessing and self . _lock is not None and self . _shared_data is not None :
175195 with self ._lock :
176196 job_list = self ._shared_data ['jobs' ]
177197 for i , job_dict in enumerate (job_list ):
178198 if job_dict ['id' ] == job_id :
179199 del job_list [i ]
180200 log .debug (f"JobsProgress | Removed job: { job_dict ['id' ]} " )
181201 break
182- else :
202+ elif not self . _use_multiprocessing and self . _fallback_lock is not None :
183203 with self ._fallback_lock :
184204 for i , job_dict in enumerate (self ._fallback_jobs ):
185205 if job_dict ['id' ] == job_id :
@@ -191,10 +211,11 @@ def get_job_list(self) -> Optional[str]:
191211 """
192212 Returns the list of job IDs as comma-separated string.
193213 """
194- if self ._use_multiprocessing :
214+ job_list = []
215+ if self ._use_multiprocessing and self ._lock is not None and self ._shared_data is not None :
195216 with self ._lock :
196217 job_list = list (self ._shared_data ['jobs' ])
197- else :
218+ elif not self . _use_multiprocessing and self . _fallback_lock is not None :
198219 with self ._fallback_lock :
199220 job_list = list (self ._fallback_jobs )
200221
@@ -208,19 +229,21 @@ def get_job_count(self) -> int:
208229 """
209230 Returns the number of jobs.
210231 """
211- if self ._use_multiprocessing :
232+ if self ._use_multiprocessing and self . _lock is not None and self . _shared_data is not None :
212233 with self ._lock :
213234 return len (self ._shared_data ['jobs' ])
214- else :
235+ elif not self . _use_multiprocessing and self . _fallback_lock is not None :
215236 with self ._fallback_lock :
216237 return len (self ._fallback_jobs )
238+ return 0
217239
218240 def __iter__ (self ):
219241 """Make the class iterable - returns Job objects"""
220- if self ._use_multiprocessing :
242+ job_dicts = []
243+ if self ._use_multiprocessing and self ._lock is not None and self ._shared_data is not None :
221244 with self ._lock :
222245 job_dicts = list (self ._shared_data ['jobs' ])
223- else :
246+ elif not self . _use_multiprocessing and self . _fallback_lock is not None :
224247 with self ._fallback_lock :
225248 job_dicts = list (self ._fallback_jobs )
226249 return iter (Job (** job_dict ) for job_dict in job_dicts )
@@ -240,9 +263,10 @@ def __contains__(self, element: Any) -> bool:
240263 else :
241264 return False
242265
243- if self ._use_multiprocessing :
266+ if self ._use_multiprocessing and self . _lock is not None and self . _shared_data is not None :
244267 with self ._lock :
245268 return any (job ['id' ] == search_id for job in self ._shared_data ['jobs' ])
246- else :
269+ elif not self . _use_multiprocessing and self . _fallback_lock is not None :
247270 with self ._fallback_lock :
248271 return any (job ['id' ] == search_id for job in self ._fallback_jobs )
272+ return False
0 commit comments