diff --git a/cacheback/base.py b/cacheback/base.py index 4747ccd..0c0c8b4 100644 --- a/cacheback/base.py +++ b/cacheback/base.py @@ -312,6 +312,21 @@ def refresh(self, *args, **kwargs): self.store(self.key(*args, **kwargs), self.expiry(*args, **kwargs), result) return result + def should_refresh(self, *args, **kwargs): + """ + Verify if the cache should be refreshed + """ + expiry, data = self.cache.get(self.key(*args, **kwargs), (None, None)) + + if data is None: + return True + + delta = expiry - time.time() + if delta > 0: + return False + + return True + def async_refresh(self, *args, **kwargs): """ 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_ logger.info( "Using %s with constructor args %r and kwargs %r", klass_str, obj_args, obj_kwargs ) + + job = klass(*obj_args, **obj_kwargs) + if not job.should_refresh(*call_args, **call_kwargs): + logger.info('Refresh escaped, cache is already fresh.') + return + logger.info("Calling refresh with args %r and kwargs %r", call_args, call_kwargs) start = time.time() try: - klass(*obj_args, **obj_kwargs).refresh(*call_args, **call_kwargs) + job.refresh(*call_args, **call_kwargs) except Exception as e: logger.exception("Error running job: '%s'", e) else: diff --git a/tests/test_base_job.py b/tests/test_base_job.py index 48753a1..420c53e 100644 --- a/tests/test_base_job.py +++ b/tests/test_base_job.py @@ -291,3 +291,16 @@ def test_job_refresh_perform_error(self, logger_mock): def test_job_refresh(self): Job.perform_async_refresh('tests.test_base_job.EmptyDummyJob', (), {}, ('foo',), {}) assert EmptyDummyJob().get('foo') is not None + + @pytest.mark.redis_required + @mock.patch('tests.test_base_job.EmptyDummyJob.fetch', return_value='foo') + def test_escape_job_refresh(self, fetch_mock, rq_burst): + job = EmptyDummyJob() + job.task_options = {'is_async': False} + + job.async_refresh('foo') + job.async_refresh('foo') + + rq_burst() + + assert fetch_mock.call_count == 1