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 =
"7.0.0"
Class Method Summary collapse
-
.cache_storage ⇒ Redis
The redis connection used for cached value storage.
- .cache_storage=(redis_connection) ⇒ Object
-
.cached?(*key_parts) ⇒ Boolean
Check if a key is cached already.
-
.clear(*key_parts) ⇒ Object
Clear a single key.
-
.flush_cache ⇒ Object
Flush LockAndCache’s cached value storage.
-
.flush_locks ⇒ Object
Flush LockAndCache’s lock storage.
- .heartbeat_expires=(seconds) ⇒ Object
-
.lock_and_cache(*key_parts_and_options, &blk) ⇒ Object
Lock and cache based on a key.
-
.lock_storage ⇒ Redis
The redis connection used for lock and cached value storage.
- .lock_storage=(redis_connection) ⇒ Object
-
.locked?(*key_parts) ⇒ Boolean
Check if a key is locked.
-
.logger ⇒ Logger
The logger.
- .logger=(logger) ⇒ Object
- .max_lock_wait=(seconds) ⇒ 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
.cache_storage ⇒ Redis
Returns The redis connection used for cached value storage.
41 42 43 |
# File 'lib/lock_and_cache.rb', line 41 def LockAndCache.cache_storage @cache_storage end |
.cache_storage=(redis_connection) ⇒ Object
35 36 37 38 |
# File 'lib/lock_and_cache.rb', line 35 def LockAndCache.cache_storage=(redis_connection) raise "only redis for now" unless redis_connection.class.to_s == 'Redis' @cache_storage = redis_connection end |
.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
107 108 109 110 |
# File 'lib/lock_and_cache.rb', line 107 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
91 92 93 94 |
# File 'lib/lock_and_cache.rb', line 91 def LockAndCache.clear(*key_parts) key = LockAndCache::Key.new key_parts key.clear end |
.flush_cache ⇒ 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 cached value storage.
60 61 62 |
# File 'lib/lock_and_cache.rb', line 60 def LockAndCache.flush_cache cache_storage.flushdb end |
.flush_locks ⇒ 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 lock storage.
69 70 71 |
# File 'lib/lock_and_cache.rb', line 69 def LockAndCache.flush_locks lock_storage.flushdb end |
.heartbeat_expires=(seconds) ⇒ Object
Can be overridden by putting ‘heartbeat_expires:` in your call to `#lock_and_cache`
127 128 129 130 131 |
# File 'lib/lock_and_cache.rb', line 127 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.
80 81 82 83 84 85 86 |
# File 'lib/lock_and_cache.rb', line 80 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 |
.lock_storage ⇒ Redis
Returns The redis connection used for lock and cached value storage.
30 31 32 |
# File 'lib/lock_and_cache.rb', line 30 def LockAndCache.lock_storage @lock_storage end |
.lock_storage=(redis_connection) ⇒ Object
24 25 26 27 |
# File 'lib/lock_and_cache.rb', line 24 def LockAndCache.lock_storage=(redis_connection) raise "only redis for now" unless redis_connection.class.to_s == 'Redis' @lock_storage = redis_connection 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
99 100 101 102 |
# File 'lib/lock_and_cache.rb', line 99 def LockAndCache.locked?(*key_parts) key = LockAndCache::Key.new key_parts key.locked? end |
.logger ⇒ Logger
Returns The logger.
51 52 53 |
# File 'lib/lock_and_cache.rb', line 51 def LockAndCache.logger @logger end |
.logger=(logger) ⇒ Object
46 47 48 |
# File 'lib/lock_and_cache.rb', line 46 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`
115 116 117 |
# File 'lib/lock_and_cache.rb', line 115 def LockAndCache.max_lock_wait=(seconds) @max_lock_wait = seconds.to_f 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.
165 166 167 168 169 170 |
# File 'lib/lock_and_cache.rb', line 165 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
149 150 151 152 |
# File 'lib/lock_and_cache.rb', line 149 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.
141 142 143 144 |
# File 'lib/lock_and_cache.rb', line 141 def lock_and_cache_locked?(method_id, *key_parts) key = LockAndCache::Key.new key_parts, context: self, method_id: method_id key.locked? end |