Class: Ask::State::Memory
Overview
In-process state backend backed by a Hash. All operations are thread-safe via a Mutex. Data is not persisted — lost on process exit.
Instance Method Summary collapse
-
#acquire_lock(key, ttl: 10) ⇒ Object
-- locking --.
-
#close ⇒ Object
-- lifecycle --.
- #delete(key) ⇒ Object
- #dequeue(queue) ⇒ Object
-
#enqueue(queue, value) ⇒ Object
-- queues --.
-
#get(key) ⇒ Object
-- key-value --.
-
#initialize ⇒ Memory
constructor
A new instance of Memory.
-
#list_append(key, value, max_length: nil) ⇒ Object
-- lists --.
- #list_range(key, start = 0, stop = -1)) ⇒ Object
- #list_remove(key, value) ⇒ Object
- #queue_depth(queue) ⇒ Object
- #release_lock(key, lock) ⇒ Object
- #set(key, value, ttl: nil) ⇒ Object
- #set_if_not_exists(key, value, ttl: nil) ⇒ Object
Constructor Details
#initialize ⇒ Memory
Returns a new instance of Memory.
156 157 158 159 160 161 162 |
# File 'lib/ask/state.rb', line 156 def initialize @data = {} @locks = {} @queues = {} @lists = {} @mutex = Mutex.new end |
Instance Method Details
#acquire_lock(key, ttl: 10) ⇒ Object
-- locking --
208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/ask/state.rb', line 208 def acquire_lock(key, ttl: 10) @mutex.synchronize do existing = @locks[key] if existing.nil? || existing.expired? lock = Lock.new( id: key, token: SecureRandom.hex(16), expires_at: Time.now + ttl ) @locks[key] = lock lock end end end |
#close ⇒ Object
-- lifecycle --
300 301 302 303 304 305 306 307 |
# File 'lib/ask/state.rb', line 300 def close @mutex.synchronize do @data.clear @locks.clear @queues.clear @lists.clear end end |
#delete(key) ⇒ Object
184 185 186 |
# File 'lib/ask/state.rb', line 184 def delete(key) @mutex.synchronize { @data.delete(key) } end |
#dequeue(queue) ⇒ Object
250 251 252 253 254 255 256 257 |
# File 'lib/ask/state.rb', line 250 def dequeue(queue) @mutex.synchronize do q = @queues[queue] return nil unless q&.any? q.shift end end |
#enqueue(queue, value) ⇒ Object
-- queues --
237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/ask/state.rb', line 237 def enqueue(queue, value) @mutex.synchronize do @queues[queue] ||= [] entry = QueueEntry.new( id: SecureRandom.uuid, value: value, enqueued_at: Time.now ) @queues[queue] << entry entry end end |
#get(key) ⇒ Object
-- key-value --
166 167 168 169 170 171 172 173 |
# File 'lib/ask/state.rb', line 166 def get(key) @mutex.synchronize do expiry = @data[key]&.dig(:expires_at) return nil if expiry && Time.now >= expiry @data[key]&.dig(:value) end end |
#list_append(key, value, max_length: nil) ⇒ Object
-- lists --
267 268 269 270 271 272 273 |
# File 'lib/ask/state.rb', line 267 def list_append(key, value, max_length: nil) @mutex.synchronize do @lists[key] ||= [] @lists[key] << value @lists[key].shift if max_length && @lists[key].length > max_length end end |
#list_range(key, start = 0, stop = -1)) ⇒ Object
275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/ask/state.rb', line 275 def list_range(key, start = 0, stop = -1) @mutex.synchronize do list = @lists[key] || [] return list if start == 0 && stop == -1 stop = list.length - 1 if stop == -1 || stop >= list.length return [] if start > stop list[start..stop] || [] end end |
#list_remove(key, value) ⇒ Object
287 288 289 290 291 292 293 294 295 296 |
# File 'lib/ask/state.rb', line 287 def list_remove(key, value) @mutex.synchronize do list = @lists[key] return 0 unless list before = list.length list.delete(value) before - list.length end end |
#queue_depth(queue) ⇒ Object
259 260 261 262 263 |
# File 'lib/ask/state.rb', line 259 def queue_depth(queue) @mutex.synchronize do (@queues[queue] || []).length end end |
#release_lock(key, lock) ⇒ Object
223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/ask/state.rb', line 223 def release_lock(key, lock) @mutex.synchronize do current = @locks[key] if current && current.token == lock.token && !current.expired? @locks.delete(key) true else false end end end |
#set(key, value, ttl: nil) ⇒ Object
175 176 177 178 179 180 181 182 |
# File 'lib/ask/state.rb', line 175 def set(key, value, ttl: nil) @mutex.synchronize do @data[key] = { value: value, expires_at: ttl ? Time.now + ttl : nil } end end |
#set_if_not_exists(key, value, ttl: nil) ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/ask/state.rb', line 188 def set_if_not_exists(key, value, ttl: nil) @mutex.synchronize do if @data.key?(key) expiry = @data[key][:expires_at] return false if expiry.nil? || Time.now < expiry # Key expired — treat as nonexistent @data.delete(key) end @data[key] = { value: value, expires_at: ttl ? Time.now + ttl : nil } true end end |