Skip to content

Commit eabb15d

Browse files
committed
Escape job refresh
1 parent c7ddf0a commit eabb15d

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

cacheback/base.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,21 @@ def refresh(self, *args, **kwargs):
312312
self.store(self.key(*args, **kwargs), self.expiry(*args, **kwargs), result)
313313
return result
314314

315+
def should_refresh(self, *args, **kwargs):
316+
"""
317+
Verify if the cache should be refreshed
318+
"""
319+
expiry, data = self.cache.get(self.key(*args, **kwargs), (None, None))
320+
321+
if data is None:
322+
return True
323+
324+
delta = expiry - time.time()
325+
if delta > 0:
326+
return False
327+
328+
return True
329+
315330
def async_refresh(self, *args, **kwargs):
316331
"""
317332
Trigger an asynchronous job to refresh the cache
@@ -479,10 +494,16 @@ def perform_async_refresh(cls, klass_str, obj_args, obj_kwargs, call_args, call_
479494
logger.info(
480495
"Using %s with constructor args %r and kwargs %r", klass_str, obj_args, obj_kwargs
481496
)
497+
498+
job = klass(*obj_args, **obj_kwargs)
499+
if not job.should_refresh(*call_args, **call_kwargs):
500+
logger.info('Refresh escaped, cache is already fresh.')
501+
return
502+
482503
logger.info("Calling refresh with args %r and kwargs %r", call_args, call_kwargs)
483504
start = time.time()
484505
try:
485-
klass(*obj_args, **obj_kwargs).refresh(*call_args, **call_kwargs)
506+
job.refresh(*call_args, **call_kwargs)
486507
except Exception as e:
487508
logger.exception("Error running job: '%s'", e)
488509
else:

tests/test_base_job.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,16 @@ def test_job_refresh_perform_error(self, logger_mock):
291291
def test_job_refresh(self):
292292
Job.perform_async_refresh('tests.test_base_job.EmptyDummyJob', (), {}, ('foo',), {})
293293
assert EmptyDummyJob().get('foo') is not None
294+
295+
@pytest.mark.redis_required
296+
@mock.patch('tests.test_base_job.EmptyDummyJob.fetch', return_value='foo')
297+
def test_escape_job_refresh(self, fetch_mock, rq_burst):
298+
job = EmptyDummyJob()
299+
job.task_options = {'is_async': False}
300+
301+
job.async_refresh('foo')
302+
job.async_refresh('foo')
303+
304+
rq_burst()
305+
306+
assert fetch_mock.call_count == 1

0 commit comments

Comments
 (0)