Class: RingCache
- Inherits:
-
Object
- Object
- RingCache
- Defined in:
- lib/ring_cache.rb,
lib/ring_cache/version.rb
Constant Summary collapse
- VERSION =
'1.0'
Instance Attribute Summary collapse
-
#capacity ⇒ Object
readonly
Returns the value of attribute capacity.
-
#target_hit_rate ⇒ Object
readonly
Returns the value of attribute target_hit_rate.
Instance Method Summary collapse
- #evict(key) ⇒ Object
- #fetch(key, &block) ⇒ Object
- #has_key?(key) ⇒ Boolean
- #hit_rate ⇒ Object
-
#initialize(options = {}) ⇒ RingCache
constructor
A new instance of RingCache.
- #last_access(key) ⇒ Object
- #read(key) ⇒ Object
- #reset ⇒ Object
- #size ⇒ Object
- #write(key, data) ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ RingCache
Returns a new instance of RingCache.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/ring_cache.rb', line 10 def initialize( = {}) @duplicate_on_store = .fetch(:duplicate_on_store, false) @duplicate_on_retrieve = .fetch(:duplicate_on_retrieve, false) execute_on_retrieve = .fetch(:execute_on_retrieve, []) @execute_on_retrieve = execute_on_retrieve.kind_of?(Array) ? execute_on_retrieve : [execute_on_retrieve] @capacity = .fetch(:capacity, nil) @target_hit_rate = .fetch(:target_hit_rate, nil) unless @target_hit_rate.nil? or (@target_hit_rate > 0.0 and @target_hit_rate < 1.0) raise ArgumentError, 'Invalid target_hit_rate' end reset end |
Instance Attribute Details
#capacity ⇒ Object (readonly)
Returns the value of attribute capacity.
8 9 10 |
# File 'lib/ring_cache.rb', line 8 def capacity @capacity end |
#target_hit_rate ⇒ Object (readonly)
Returns the value of attribute target_hit_rate.
8 9 10 |
# File 'lib/ring_cache.rb', line 8 def target_hit_rate @target_hit_rate end |
Instance Method Details
#evict(key) ⇒ Object
26 27 28 29 30 31 32 33 34 |
# File 'lib/ring_cache.rb', line 26 def evict(key) if @cache.has_key?(key) @access_time_index.delete([@cache[key][:last_accessed_at], key]) @cache.delete(key) true else false end end |
#fetch(key, &block) ⇒ Object
36 37 38 39 40 41 42 |
# File 'lib/ring_cache.rb', line 36 def fetch(key, &block) unless (data = read(key)) data = block.call write(key, data) end data end |
#has_key?(key) ⇒ Boolean
44 45 46 |
# File 'lib/ring_cache.rb', line 44 def has_key?(key) @cache.has_key?(key) end |
#hit_rate ⇒ Object
48 49 50 |
# File 'lib/ring_cache.rb', line 48 def hit_rate (@access_count > 0) ? (@hit_count / @access_count.to_f) : 0.0 end |
#last_access(key) ⇒ Object
52 53 54 |
# File 'lib/ring_cache.rb', line 52 def last_access(key) has_key?(key) ? @cache[key][:last_accessed_at] : nil end |
#read(key) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/ring_cache.rb', line 56 def read(key) @access_count += 1 if @cache.has_key?(key) access_time = Time.now @access_time_index.delete([@cache[key][:last_accessed_at], key]) @access_time_index << [access_time, key] @cache[key][:last_accessed_at] = access_time @hit_count += 1 data = @cache[key][:data] data = data.dup if @duplicate_on_retrieve and !data.nil? unless @execute_on_retrieve.empty? or data.nil? @execute_on_retrieve.each do |method| method = method.to_sym if data.respond_to?(method) data.send(method) elsif data.kind_of?(Enumerable) and data.all? { |d| d.respond_to?(method) } data.each { |d| d.send(method) } else raise RuntimeError, "Retrieved data does not respond to #{method.inspect}" end end end data else nil end end |
#reset ⇒ Object
89 90 91 92 93 94 95 |
# File 'lib/ring_cache.rb', line 89 def reset @cache = {} @access_time_index = SortedSet.new @access_count = 0 @hit_count = 0 true end |
#size ⇒ Object
97 98 99 |
# File 'lib/ring_cache.rb', line 97 def size @cache.size end |
#write(key, data) ⇒ Object
101 102 103 104 105 106 107 |
# File 'lib/ring_cache.rb', line 101 def write(key, data) evict_oldest if must_evict? data = data.dup if @duplicate_on_store and !data.nil? access_time = Time.now @cache[key] = { last_accessed_at: access_time, data: data } @access_time_index << [access_time, key] end |