volatile_hash 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rvmrc +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +28 -0
- data/README +8 -0
- data/Rakefile +7 -0
- data/lib/volatile_hash.rb +54 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/volatile_hash_spec.rb +92 -0
- data/volatile_hash.gemspec +18 -0
- metadata +87 -0
data/.rvmrc
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
volatile_hash (0.0.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.3)
|
10
|
+
rake (0.9.2.2)
|
11
|
+
rr (1.0.4)
|
12
|
+
rspec (2.8.0)
|
13
|
+
rspec-core (~> 2.8.0)
|
14
|
+
rspec-expectations (~> 2.8.0)
|
15
|
+
rspec-mocks (~> 2.8.0)
|
16
|
+
rspec-core (2.8.0)
|
17
|
+
rspec-expectations (2.8.0)
|
18
|
+
diff-lcs (~> 1.1.2)
|
19
|
+
rspec-mocks (2.8.0)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
rake (~> 0.9.2)
|
26
|
+
rr (~> 1.0.4)
|
27
|
+
rspec (~> 2.8.0)
|
28
|
+
volatile_hash!
|
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
class VolatileHash
|
2
|
+
def initialize(options)
|
3
|
+
@strategy = options[:strategy] || 'ttl'
|
4
|
+
@cache = {}
|
5
|
+
if @strategy == 'ttl'
|
6
|
+
@registry = {}
|
7
|
+
@ttl = options[:ttl] || 3600
|
8
|
+
else #lru
|
9
|
+
@max_items = options[:max] || 10
|
10
|
+
@item_order = []
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
value = @cache[key]
|
16
|
+
if @strategy == 'ttl'
|
17
|
+
if expired?(key)
|
18
|
+
@cache.delete key
|
19
|
+
@registry.delete key
|
20
|
+
value = nil
|
21
|
+
end
|
22
|
+
else
|
23
|
+
lru_update key if @cache.has_key?(key)
|
24
|
+
end
|
25
|
+
value #in case of LRU, just return the value that was read
|
26
|
+
end
|
27
|
+
|
28
|
+
def []=(key, value)
|
29
|
+
if @strategy == 'ttl'
|
30
|
+
@registry[key] = Time.now + @ttl.to_f
|
31
|
+
@cache[key] = value
|
32
|
+
else
|
33
|
+
@item_order.unshift key
|
34
|
+
@cache[key] = value
|
35
|
+
lru_invalidate if @max_items < @item_order.length
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def expired?(key)
|
41
|
+
Time.now > @registry[key]
|
42
|
+
end
|
43
|
+
|
44
|
+
def lru_invalidate
|
45
|
+
while @max_items < @item_order.length
|
46
|
+
@cache.delete @item_order.pop
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def lru_update(key)
|
51
|
+
@item_order.delete key
|
52
|
+
@item_order.unshift key
|
53
|
+
end
|
54
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe VolatileHash do
|
4
|
+
describe "TTL mode" do
|
5
|
+
before do
|
6
|
+
@cache = VolatileHash.new(:strategy => 'ttl', :ttl => 0.5, :max => 1)
|
7
|
+
@x = Object.new
|
8
|
+
@cache[:x] = @x.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should remember cached values" do
|
12
|
+
@cache[:x].should == @x.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should not have to re-calculate cached values" do
|
16
|
+
dont_allow(@x).to_s
|
17
|
+
@cache[:x] ||= @x.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should forget cached values after the TTL expires" do
|
21
|
+
@cache[:x].should == @x.to_s
|
22
|
+
|
23
|
+
sleep(0.6)
|
24
|
+
|
25
|
+
@cache[:x].should be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not throw out least-recently used value" do
|
29
|
+
@cache[:y] =1
|
30
|
+
|
31
|
+
@cache[:x].should_not be_nil
|
32
|
+
@cache[:y].should_not be_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "LRU mode" do
|
37
|
+
before do
|
38
|
+
@cache = VolatileHash.new(:strategy => 'lru', :max => 3, :ttl => 0.1)
|
39
|
+
@x = Object.new
|
40
|
+
@y = Object.new
|
41
|
+
@z = Object.new
|
42
|
+
@cache[:x] = @x.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should remember cached values" do
|
46
|
+
@cache[:x].should == @x.to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not have to re-calculate cached values" do
|
50
|
+
dont_allow(@x).to_s
|
51
|
+
@cache[:x] ||= @x.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should have only up to the last max values" do
|
55
|
+
@cache[:x].should == @x.to_s
|
56
|
+
@cache[:y].should be_nil
|
57
|
+
@cache[:z].should be_nil
|
58
|
+
@cache[:w].should be_nil
|
59
|
+
|
60
|
+
@cache[:y] = @y.to_s
|
61
|
+
@cache[:z] = @z.to_s
|
62
|
+
@cache[:w] = @z.to_s
|
63
|
+
|
64
|
+
@cache[:x].should be_nil
|
65
|
+
@cache[:y].should == @y.to_s
|
66
|
+
@cache[:z].should == @z.to_s
|
67
|
+
@cache[:w].should == @z.to_s
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should throw out the least recently accessed value" do
|
71
|
+
@cache[:y] = @y.to_s
|
72
|
+
@cache[:z] = @z.to_s
|
73
|
+
@cache[:y].should == @y.to_s
|
74
|
+
@cache[:x].should == @x.to_s
|
75
|
+
@cache[:z].should == @z.to_s
|
76
|
+
|
77
|
+
@cache[:w] = @x.to_s
|
78
|
+
|
79
|
+
@cache[:x].should == @x.to_s
|
80
|
+
@cache[:y].should be_nil
|
81
|
+
@cache[:z].should == @z.to_s
|
82
|
+
@cache[:w].should == @x.to_s
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should not expire by ttl" do
|
86
|
+
sleep(0.3)
|
87
|
+
@cache[:x].should_not be_nil
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'volatile_hash'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2012-02-22'
|
5
|
+
s.summary = "Implements LRU and TTL caches"
|
6
|
+
s.description = "Implements key-based cache that can have a least-recently-used or time-to-live expiration strategy"
|
7
|
+
s.authors = ["Satya P"]
|
8
|
+
s.email = 'github@thesatya.com'
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
11
|
+
s.require_paths = ["lib"]
|
12
|
+
|
13
|
+
s.homepage = 'http://github.com/satyap/volatile_hash'
|
14
|
+
|
15
|
+
s.add_development_dependency 'rspec', '~> 2.8.0'
|
16
|
+
s.add_development_dependency 'rr', '~> 1.0.4'
|
17
|
+
s.add_development_dependency 'rake', '~> 0.9.2'
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: volatile_hash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Satya P
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-22 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &74297420 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.8.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *74297420
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rr
|
27
|
+
requirement: &74297180 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.4
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *74297180
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &74296950 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.9.2
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *74296950
|
47
|
+
description: Implements key-based cache that can have a least-recently-used or time-to-live
|
48
|
+
expiration strategy
|
49
|
+
email: github@thesatya.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .rvmrc
|
55
|
+
- Gemfile
|
56
|
+
- Gemfile.lock
|
57
|
+
- README
|
58
|
+
- Rakefile
|
59
|
+
- lib/volatile_hash.rb
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
- spec/volatile_hash_spec.rb
|
62
|
+
- volatile_hash.gemspec
|
63
|
+
homepage: http://github.com/satyap/volatile_hash
|
64
|
+
licenses: []
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.8.10
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: Implements LRU and TTL caches
|
87
|
+
test_files: []
|