cachier 3.4.0__py3-none-any.whl → 3.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cachier/cores/pickle.py +78 -10
- cachier/version.info +1 -1
- {cachier-3.4.0.dist-info → cachier-3.4.1.dist-info}/METADATA +1 -1
- {cachier-3.4.0.dist-info → cachier-3.4.1.dist-info}/RECORD +8 -8
- {cachier-3.4.0.dist-info → cachier-3.4.1.dist-info}/WHEEL +0 -0
- {cachier-3.4.0.dist-info → cachier-3.4.1.dist-info}/entry_points.txt +0 -0
- {cachier-3.4.0.dist-info → cachier-3.4.1.dist-info}/licenses/LICENSE +0 -0
- {cachier-3.4.0.dist-info → cachier-3.4.1.dist-info}/top_level.txt +0 -0
cachier/cores/pickle.py
CHANGED
@@ -6,8 +6,10 @@
|
|
6
6
|
# Licensed under the MIT license:
|
7
7
|
# http://www.opensource.org/licenses/MIT-license
|
8
8
|
# Copyright (c) 2016, Shay Palachy <shaypal5@gmail.com>
|
9
|
+
import logging
|
9
10
|
import os
|
10
11
|
import pickle # for local caching
|
12
|
+
import time
|
11
13
|
from datetime import datetime
|
12
14
|
from typing import Any, Dict, Optional, Tuple, Union
|
13
15
|
|
@@ -51,12 +53,14 @@ class _PickleCore(_BaseCore):
|
|
51
53
|
if not entry._processing:
|
52
54
|
# print('stopping observer!')
|
53
55
|
self.value = entry.value
|
54
|
-
self.observer
|
56
|
+
if self.observer is not None:
|
57
|
+
self.observer.stop()
|
55
58
|
# else:
|
56
59
|
# print('NOT stopping observer... :(')
|
57
60
|
except AttributeError: # catching entry being None
|
58
61
|
self.value = None
|
59
|
-
self.observer
|
62
|
+
if self.observer is not None:
|
63
|
+
self.observer.stop()
|
60
64
|
|
61
65
|
def on_created(self, event) -> None:
|
62
66
|
"""A Watchdog Event Handler method.""" # noqa: D401
|
@@ -256,29 +260,93 @@ class _PickleCore(_BaseCore):
|
|
256
260
|
cache[key]._processing = False
|
257
261
|
self._save_cache(cache)
|
258
262
|
|
263
|
+
def _create_observer(self) -> Observer:
|
264
|
+
"""Create a new observer instance."""
|
265
|
+
return Observer()
|
266
|
+
|
267
|
+
def _cleanup_observer(self, observer: Observer) -> None:
|
268
|
+
"""Clean up observer properly."""
|
269
|
+
try:
|
270
|
+
if observer.is_alive():
|
271
|
+
observer.stop()
|
272
|
+
observer.join(timeout=1.0)
|
273
|
+
except Exception as e:
|
274
|
+
logging.debug("Observer cleanup failed: %s", e)
|
275
|
+
|
259
276
|
def wait_on_entry_calc(self, key: str) -> Any:
|
277
|
+
"""Wait for entry calculation to complete with inotify protection."""
|
260
278
|
if self.separate_files:
|
261
279
|
entry = self._load_cache_by_key(key)
|
262
280
|
filename = f"{self.cache_fname}_{key}"
|
263
281
|
else:
|
264
282
|
with self.lock:
|
265
|
-
entry = self.get_cache_dict()
|
283
|
+
entry = self.get_cache_dict().get(key)
|
266
284
|
filename = self.cache_fname
|
285
|
+
|
267
286
|
if entry and not entry._processing:
|
268
287
|
return entry.value
|
288
|
+
|
289
|
+
# Try to use inotify-based waiting
|
290
|
+
try:
|
291
|
+
return self._wait_with_inotify(key, filename)
|
292
|
+
except OSError as e:
|
293
|
+
if "inotify instance limit reached" in str(e):
|
294
|
+
# Fall back to polling if inotify limit is reached
|
295
|
+
return self._wait_with_polling(key)
|
296
|
+
else:
|
297
|
+
raise
|
298
|
+
|
299
|
+
def _wait_with_inotify(self, key: str, filename: str) -> Any:
|
300
|
+
"""Wait for calculation using inotify with proper cleanup."""
|
269
301
|
event_handler = _PickleCore.CacheChangeHandler(
|
270
302
|
filename=filename, core=self, key=key
|
271
303
|
)
|
272
|
-
|
304
|
+
|
305
|
+
observer = self._create_observer()
|
273
306
|
event_handler.inject_observer(observer)
|
274
|
-
|
275
|
-
|
307
|
+
|
308
|
+
try:
|
309
|
+
observer.schedule(
|
310
|
+
event_handler, path=self.cache_dir, recursive=True
|
311
|
+
)
|
312
|
+
observer.start()
|
313
|
+
|
314
|
+
time_spent = 0
|
315
|
+
while observer.is_alive():
|
316
|
+
observer.join(timeout=1.0)
|
317
|
+
time_spent += 1
|
318
|
+
self.check_calc_timeout(time_spent)
|
319
|
+
|
320
|
+
# Check if calculation is complete
|
321
|
+
if event_handler.value is not None:
|
322
|
+
break
|
323
|
+
|
324
|
+
return event_handler.value
|
325
|
+
finally:
|
326
|
+
# Always cleanup the observer
|
327
|
+
self._cleanup_observer(observer)
|
328
|
+
|
329
|
+
def _wait_with_polling(self, key: str) -> Any:
|
330
|
+
"""Fallback method using polling instead of inotify."""
|
276
331
|
time_spent = 0
|
277
|
-
while
|
278
|
-
|
332
|
+
while True:
|
333
|
+
time.sleep(1) # Poll every 1 second (matching other cores)
|
279
334
|
time_spent += 1
|
280
|
-
|
281
|
-
|
335
|
+
|
336
|
+
try:
|
337
|
+
if self.separate_files:
|
338
|
+
entry = self._load_cache_by_key(key)
|
339
|
+
else:
|
340
|
+
with self.lock:
|
341
|
+
entry = self.get_cache_dict().get(key)
|
342
|
+
|
343
|
+
if entry and not entry._processing:
|
344
|
+
return entry.value
|
345
|
+
|
346
|
+
self.check_calc_timeout(time_spent)
|
347
|
+
except (FileNotFoundError, EOFError):
|
348
|
+
# Continue polling even if there are file errors
|
349
|
+
pass
|
282
350
|
|
283
351
|
def clear_cache(self) -> None:
|
284
352
|
if self.separate_files:
|
cachier/version.info
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.4.
|
1
|
+
3.4.1
|
@@ -5,17 +5,17 @@ cachier/_version.py,sha256=jnPPRn_qmjNi-qmQjlHnzNGf3LSBTYkMmJdGjxMTOBM,1089
|
|
5
5
|
cachier/config.py,sha256=6hyQtn9T6UXu2UQhKJltWT0Nu4OBS4ION1x7Lt1i8Og,3838
|
6
6
|
cachier/core.py,sha256=W1O_a9rkgsErG3spVPZpnfRu9k0MbV94rGkv79KDgBA,16243
|
7
7
|
cachier/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
-
cachier/version.info,sha256=
|
8
|
+
cachier/version.info,sha256=zHFPXgIkp4MR9INen7uI5pujX2Xn3Vy32GyrtKhLvXI,6
|
9
9
|
cachier/cores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
cachier/cores/base.py,sha256=s7qgmDJA4LGub6ydGfMk9vVJW4fgeU0EXl-9gmpuh28,3683
|
11
11
|
cachier/cores/memory.py,sha256=fsvqq9rwwmAaMBvYo-oUNAxB6UOyfBpuf8ACW_XTaU0,3572
|
12
12
|
cachier/cores/mongo.py,sha256=wVit36jQeNkP1KyxMtm6jDglazpdORYzTOPJ0q10BWI,4979
|
13
|
-
cachier/cores/pickle.py,sha256=
|
13
|
+
cachier/cores/pickle.py,sha256=L_IwKSnskJqlGsulkhMQukKdylq_ghpyG5BvdB_7WzM,12901
|
14
14
|
cachier/cores/redis.py,sha256=rWrkEwWPzfFvH1eLkgBdhzxqPtJtx6N_sYcqRPy_P9Y,7553
|
15
15
|
cachier/cores/sql.py,sha256=nuf2-Szo7VTPRa7IC3JGWEtGsBtdkIrx0bhOm3U0mfE,9895
|
16
|
-
cachier-3.4.
|
17
|
-
cachier-3.4.
|
18
|
-
cachier-3.4.
|
19
|
-
cachier-3.4.
|
20
|
-
cachier-3.4.
|
21
|
-
cachier-3.4.
|
16
|
+
cachier-3.4.1.dist-info/licenses/LICENSE,sha256=-2WrMJkIa0gVP6YQHXXDT7ws-S3M2NEVEF4XF3K8qrY,1069
|
17
|
+
cachier-3.4.1.dist-info/METADATA,sha256=__yRE190T79aUMOS9uaXSWj8q-YJp-3LpwLoLpOZxt8,24446
|
18
|
+
cachier-3.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
19
|
+
cachier-3.4.1.dist-info/entry_points.txt,sha256=x4Y7t6Y0Qev_3fgG-Jv7TrsvVdJty3FnGAdkT8-_5mY,49
|
20
|
+
cachier-3.4.1.dist-info/top_level.txt,sha256=_rW_HiJumDCch67YT-WAgzcyvKg5RiYDMZq9d-0ZpaE,8
|
21
|
+
cachier-3.4.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|