Class: Waitmate::Store::Redis
- Inherits:
-
Object
- Object
- Waitmate::Store::Redis
- Defined in:
- lib/waitmate/store/redis.rb
Overview
Redis-backed store contract implementation. All operations that touch capacity or ordering run inside atomic Lua scripts so concurrent callers cannot double-count or lose slots.
Per-queue data model:
waitmate:queue:{q} - sorted set keyed by enqueue timestamp (FIFO)
waitmate:waiting_expiry:{q} - sorted set keyed by expiry timestamp
waitmate:active:{q} - sorted set keyed by expiry timestamp
Constant Summary collapse
- KEY_PREFIX =
"waitmate"- LUA_SCRIPTS =
{ enqueue: <<~LUA, position: <<~LUA, active_count: <<~LUA, admit: <<~LUA, heartbeat: <<~LUA, expire_stale: <<~LUA local queue_key = KEYS[1] local expiry_key = KEYS[2] local active_key = KEYS[3] local now = tonumber(ARGV[1]) local expired_waiting = redis.call('ZRANGEBYSCORE', expiry_key, '-inf', now) for i = 1, #expired_waiting do redis.call('ZREM', queue_key, expired_waiting[i]) redis.call('ZREM', expiry_key, expired_waiting[i]) end local active_removed = redis.call('ZREMRANGEBYSCORE', active_key, '-inf', now) return {#expired_waiting, active_removed} LUA }.freeze
Instance Attribute Summary collapse
-
#redis ⇒ Object
readonly
Returns the value of attribute redis.
Instance Method Summary collapse
- #active_count(queue_name) ⇒ Object
- #admit(queue_name, max_concurrent, count: max_concurrent) ⇒ Object
- #enqueue(queue_name, identity, ttl: nil) ⇒ Object
- #expire_stale(queue_name) ⇒ Object
- #heartbeat(queue_name, identity, ttl: nil) ⇒ Object
-
#initialize(redis: nil, config: Waitmate.configuration) ⇒ Redis
constructor
A new instance of Redis.
- #position(queue_name, identity) ⇒ Object
- #release(queue_name, identity) ⇒ Object
Constructor Details
#initialize(redis: nil, config: Waitmate.configuration) ⇒ Redis
Returns a new instance of Redis.
161 162 163 164 165 166 167 168 169 |
# File 'lib/waitmate/store/redis.rb', line 161 def initialize(redis: nil, config: Waitmate.configuration) unless defined?(::Redis) raise ConfigurationError, "Redis gem is not available. Add `gem 'redis'` to your Gemfile to use the Redis adapter." end @config = config @redis = redis || ::Redis.new end |
Instance Attribute Details
#redis ⇒ Object (readonly)
Returns the value of attribute redis.
171 172 173 |
# File 'lib/waitmate/store/redis.rb', line 171 def redis @redis end |
Instance Method Details
#active_count(queue_name) ⇒ Object
195 196 197 198 199 200 201 |
# File 'lib/waitmate/store/redis.rb', line 195 def active_count(queue_name) eval_script( :active_count, keys: [active_key(queue_name)], argv: [] ) end |
#admit(queue_name, max_concurrent, count: max_concurrent) ⇒ Object
203 204 205 206 207 208 209 |
# File 'lib/waitmate/store/redis.rb', line 203 def admit(queue_name, max_concurrent, count: max_concurrent) eval_script( :admit, keys: [queue_key(queue_name), expiry_key(queue_name), active_key(queue_name)], argv: [, @config.queue_ttl, max_concurrent, count] ) end |
#enqueue(queue_name, identity, ttl: nil) ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/waitmate/store/redis.rb', line 173 def enqueue(queue_name, identity, ttl: nil) ttl ||= @config.queue_ttl now = expiry = now + ttl eval_script( :enqueue, keys: [queue_key(queue_name), expiry_key(queue_name), active_key(queue_name)], argv: [identity.to_s, now, expiry] ) end |
#expire_stale(queue_name) ⇒ Object
228 229 230 231 232 233 234 235 236 |
# File 'lib/waitmate/store/redis.rb', line 228 def expire_stale(queue_name) waiting, active = eval_script( :expire_stale, keys: [queue_key(queue_name), expiry_key(queue_name), active_key(queue_name)], argv: [] ) {waiting: waiting, active: active} end |
#heartbeat(queue_name, identity, ttl: nil) ⇒ Object
218 219 220 221 222 223 224 225 226 |
# File 'lib/waitmate/store/redis.rb', line 218 def heartbeat(queue_name, identity, ttl: nil) ttl ||= @config.queue_ttl result = eval_script( :heartbeat, keys: [queue_key(queue_name), expiry_key(queue_name), active_key(queue_name)], argv: [identity.to_s, , ttl] ) result == 1 end |
#position(queue_name, identity) ⇒ Object
185 186 187 188 189 190 191 192 193 |
# File 'lib/waitmate/store/redis.rb', line 185 def position(queue_name, identity) rank = eval_script( :position, keys: [queue_key(queue_name), expiry_key(queue_name), active_key(queue_name)], argv: [identity.to_s, ] ) (rank == -1) ? nil : rank end |
#release(queue_name, identity) ⇒ Object
211 212 213 214 215 216 |
# File 'lib/waitmate/store/redis.rb', line 211 def release(queue_name, identity) result = with_redis do |redis| redis.zrem(active_key(queue_name), identity.to_s) end !!result end |