Class: Tina4::QueryCache

Inherits:
Object
  • Object
show all
Defined in:
lib/tina4/sql_translation.rb

Overview

In-memory cache with TTL support for query results.

Usage:

cache = Tina4::QueryCache.new(default_ttl: 60, max_size: 1000)
cache.set("key", "value", ttl: 30)
cache.get("key")  # => "value"

Defined Under Namespace

Classes: CacheEntry

Instance Method Summary collapse

Constructor Details

#initialize(default_ttl: 300, max_size: 1000) ⇒ QueryCache

Returns a new instance of QueryCache.

Parameters:

  • default_ttl (Integer) (defaults to: 300)

    default TTL in seconds (default: 300)

  • max_size (Integer) (defaults to: 1000)

    maximum number of cache entries (default: 1000)



170
171
172
173
174
175
# File 'lib/tina4/sql_translation.rb', line 170

def initialize(default_ttl: 300, max_size: 1000)
  @default_ttl = default_ttl
  @max_size = max_size
  @store = {}
  @mutex = Mutex.new
end

Instance Method Details

#clearObject

Clear all entries from the cache.



245
246
247
# File 'lib/tina4/sql_translation.rb', line 245

def clear
  @mutex.synchronize { @store.clear }
end

#clear_tag(tag) ⇒ Integer

Clear all entries with a given tag.

Parameters:

  • tag (String)

Returns:

  • (Integer)

    number of entries removed



253
254
255
256
257
258
259
# File 'lib/tina4/sql_translation.rb', line 253

def clear_tag(tag)
  @mutex.synchronize do
    keys_to_remove = @store.select { |_k, v| v.tags.include?(tag) }.keys
    keys_to_remove.each { |k| @store.delete(k) }
    keys_to_remove.size
  end
end

#delete(key) ⇒ Boolean

Delete a key from the cache.

Parameters:

  • key (String)

Returns:

  • (Boolean)

    true if the key was present



238
239
240
241
242
# File 'lib/tina4/sql_translation.rb', line 238

def delete(key)
  @mutex.synchronize do
    !@store.delete(key).nil?
  end
end

#get(key, default = nil) ⇒ Object?

Retrieve a cached value. Returns nil if expired or missing.

Parameters:

  • key (String)
  • default (Object) (defaults to: nil)

    value to return if key is missing

Returns:

  • (Object, nil)


202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/tina4/sql_translation.rb', line 202

def get(key, default = nil)
  @mutex.synchronize do
    entry = @store[key]
    return default unless entry

    if Time.now.to_f > entry.expires_at
      @store.delete(key)
      return default
    end

    entry.value
  end
end

#has?(key) ⇒ Boolean

Check if a key exists and is not expired.

Parameters:

  • key (String)

Returns:

  • (Boolean)


220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/tina4/sql_translation.rb', line 220

def has?(key)
  @mutex.synchronize do
    entry = @store[key]
    return false unless entry

    if Time.now.to_f > entry.expires_at
      @store.delete(key)
      return false
    end

    true
  end
end

#remember(key, ttl, &block) ⇒ Object

Fetch from cache, or compute and store.

Parameters:

  • key (String)
  • ttl (Integer)

    TTL in seconds

  • block (Proc)

    factory to compute the value if not cached

Returns:

  • (Object)


279
280
281
282
283
284
285
286
# File 'lib/tina4/sql_translation.rb', line 279

def remember(key, ttl, &block)
  cached = get(key)
  return cached unless cached.nil?

  value = block.call
  set(key, value, ttl: ttl)
  value
end

#set(key, value, ttl: nil, tags: []) ⇒ Object

Store a value with optional TTL and tags.

Parameters:

  • key (String)
  • value (Object)
  • ttl (Integer, nil) (defaults to: nil)

    TTL in seconds (nil uses default)

  • tags (Array<String>) (defaults to: [])

    optional tags for grouped invalidation



183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/tina4/sql_translation.rb', line 183

def set(key, value, ttl: nil, tags: [])
  ttl ||= @default_ttl
  expires_at = Time.now.to_f + ttl

  @mutex.synchronize do
    # Evict oldest if at capacity
    if @store.size >= @max_size && !@store.key?(key)
      oldest_key = @store.keys.first
      @store.delete(oldest_key)
    end
    @store[key] = CacheEntry.new(value, expires_at, tags)
  end
end

#sizeInteger

Current number of entries in the cache.

Returns:

  • (Integer)


291
292
293
# File 'lib/tina4/sql_translation.rb', line 291

def size
  @mutex.synchronize { @store.size }
end

#sweepInteger

Remove all expired entries.

Returns:

  • (Integer)

    number of entries removed



264
265
266
267
268
269
270
271
# File 'lib/tina4/sql_translation.rb', line 264

def sweep
  @mutex.synchronize do
    now = Time.now.to_f
    keys_to_remove = @store.select { |_k, v| now > v.expires_at }.keys
    keys_to_remove.each { |k| @store.delete(k) }
    keys_to_remove.size
  end
end