Class: Ask::State::Memory
- Inherits:
-
Adapter
- Object
- Adapter
- Ask::State::Memory
- Defined in:
- lib/ask/state/memory.rb
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.
Available automatically when using ask-state-providers.
For lightweight use without the full providers gem, see
Adapter for the abstract contract.
Instance Method Summary collapse
-
#acquire_lock(key, ttl: 10) ⇒ Object
-- locking --.
- #clear ⇒ Object
-
#close ⇒ Object
-- lifecycle --.
- #delete(key) ⇒ Object
- #dequeue(queue) ⇒ Object
-
#enqueue(queue, value) ⇒ Object
-- queues --.
- #exists?(key) ⇒ Boolean
-
#get(key) ⇒ Object
-- key-value --.
-
#initialize ⇒ Memory
constructor
A new instance of Memory.
- #keys(pattern: nil) ⇒ Object
-
#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.
15 16 17 18 19 20 21 |
# File 'lib/ask/state/memory.rb', line 15 def initialize @data = {} @locks = {} @queues = {} @lists = {} @mutex = Mutex.new end |
Instance Method Details
#acquire_lock(key, ttl: 10) ⇒ Object
-- locking --
97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/ask/state/memory.rb', line 97 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 |
#clear ⇒ Object
63 64 65 66 67 68 69 70 |
# File 'lib/ask/state/memory.rb', line 63 def clear @mutex.synchronize do @data.clear @locks.clear @queues.clear @lists.clear end end |
#close ⇒ Object
-- lifecycle --
185 186 187 188 189 190 191 192 |
# File 'lib/ask/state/memory.rb', line 185 def close @mutex.synchronize do @data.clear @locks.clear @queues.clear @lists.clear end end |
#delete(key) ⇒ Object
43 44 45 |
# File 'lib/ask/state/memory.rb', line 43 def delete(key) @mutex.synchronize { @data.delete(key) } end |
#dequeue(queue) ⇒ Object
139 140 141 142 143 144 145 |
# File 'lib/ask/state/memory.rb', line 139 def dequeue(queue) @mutex.synchronize do q = @queues[queue] return nil unless q&.any? q.shift end end |
#enqueue(queue, value) ⇒ Object
-- queues --
126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/ask/state/memory.rb', line 126 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 |
#exists?(key) ⇒ Boolean
72 73 74 75 76 77 78 |
# File 'lib/ask/state/memory.rb', line 72 def exists?(key) @mutex.synchronize do expiry = @data[key]&.dig(:expires_at) return false if expiry && Time.now >= expiry @data.key?(key) end end |
#get(key) ⇒ Object
-- key-value --
25 26 27 28 29 30 31 32 |
# File 'lib/ask/state/memory.rb', line 25 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 |
#keys(pattern: nil) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/ask/state/memory.rb', line 80 def keys(pattern: nil) @mutex.synchronize do active = @data.select do |_k, v| expiry = v[:expires_at] expiry.nil? || Time.now < expiry end keys = active.keys.map(&:to_s) return keys unless pattern regex = self.class.glob_to_regex(pattern) keys.select { |k| k.match?(regex) } end end |
#list_append(key, value, max_length: nil) ⇒ Object
-- lists --
155 156 157 158 159 160 161 |
# File 'lib/ask/state/memory.rb', line 155 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
163 164 165 166 167 168 169 170 171 |
# File 'lib/ask/state/memory.rb', line 163 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
173 174 175 176 177 178 179 180 181 |
# File 'lib/ask/state/memory.rb', line 173 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
147 148 149 150 151 |
# File 'lib/ask/state/memory.rb', line 147 def queue_depth(queue) @mutex.synchronize do (@queues[queue] || []).length end end |
#release_lock(key, lock) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/ask/state/memory.rb', line 112 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
34 35 36 37 38 39 40 41 |
# File 'lib/ask/state/memory.rb', line 34 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
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/ask/state/memory.rb', line 47 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 @data.delete(key) end @data[key] = { value: value, expires_at: ttl ? Time.now + ttl : nil } true end end |