diff --git a/cacheops/getset.py b/cacheops/getset.py index 3b40e78e..e302d26b 100644 --- a/cacheops/getset.py +++ b/cacheops/getset.py @@ -1,6 +1,7 @@ from contextlib import contextmanager import hashlib import json +import random from .conf import settings from .redis import redis_client, handle_connection_failure, load_script @@ -35,6 +36,8 @@ def cache_thing(prefix, cache_key, data, cond_dnfs, timeout, dbs=(), precall_key json.dumps(schemes), json.dumps(conj_keys), timeout, + # Need to pass it from here since random inside is not seeded in Redis pre 7.0 + random.random(), expected_checksum, ] ) diff --git a/cacheops/lua/cache_thing.lua b/cacheops/lua/cache_thing.lua index f4468f41..900062e6 100644 --- a/cacheops/lua/cache_thing.lua +++ b/cacheops/lua/cache_thing.lua @@ -50,13 +50,13 @@ for db_table, disj in pairs(dnfs) do -- REDIS_7 redis.call('expire', conj_key, timeout, 'gt') -- /REDIS_7 - -- REDIS_6 + -- REDIS_4 local conj_ttl = redis.call('ttl', conj_key) if conj_ttl < timeout then -- We set conj_key life with a margin over key life to call expire rarer -- And add few extra seconds to be extra safe redis.call('expire', conj_key, timeout * 2 + 10) end - -- /REDIS_6 + -- /REDIS_4 end end diff --git a/cacheops/lua/cache_thing_insideout.lua b/cacheops/lua/cache_thing_insideout.lua index 21f40820..3f0608da 100644 --- a/cacheops/lua/cache_thing_insideout.lua +++ b/cacheops/lua/cache_thing_insideout.lua @@ -4,7 +4,8 @@ local data = ARGV[1] local schemes = cjson.decode(ARGV[2]) local conj_keys = cjson.decode(ARGV[3]) local timeout = tonumber(ARGV[4]) -local expected_checksum = ARGV[5] +local rnd = ARGV[5] -- A new value for empty stamps +local expected_checksum = ARGV[6] -- Ensure schemes are known for db_table, _schemes in pairs(schemes) do @@ -13,23 +14,31 @@ end -- Fill in invalidators and collect stamps local stamps = {} -local rnd = tostring(math.random()) -- A new value for empty stamps for _, conj_key in ipairs(conj_keys) do + -- REDIS_7 local stamp = redis.call('set', conj_key, rnd, 'nx', 'get') or rnd + -- /REDIS_7 + -- REDIS_4 + local stamp = redis.call('get', conj_key) + if not stamp then + stamp = rnd + redis.call('set', conj_key, rnd) + end + -- /REDIS_4 table.insert(stamps, stamp) -- NOTE: an invalidator should live longer than any key it references. -- So we update its ttl on every key if needed. -- REDIS_7 redis.call('expire', conj_key, timeout, 'gt') -- /REDIS_7 - -- REDIS_6 + -- REDIS_4 local conj_ttl = redis.call('ttl', conj_key) if conj_ttl < timeout then -- We set conj_key life with a margin over key life to call expire rarer -- And add few extra seconds to be extra safe redis.call('expire', conj_key, timeout * 2 + 10) end - -- /REDIS_6 + -- /REDIS_4 end -- Write data to cache along with a checksum of the stamps to see if any of them changed diff --git a/cacheops/redis.py b/cacheops/redis.py index e9bc78ae..8057e162 100644 --- a/cacheops/redis.py +++ b/cacheops/redis.py @@ -63,7 +63,7 @@ def load_script(name): with open(filename) as f: code = f.read() if is_redis_7(): - code = re.sub(r'REDIS_6.*?/REDIS_6', '', code, flags=re.S) + code = re.sub(r'REDIS_4.*?/REDIS_4', '', code, flags=re.S) else: code = re.sub(r'REDIS_7.*?/REDIS_7', '', code, flags=re.S) return redis_client.register_script(code)