Module: LockAndCacheMsgpack
- Defined in:
- lib/lock_and_cache_msgpack.rb,
lib/lock_and_cache_msgpack/key.rb,
lib/lock_and_cache_msgpack/action.rb,
lib/lock_and_cache_msgpack/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: Action, Key, TimeoutWaitingForLock
Constant Summary collapse
- DEFAULT_MAX_LOCK_WAIT =
1 day in seconds
60 * 60 * 24
- DEFAULT_HEARTBEAT_EXPIRES =
32 seconds
32- VERSION =
'4.1.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 LockAndCacheMsgpack’s storage.
- .heartbeat_expires ⇒ Object
- .heartbeat_expires=(seconds) ⇒ Object
-
.lock_and_cache(*key_parts_and_options, &blk) ⇒ Object
Lock and cache based on a key.
- .lock_manager ⇒ Object
-
.locked?(*key_parts) ⇒ Boolean
Check if a key is locked.
-
.logger ⇒ Logger
The logger.
- .logger=(logger) ⇒ Object
- .max_lock_wait ⇒ 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 LockAndCacheMsgpack into a class and call it from within its methods.
Check if a key is cached already
95 96 97 98 |
# File 'lib/lock_and_cache_msgpack.rb', line 95 def LockAndCacheMsgpack.cached?(*key_parts) key = LockAndCacheMsgpack::Key.new key_parts key.cached? end |
.clear(*key_parts) ⇒ Object
Standalone mode. See also “context mode,” where you mix LockAndCacheMsgpack into a class and call it from within its methods.
Clear a single key
79 80 81 82 |
# File 'lib/lock_and_cache_msgpack.rb', line 79 def LockAndCacheMsgpack.clear(*key_parts) key = LockAndCacheMsgpack::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 ‘LockAndCacheMsgpack.clear(key)` (standalone mode) or `#lock_and_cache_clear(method_id, *key_parts)` in context mode.
Flush LockAndCacheMsgpack’s storage.
57 58 59 |
# File 'lib/lock_and_cache_msgpack.rb', line 57 def LockAndCacheMsgpack.flush storage.flushdb end |
.heartbeat_expires ⇒ Object
122 123 124 |
# File 'lib/lock_and_cache_msgpack.rb', line 122 def LockAndCacheMsgpack.heartbeat_expires @heartbeat_expires || DEFAULT_HEARTBEAT_EXPIRES end |
.heartbeat_expires=(seconds) ⇒ Object
Can be overridden by putting ‘heartbeat_expires:` in your call to `#lock_and_cache`
115 116 117 118 119 |
# File 'lib/lock_and_cache_msgpack.rb', line 115 def LockAndCacheMsgpack.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 LockAndCacheMsgpack into a class and call it from within its methods.
A single hash arg is treated as a cache key, e.g. ‘LockAndCacheMsgpack.lock_and_cache(foo: :bar, expires: 100)` will be treated as a cache key of `foo: :bar, expires: 100` (which is probably wrong!!!). Try `LockAndCacheMsgpack.lock_and_cache({ foo: :bar }, expires: 100)` instead. This is the opposite of context mode.
Lock and cache based on a key.
68 69 70 71 72 73 74 |
# File 'lib/lock_and_cache_msgpack.rb', line 68 def LockAndCacheMsgpack.lock_and_cache(*, &blk) = (.last.is_a?(Hash) && .length > 1) ? .pop : {} raise "need a cache key" unless .length > 0 key = LockAndCacheMsgpack::Key.new action = LockAndCacheMsgpack::Action.new key, , blk action.perform end |
.lock_manager ⇒ Object
127 128 129 |
# File 'lib/lock_and_cache_msgpack.rb', line 127 def LockAndCacheMsgpack.lock_manager @lock_manager end |
.locked?(*key_parts) ⇒ Boolean
Standalone mode. See also “context mode,” where you mix LockAndCacheMsgpack into a class and call it from within its methods.
Check if a key is locked
87 88 89 90 |
# File 'lib/lock_and_cache_msgpack.rb', line 87 def LockAndCacheMsgpack.locked?(*key_parts) key = LockAndCacheMsgpack::Key.new key_parts key.locked? end |
.logger ⇒ Logger
Returns The logger.
48 49 50 |
# File 'lib/lock_and_cache_msgpack.rb', line 48 def LockAndCacheMsgpack.logger @logger end |
.logger=(logger) ⇒ Object
43 44 45 |
# File 'lib/lock_and_cache_msgpack.rb', line 43 def LockAndCacheMsgpack.logger=(logger) @logger = logger end |
.max_lock_wait ⇒ Object
108 109 110 |
# File 'lib/lock_and_cache_msgpack.rb', line 108 def LockAndCacheMsgpack.max_lock_wait @max_lock_wait || DEFAULT_MAX_LOCK_WAIT end |
.max_lock_wait=(seconds) ⇒ Object
Can be overridden by putting ‘max_lock_wait:` in your call to `#lock_and_cache`
103 104 105 |
# File 'lib/lock_and_cache_msgpack.rb', line 103 def LockAndCacheMsgpack.max_lock_wait=(seconds) @max_lock_wait = seconds.to_f end |
.storage ⇒ Redis
Returns The redis connection used for lock and cached value storage.
32 33 34 35 36 37 38 39 40 |
# File 'lib/lock_and_cache_msgpack.rb', line 32 def LockAndCacheMsgpack.storage @storage ||= begin connection = @redis_connection.class == Proc ? @redis_connection.call : @redis_connection raise "only redis for now" unless connection.class.to_s == 'Redis' @lock_manager = Redlock::Client.new [connection], retry_count: 1 connection end end |
.storage=(redis_connection) ⇒ Object
27 28 29 |
# File 'lib/lock_and_cache_msgpack.rb', line 27 def LockAndCacheMsgpack.storage=(redis_connection) @redis_connection = 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 LockAndCacheMsgpack 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.
158 159 160 161 162 163 |
# File 'lib/lock_and_cache_msgpack.rb', line 158 def lock_and_cache(*, &blk) = .last.is_a?(Hash) ? .pop : {} key = LockAndCacheMsgpack::Key.new , context: self, caller: caller action = LockAndCacheMsgpack::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 LockAndCacheMsgpack mixed in. See also standalone mode.
Clear a lock and cache given exactly the method and exactly the same arguments
142 143 144 145 |
# File 'lib/lock_and_cache_msgpack.rb', line 142 def lock_and_cache_clear(method_id, *key_parts) key = LockAndCacheMsgpack::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 LockAndCacheMsgpack mixed in. See also standalone mode.
Check if a method is locked on an object.
134 135 136 137 |
# File 'lib/lock_and_cache_msgpack.rb', line 134 def lock_and_cache_locked?(method_id, *key_parts) key = LockAndCacheMsgpack::Key.new key_parts, context: self, method_id: method_id key.locked? end |