Implement cache lock on commit for JsonDB
This commit is contained in:
parent
bccfcff19d
commit
14971857c7
|
@ -55,6 +55,10 @@ def get(document, cache=True):
|
|||
def commit(document, data, cache=True):
|
||||
"""Insert/update a document in the DB."""
|
||||
|
||||
# Only allow one commit at a time.
|
||||
if not lock_cache(document):
|
||||
return
|
||||
|
||||
# Need to create the file?
|
||||
path = mkpath(document)
|
||||
if not os.path.isfile(path):
|
||||
|
@ -78,6 +82,9 @@ def commit(document, data, cache=True):
|
|||
# Write the JSON.
|
||||
write_json(path, data)
|
||||
|
||||
# Release the lock.
|
||||
unlock_cache(document)
|
||||
|
||||
|
||||
def delete(document):
|
||||
"""Delete a document from the DB."""
|
||||
|
@ -225,3 +232,34 @@ def del_cache(key):
|
|||
key = Config.db.redis_prefix + key
|
||||
client = get_redis()
|
||||
client.delete(key)
|
||||
|
||||
|
||||
def lock_cache(key, timeout=5, expire=20):
|
||||
"""Cache level 'file locking' implementation.
|
||||
|
||||
The `key` will be automatically suffixed with `_lock`.
|
||||
The `timeout` is the max amount of time to wait for a lock.
|
||||
The `expire` is how long a lock may exist before it's considered stale.
|
||||
|
||||
Returns True on success, None on failure to acquire lock."""
|
||||
lock_key = key + "_lock"
|
||||
begin = int(time.time())
|
||||
|
||||
lock = get_cache(lock_key)
|
||||
while lock:
|
||||
time.sleep(0.2)
|
||||
lock = get_cache(lock_key)
|
||||
if int(time.time()) - begin >= timeout:
|
||||
handle_exception(
|
||||
Exception("Redis key lock timed out waiting for {}".format(key))
|
||||
)
|
||||
return None
|
||||
|
||||
# Take the lock.
|
||||
set_cache(lock_key, time.time(), expire)
|
||||
return True
|
||||
|
||||
|
||||
def unlock_cache(key):
|
||||
"""Release the lock on a cache key."""
|
||||
del_cache(key + "_lock")
|
||||
|
|
Loading…
Reference in New Issue
Block a user