Class: ChefStash::TimeCache

Inherits:
Object
  • Object
show all
Defined in:
lib/chef_stash/time_cache.rb

Overview

In-process cache with least-recently used (LRU) and time-to-live (TTL) expiration semantics. This implementation is thread-safe. It does not use a thread to clean up expired values. Instead, an expiration check is performed:

  1. Every time you retrieve a value, against that value. If the value has expired, it will be removed and ‘nil` will be returned.

  2. Every ‘expire_interval` operations as the cache is used to remove all expired values up to that point.

For manual expiration call #expire!.

Defined Under Namespace

Classes: Entry

Constant Summary collapse

DEFAULT_TTL_SECONDS =

The maximum number of seconds an element can exist in the cache regardless of use. The element expires at this limit and will no longer be returned from the cache. The default value is 3600, or 1 hour. Setting A TTL value of 0 means no TTL eviction takes place (infinite lifetime).

3600
DEFAULT_TTI_SECONDS =

The maximum number of seconds an element can exist in the cache without being accessed. The element expires at this limit and will no longer be returned from the cache. The default value is 3600, or 1 hour. Setting a TTI value of 0 means no TTI eviction takes place (infinite lifetime).

3600
DEFAULT_MAX_ENTRIES =

The maximum sum total number of elements (cache entries) allowed on the disk tier for the cache. If this target is exceeded, eviction occurs to bring the count within the allowed target. The default value is 1,000. A setting of 0 means that no eviction of the cache’s entries takes place (infinite size is allowed), and consequently can cause the node to run out of disk space.

1_000

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ TimeCache

Initializes the cache.

Parameters:

  • opts (Hash) (defaults to: {})

    The options to configure the cache.

Options Hash (opts):

  • :max_entries (Integer)

    Maximum number of elements in the cache.

  • :ttl (Numeric)

    Maximum time, in seconds, for a value to stay in the cache.

  • :tti (Numeric)

    Maximum time, in seconds, for a value to stay in the cache without being accessed.

  • :interval (Integer)

    Number of cache operations between calls to #expire!.



87
88
89
90
91
92
93
94
95
96
# File 'lib/chef_stash/time_cache.rb', line 87

def initialize(opts = {})
  @max_entries = opts.fetch(:max_entries, DEFAULT_MAX_ENTRIES)
  @ttl_seconds = opts.fetch(:ttl_seconds, DEFAULT_TTL_SECONDS)
  @tti_seconds = opts.fetch(:ttl_seconds, DEFAULT_TTI_SECONDS)
  @interval    = opts.fetch(:interval, 100)
  @operations  = 0
  @monitor     = Monitor.new
  @stash       = {}
  @expires_at  = {}
end

Instance Attribute Details

#:stats(: stats) ⇒ CacheStats (readonly)

Returns The Cache statistics.

Returns:

  • (CacheStats)

    The Cache statistics.



59
# File 'lib/chef_stash/time_cache.rb', line 59

attr_reader :stats

#:tti (DEFAULT_TTI_SECONDS)(: tti(DEFAULT_TTI_SECONDS)) ⇒ Integer (readonly)

Returns The time to idle for an element before it expires.

Returns:

  • (Integer)

    The time to idle for an element before it expires.



67
# File 'lib/chef_stash/time_cache.rb', line 67

attr_reader :tti

#:ttl (DEFAULT_TTL_SECONDS)(: ttl(DEFAULT_TTL_SECONDS)) ⇒ Integer (readonly)

Returns The time to live for an element before it expires.

Returns:

  • (Integer)

    The time to live for an element before it expires.



63
# File 'lib/chef_stash/time_cache.rb', line 63

attr_reader :ttl

#statsObject (readonly)

Returns the value of attribute stats.



59
60
61
# File 'lib/chef_stash/time_cache.rb', line 59

def stats
  @stats
end

#ttiObject (readonly)

Returns the value of attribute tti.



67
68
69
# File 'lib/chef_stash/time_cache.rb', line 67

def tti
  @tti
end

#ttlObject (readonly)

Returns the value of attribute ttl.



63
64
65
# File 'lib/chef_stash/time_cache.rb', line 63

def ttl
  @ttl
end

Instance Method Details

#[](key) ⇒ Object? Also known as: get

Retrieves a value from the cache.

Parameters:

  • key (Object)

    The key to look up.

Returns:

  • (Object, nil)

    The value at the key, when present, or ‘nil`.



143
144
145
146
147
148
# File 'lib/chef_stash/time_cache.rb', line 143

def [](key)
  @monitor.synchronize do
    _, value = get(key)
    value
  end
end

#[]=(key, val) ⇒ Object? Also known as: set

Stores a value in the cache.

Parameters:

  • key (Object)

    The key to store.

  • val (Object)

    The value to store.

Returns:

  • (Object, nil)

    The value at the key.



162
163
164
165
166
167
# File 'lib/chef_stash/time_cache.rb', line 162

def []=(key, val)
  @monitor.synchronize do
    expire!
    store(key, val)
  end
end

#clearself

Clears the cache.

Returns:

  • (self)


204
205
206
207
208
209
210
# File 'lib/chef_stash/time_cache.rb', line 204

def clear
  @monitor.synchronize do
    @stash.clear
    @expires_at.clear
    self
  end
end

#countInteger Also known as: size, length

Note:

Calls to #empty? do not count against ‘expire_interval`. Therefore, the number of elements is that prior to any expiration.

Returns the number of elements in the cache.

Returns:

  • (Integer)

    Number of elements in the cache.



221
222
223
# File 'lib/chef_stash/time_cache.rb', line 221

def count
  @monitor.synchronize { @stash.count }
end

#delete(key) ⇒ Object?

Removes a value from the cache.

Parameters:

  • key (Object)

    The key to remove.

Returns:

  • (Object, nil)

    The value at the key, when present, or ‘nil`.



178
179
180
181
182
183
184
185
186
187
188
# File 'lib/chef_stash/time_cache.rb', line 178

def delete(key)
  @monitor.synchronize do
    entry = @stash.delete(key)
    if entry
      @expires_at.delete(entry)
      entry.value
    else
      nil
    end
  end
end

#each {|Array<key, value>| ... } ⇒ Enumerator, Array<key, value>

Note:

The returned values could have expired by the time the client code gets to accessing them.

Note:

Because of its stability, this operation is very expensive. Use with caution.

Allows iteration over the items in the cache. Enumeration is stable: it is not affected by changes to the cache, including value expiration. Expired values are removed first.

Yields:

  • (Array<key, value>)

    Key/value pairs, when a block is provided.

Returns:

  • (Enumerator, Array<key, value>)

    An Enumerator, when no block is provided, or array of key/value pairs.



245
246
247
248
249
250
# File 'lib/chef_stash/time_cache.rb', line 245

def each(&block)
  @monitor.synchronize do
    expire!
    @stash.map { |key, entry| [key, entry.value] }.each(&block)
  end
end

#empty?Boolean

Note:

calls to #empty? do not count against ‘expire_interval`.

Checks whether the cache is empty.

Returns:

  • (Boolean)


196
197
198
# File 'lib/chef_stash/time_cache.rb', line 196

def empty?
  @monitor.synchronize { count == 0 }
end

#expire!self

Removes expired values from the cache.

Returns:

  • (self)


256
257
258
259
260
261
# File 'lib/chef_stash/time_cache.rb', line 256

def expire!
  @monitor.synchronize do
    check_expired(Time.now.to_f)
    self
  end
end

#fetch(key) { ... } ⇒ Object

Retrieves a value from the cache, if available and not expired, or yields to a block that calculates the value to be stored in the cache.

Parameters:

  • key (Object)

    The key to look up or store at.

Yields:

  • yields when the value is not present.

Yield Returns:

  • (Object)

    The value to store in the cache.

Returns:

  • (Object)

    The value at the key.



128
129
130
131
132
133
# File 'lib/chef_stash/time_cache.rb', line 128

def fetch(key)
  @monitor.synchronize do
    found, value = get(key)
    found ? value : store(key, yield)
  end
end

#inspectString

Returns information about the number of objects in the cache, its maximum size and TTL.

Returns:

  • (String)


276
277
278
279
280
281
# File 'lib/chef_stash/time_cache.rb', line 276

def inspect
  @monitor.synchronize do
    "<#{self.class.name} count=#{count} max_entries=#{@max_entries} " \
    "ttl=#{@ttl_seconds}>"
  end
end

#keysArray<String, Symbol>

Return all keys in the store as an array.

Returns:

  • (Array<String, Symbol>)

    all the keys in store



267
268
269
# File 'lib/chef_stash/time_cache.rb', line 267

def keys
  @monitor.synchronize { @stash.keys }
end

#load(data) ⇒ Object

Loads a hash of data into the stash.

Parameters:

  • data (Hash)

    Hash of data with either String or Symbol keys.

Returns:

  • nothing.



105
106
107
108
109
110
111
112
# File 'lib/chef_stash/time_cache.rb', line 105

def load(data)
  @monitor.synchronize do
    data.each do |key, value|
      expire!
      store(key, val)
    end
  end
end