Class: LRUHash

Inherits:
Object
  • Object
show all
Defined in:
lib/semian/lru_hash.rb

Defined Under Namespace

Classes: NoopMutex

Instance Method Summary collapse

Constructor Details

#initialize(max_size: Semian.maximum_lru_size, min_time: Semian.minimum_lru_time) ⇒ LRUHash

Create an LRU hash

Arguments:

+max_size+ The maximum size of the table
+min_time+ The minimum time a resource can live in the cache

Note:

The +min_time+ is a stronger guarantee than +max_size+. That is, if there are
more than +max_size+ entries in the cache, but they've all been updated more
recently than +min_time+, the garbage collection will not remove them and the
cache can grow without bound. This usually means that you have many active
circuits to disparate endpoints (or your circuit names are bad).
If the max_size is 0, the garbage collection will be very aggressive and
potentially computationally expensive.


52
53
54
55
56
57
58
59
60
61
62
# File 'lib/semian/lru_hash.rb', line 52

def initialize(max_size: Semian.maximum_lru_size, min_time: Semian.minimum_lru_time)
  @max_size = max_size
  @min_time = min_time
  @table = {}
  @lock =
    if Semian.thread_safe?
      Mutex.new
    else
      NoopMutex.new
    end
end

Instance Method Details

#[](key) ⇒ Object



115
116
117
# File 'lib/semian/lru_hash.rb', line 115

def [](key)
  get(key)
end

#[]=(key, resource) ⇒ Object



111
112
113
# File 'lib/semian/lru_hash.rb', line 111

def []=(key, resource)
  set(key, resource)
end

#clearObject



34
35
36
# File 'lib/semian/lru_hash.rb', line 34

def clear
  @lock.synchronize { @table.clear }
end

#count(&block) ⇒ Object



68
69
70
# File 'lib/semian/lru_hash.rb', line 68

def count(&block)
  @lock.synchronize { @table.count(&block) }
end

#delete(key) ⇒ Object



105
106
107
108
109
# File 'lib/semian/lru_hash.rb', line 105

def delete(key)
  @lock.synchronize do
    @table.delete(key)
  end
end

#empty?Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/semian/lru_hash.rb', line 72

def empty?
  @lock.synchronize { @table.empty? }
end

#get(key) ⇒ Object

This method uses the property that “Hashes enumerate their values in the order that the corresponding keys were inserted.” Deleting a key and re-inserting it effectively moves it to the front of the cache. Update the ‘updated_at` field so we can use it later do decide if the resource is “in use”.



94
95
96
97
98
99
100
101
102
103
# File 'lib/semian/lru_hash.rb', line 94

def get(key)
  @lock.synchronize do
    found = @table.delete(key)
    if found
      @table[key] = found
      found.updated_at = Time.now
    end
    found
  end
end

#keysObject



30
31
32
# File 'lib/semian/lru_hash.rb', line 30

def keys
  @lock.synchronize { @table.keys }
end

#set(key, resource) ⇒ Object



80
81
82
83
84
85
86
87
# File 'lib/semian/lru_hash.rb', line 80

def set(key, resource)
  @lock.synchronize do
    @table.delete(key)
    @table[key] = resource
    resource.updated_at = Time.now
  end
  clear_unused_resources if @table.length > @max_size
end

#sizeObject



64
65
66
# File 'lib/semian/lru_hash.rb', line 64

def size
  @lock.synchronize { @table.size }
end

#valuesObject



76
77
78
# File 'lib/semian/lru_hash.rb', line 76

def values
  @lock.synchronize { @table.values }
end