volatile_hash 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm use ruby-1.9.2-p180@colorize --create
2
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
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
@@ -0,0 +1,8 @@
1
+ Implements a Time-to-live based cache and a Least-recently-used cache.
2
+
3
+
4
+ = Test/Development
5
+
6
+ gem install bundler
7
+ bundle install
8
+ rake
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'rspec/core/rake_task'
2
+ task :default => :spec
3
+
4
+ RSpec::Core::RakeTask.new do |t|
5
+ # t.pattern = 'spec/**/*_spec.rb'
6
+ end
7
+
@@ -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
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'volatile_hash'
5
+
6
+ RSpec.configure do |config|
7
+ # some (optional) config here
8
+ config.mock_with :rr
9
+ end
10
+
@@ -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: []