mirror of
https://github.com/wassname/cachier.git
synced 2026-09-09 11:19:08 +08:00
Merge pull request #8 from MichaelRazum/master
Added RecalculationNeeded Exception
This commit is contained in:
+9
-5
@@ -30,7 +30,7 @@ except ImportError: # we're in python 2.x
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
from .pickle_core import _PickleCore
|
||||
from .mongo_core import _MongoCore
|
||||
from .mongo_core import _MongoCore, RecalculationNeeded
|
||||
|
||||
|
||||
|
||||
@@ -82,8 +82,6 @@ def _calc_entry(core, key, func, args, kwds):
|
||||
finally:
|
||||
core.mark_entry_not_calculated(key)
|
||||
|
||||
|
||||
|
||||
def cachier(stale_after=None, next_time=False, pickle_reload=True,
|
||||
mongetter=None):
|
||||
"""A persistent, stale-free memoization decorator.
|
||||
@@ -156,7 +154,10 @@ def cachier(stale_after=None, next_time=False, pickle_reload=True,
|
||||
_print('Returning stale.')
|
||||
return entry['value'] # return stale val
|
||||
_print('Already calc. Waiting on change.')
|
||||
return core.wait_on_entry_calc(key)
|
||||
try:
|
||||
return core.wait_on_entry_calc(key)
|
||||
except RecalculationNeeded:
|
||||
return _calc_entry(core, key, func, args, kwds)
|
||||
if next_time:
|
||||
_print('Async calc and return stale')
|
||||
try:
|
||||
@@ -173,7 +174,10 @@ def cachier(stale_after=None, next_time=False, pickle_reload=True,
|
||||
return entry['value']
|
||||
if entry['being_calculated']:
|
||||
_print('No value but being calculated. Waiting.')
|
||||
return core.wait_on_entry_calc(key)
|
||||
try:
|
||||
return core.wait_on_entry_calc(key)
|
||||
except RecalculationNeeded:
|
||||
return _calc_entry(core, key, func, args, kwds)
|
||||
_print('No entry found. No current calc. Calling like a boss.')
|
||||
return _calc_entry(core, key, func, args, kwds)
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ from .base_core import _BaseCore
|
||||
|
||||
MONGO_SLEEP_DURATION_IN_SEC = 1
|
||||
|
||||
class RecalculationNeeded(Exception):
|
||||
pass
|
||||
|
||||
class _MongoCore(_BaseCore):
|
||||
|
||||
@@ -126,6 +128,8 @@ class _MongoCore(_BaseCore):
|
||||
while True:
|
||||
time.sleep(MONGO_SLEEP_DURATION_IN_SEC)
|
||||
key, entry = self.get_entry_by_key(key)
|
||||
if entry is None:
|
||||
raise RecalculationNeeded()
|
||||
if entry is not None and not entry['being_calculated']:
|
||||
return entry['value']
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Testing the MongoDB core of cachier."""
|
||||
|
||||
import datetime
|
||||
import sys
|
||||
from random import random
|
||||
from datetime import timedelta
|
||||
@@ -15,8 +16,7 @@ from pymongo.mongo_client import MongoClient
|
||||
from pymongo.errors import OperationFailure
|
||||
|
||||
from cachier import cachier
|
||||
from cachier.mongo_core import _MongoCore
|
||||
|
||||
from cachier.mongo_core import _MongoCore, RecalculationNeeded
|
||||
|
||||
_TEST_HOST = 'ds119508.mlab.com'
|
||||
_TEST_PORT = 19508
|
||||
@@ -163,3 +163,43 @@ def test_mongo_write_failure():
|
||||
def test_mongo_clear_being_calculated():
|
||||
"""Testing MongoDB core clear_being_calculated."""
|
||||
_func_w_bad_mongo.clear_being_calculated()
|
||||
|
||||
|
||||
def test_stalled_mongo_db_cache():
|
||||
@cachier(mongetter=_test_mongetter)
|
||||
def _stalled_func():
|
||||
return 1
|
||||
core = _MongoCore(_test_mongetter, None, False)
|
||||
core.set_func(_stalled_func)
|
||||
core.clear_cache()
|
||||
with pytest.raises(RecalculationNeeded):
|
||||
core.wait_on_entry_calc(key=None)
|
||||
|
||||
def test_stalled_mong_db_core(monkeypatch):
|
||||
def mock_get_entry(self, args, kwargs):
|
||||
return "key", {'being_calculated': True}
|
||||
def mock_get_entry_by_key(self, key):
|
||||
return "key", None
|
||||
monkeypatch.setattr("cachier.mongo_core._MongoCore.get_entry", mock_get_entry )
|
||||
monkeypatch.setattr("cachier.mongo_core._MongoCore.get_entry_by_key", mock_get_entry_by_key )
|
||||
@cachier(mongetter=_test_mongetter)
|
||||
def _stalled_func():
|
||||
return 1
|
||||
res = _stalled_func()
|
||||
assert res == 1
|
||||
|
||||
def mock_get_entry_2(self, args, kwargs):
|
||||
return "key", {'being_calculated': True,
|
||||
"value": 1,
|
||||
"time": datetime.datetime.now() - datetime.timedelta(seconds=10)}
|
||||
monkeypatch.setattr("cachier.mongo_core._MongoCore.get_entry", mock_get_entry_2 )
|
||||
|
||||
stale_after = datetime.timedelta(seconds=1)
|
||||
@cachier(mongetter=_test_mongetter,stale_after=stale_after)
|
||||
def _stalled_func_2():
|
||||
""" Testing stalled function"""
|
||||
return 2
|
||||
res = _stalled_func_2()
|
||||
assert res == 2
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user