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 =
'5.0.0'
Class Method Summary collapse
-
.cached?(*key_parts) ⇒ Boolean
Check if a key is cached already.
-
.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.
-
.logger ⇒ Logger
The logger.
- .logger=(logger) ⇒ Object
- .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
.cached?(*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 cached already
87 88 89 90 |
# File 'lib/lock_and_cache.rb', line 87 def LockAndCache.cached?(*key_parts) key = LockAndCache::Key.new key_parts key.cached? end |
.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
71 72 73 74 |
# File 'lib/lock_and_cache.rb', line 71 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.
49 50 51 |
# File 'lib/lock_and_cache.rb', line 49 def LockAndCache.flush storage.flushdb end |
.heartbeat_expires=(seconds) ⇒ Object
Can be overridden by putting ‘heartbeat_expires:` in your call to `#lock_and_cache`
107 108 109 110 111 |
# File 'lib/lock_and_cache.rb', line 107 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.
60 61 62 63 64 65 66 |
# File 'lib/lock_and_cache.rb', line 60 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
79 80 81 82 |
# File 'lib/lock_and_cache.rb', line 79 def LockAndCache.locked?(*key_parts) key = LockAndCache::Key.new key_parts key.locked? end |
.logger ⇒ Logger
40 41 42 |
# File 'lib/lock_and_cache.rb', line 40 def LockAndCache.logger @logger end |
.logger=(logger) ⇒ Object
35 36 37 |
# File 'lib/lock_and_cache.rb', line 35 def LockAndCache.logger=(logger) @logger = logger end |
.max_lock_wait=(seconds) ⇒ Object
Can be overridden by putting ‘max_lock_wait:` in your call to `#lock_and_cache`
95 96 97 |
# File 'lib/lock_and_cache.rb', line 95 def LockAndCache.max_lock_wait=(seconds) @max_lock_wait = seconds.to_f end |
.storage ⇒ Redis
30 31 32 |
# File 'lib/lock_and_cache.rb', line 30 def LockAndCache.storage @storage end |
.storage=(redis_connection) ⇒ Object
24 25 26 27 |
# 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 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.
145 146 147 148 149 150 |
# File 'lib/lock_and_cache.rb', line 145 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
129 130 131 132 |
# File 'lib/lock_and_cache.rb', line 129 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.
121 122 123 124 |
# File 'lib/lock_and_cache.rb', line 121 def lock_and_cache_locked?(method_id, *key_parts) key = LockAndCache::Key.new key_parts, context: self, method_id: method_id key.locked? end |