Module: LockAndCache
- Defined in:
- lib/lock_and_cache.rb,
lib/lock_and_cache/key.rb,
lib/lock_and_cache/action.rb,
lib/lock_and_cache/version.rb
Overview
Lock and cache using redis!
Most caching libraries don’t do locking, meaning that >1 process can be calculating a cached value at the same time. Since you presumably cache things because they cost CPU, database reads, or money, doesn’t it make sense to lock while caching?
Defined Under Namespace
Classes: TimeoutWaitingForLock
Constant Summary collapse
- DEFAULT_MAX_LOCK_WAIT =
1 day in seconds
60 * 60 * 24
- DEFAULT_HEARTBEAT_EXPIRES =
32 seconds
32- VERSION =
'3.0.0'
Class Method Summary collapse
-
.clear(*key_parts) ⇒ Object
Clear a single key.
-
.flush ⇒ Object
Flush LockAndCache’s storage.
- .heartbeat_expires=(seconds) ⇒ Object
-
.lock_and_cache(*key_parts_and_options, &blk) ⇒ Object
Lock and cache based on a key.
-
.locked?(*key_parts) ⇒ Boolean
Check if a key is locked.
- .max_lock_wait=(seconds) ⇒ Object
-
.storage ⇒ Redis
The redis connection used for lock and cached value storage.
- .storage=(redis_connection) ⇒ Object
Instance Method Summary collapse
-
#lock_and_cache(*key_parts_and_options, &blk) ⇒ Object
Lock and cache a method given key parts.
-
#lock_and_cache_clear(method_id, *key_parts) ⇒ Object
Clear a lock and cache given exactly the method and exactly the same arguments.
-
#lock_and_cache_locked?(method_id, *key_parts) ⇒ Boolean
Check if a method is locked on an object.
Class Method Details
.clear(*key_parts) ⇒ Object
Standalone mode. See also “context mode,” where you mix LockAndCache into a class and call it from within its methods.
Clear a single key
62 63 64 65 |
# File 'lib/lock_and_cache.rb', line 62 def LockAndCache.clear(*key_parts) key = LockAndCache::Key.new key_parts key.clear end |
.flush ⇒ Object
If you are sharing a redis database, it will clear it…
If you want to clear a single key, try ‘LockAndCache.clear(key)` (standalone mode) or `#lock_and_cache_clear(method_id, *key_parts)` in context mode.
Flush LockAndCache’s storage.
40 41 42 |
# File 'lib/lock_and_cache.rb', line 40 def LockAndCache.flush storage.flushdb end |
.heartbeat_expires=(seconds) ⇒ Object
Can be overridden by putting ‘heartbeat_expires:` in your call to `#lock_and_cache`
90 91 92 93 94 |
# File 'lib/lock_and_cache.rb', line 90 def LockAndCache.heartbeat_expires=(seconds) memo = seconds.to_f raise "heartbeat_expires must be greater than 2 seconds" unless memo >= 2 @heartbeat_expires = memo end |
.lock_and_cache(*key_parts_and_options, &blk) ⇒ Object
Standalone mode. See also “context mode,” where you mix LockAndCache into a class and call it from within its methods.
A single hash arg is treated as a cache key, e.g. ‘LockAndCache.lock_and_cache(foo: :bar, expires: 100)` will be treated as a cache key of `foo: :bar, expires: 100` (which is probably wrong!!!). Try `LockAndCache.lock_and_cache({ foo: :bar }, expires: 100)` instead. This is the opposite of context mode.
Lock and cache based on a key.
51 52 53 54 55 56 57 |
# File 'lib/lock_and_cache.rb', line 51 def LockAndCache.lock_and_cache(*, &blk) = (.last.is_a?(Hash) && .length > 1) ? .pop : {} raise "need a cache key" unless .length > 0 key = LockAndCache::Key.new action = LockAndCache::Action.new key, , blk action.perform end |
.locked?(*key_parts) ⇒ Boolean
Standalone mode. See also “context mode,” where you mix LockAndCache into a class and call it from within its methods.
Check if a key is locked
70 71 72 73 |
# File 'lib/lock_and_cache.rb', line 70 def LockAndCache.locked?(*key_parts) key = LockAndCache::Key.new key_parts key.locked? end |
.max_lock_wait=(seconds) ⇒ Object
Can be overridden by putting ‘max_lock_wait:` in your call to `#lock_and_cache`
78 79 80 |
# File 'lib/lock_and_cache.rb', line 78 def LockAndCache.max_lock_wait=(seconds) @max_lock_wait = seconds.to_f end |
.storage ⇒ Redis
Returns The redis connection used for lock and cached value storage.
31 32 33 |
# File 'lib/lock_and_cache.rb', line 31 def LockAndCache.storage @storage end |
.storage=(redis_connection) ⇒ Object
24 25 26 27 28 |
# File 'lib/lock_and_cache.rb', line 24 def LockAndCache.storage=(redis_connection) raise "only redis for now" unless redis_connection.class.to_s == 'Redis' @storage = redis_connection @lock_manager = Redlock::Client.new [redis_connection], retry_count: 1 end |
Instance Method Details
#lock_and_cache(*key_parts_and_options, &blk) ⇒ Object
Subject mode - this is expected to be called on an object whose class has LockAndCache mixed in. See also standalone mode.
A single hash arg is treated as an options hash, e.g. ‘lock_and_cache(expires: 100)` will be treated as options `expires: 100`. This is the opposite of standalone mode.
Lock and cache a method given key parts.
The cache key will automatically include the class name of the object calling it (the context!) and the name of the method it is called from.
133 134 135 136 137 138 |
# File 'lib/lock_and_cache.rb', line 133 def lock_and_cache(*, &blk) = .last.is_a?(Hash) ? .pop : {} key = LockAndCache::Key.new , context: self, caller: caller action = LockAndCache::Action.new key, , blk action.perform end |
#lock_and_cache_clear(method_id, *key_parts) ⇒ Object
Subject mode - this is expected to be called on an object whose class has LockAndCache mixed in. See also standalone mode.
Clear a lock and cache given exactly the method and exactly the same arguments
117 118 119 120 |
# File 'lib/lock_and_cache.rb', line 117 def lock_and_cache_clear(method_id, *key_parts) key = LockAndCache::Key.new key_parts, context: self, method_id: method_id key.clear end |
#lock_and_cache_locked?(method_id, *key_parts) ⇒ Boolean
Subject mode - this is expected to be called on an object whose class has LockAndCache mixed in. See also standalone mode.
Check if a method is locked on an object.
109 110 111 112 |
# File 'lib/lock_and_cache.rb', line 109 def lock_and_cache_locked?(method_id, *key_parts) key = LockAndCache::Key.new key_parts, context: self, method_id: method_id key.locked? end |