that_old_cache 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/README.md ADDED
@@ -0,0 +1,16 @@
1
+ That Old Cache
2
+ ==============
3
+
4
+ Description
5
+ -----------
6
+
7
+ Getting sick of memcached just kicking your stuff out of memory in Rails? Maybe you've thought
8
+ *"Gee, wouldn't it be nice to just serve the old cache while I refresh it."* Well, look no
9
+ further! **That Old Cache** is a Rubygem that does just that, giving you the ability to fire
10
+ off a process to refresh the cache once it expires, without the annoying "initial load" problem
11
+ that affects your users.
12
+
13
+ Authors
14
+ -------
15
+
16
+ Joey Robert ([http://joeyrobert.org/](http://joeyrobert.org/))
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/gempackagetask'
4
+ require 'spec/rake/spectask'
5
+
6
+ desc 'Default: run specs.'
7
+ task :default => :spec
8
+
9
+ desc 'Run the specs'
10
+ Spec::Rake::SpecTask.new(:spec) do |t|
11
+ t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
12
+ t.spec_files = FileList['spec/**/*_spec.rb']
13
+ end
14
+
15
+ PKG_FILES = FileList['lib/**/*', 'spec/*', 'Rakefile', 'README.md', 'VERSION']
16
+
17
+ spec = Gem::Specification.new do |s|
18
+ s.name = "that_old_cache"
19
+ s.version = "0.0.1"
20
+ s.author = "Joey Robert"
21
+ s.email = "joey@joeyrobert.org"
22
+ s.homepage = "http://github.com/joeyrobert/that_old_cache"
23
+ s.platform = Gem::Platform::RUBY
24
+ s.summary = "Serve old caches from memcached while you update in Rails"
25
+ s.description = "An ActiveSupport MemCache store that requires serves keys until they are explicitly overwritten"
26
+ s.files = PKG_FILES.to_a
27
+ s.require_path = "lib"
28
+ s.has_rdoc = false
29
+ s.add_dependency "yajl-ruby", ">= 0.7.x"
30
+ s.add_dependency "activesupport", ">= 2.3.x"
31
+ end
32
+
33
+ desc 'Turn this plugin into a gem.'
34
+ Rake::GemPackageTask.new(spec) { |pkg| pkg.gem_spec = spec }
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1 @@
1
+ require 'that_old_cache/ttled_mem_cache_store'
@@ -0,0 +1,60 @@
1
+ require 'active_support'
2
+ require 'yajl'
3
+
4
+ module ActiveSupport
5
+ module Cache
6
+ class TTLedMemCacheStore < MemCacheStore
7
+ # Adds the following option:
8
+ # :valid_for => number of seconds from now that the cache with "expire"
9
+ # :raw is not supported with :valid_for
10
+ def write(key, value, options = nil)
11
+ if options && options[:valid_for]
12
+ options.delete(:raw)
13
+ super(key, encode({ :data => value, :ttl => time_for(options.delete(:valid_for)) }), options)
14
+ else
15
+ super
16
+ end
17
+ end
18
+
19
+ # Adds the following option:
20
+ # :valid_for => true
21
+ # :raw is not supported with :valid_for
22
+ def read(key, options = nil)
23
+ if options && options.delete(:valid_for)
24
+ options.delete(:raw)
25
+ parse(super)[:data] rescue nil
26
+ else
27
+ super
28
+ end
29
+ end
30
+
31
+ # only works for TTLed keys
32
+ def expired?(key)
33
+ begin
34
+ ttl(key) < Time.now.to_i
35
+ rescue NoMethodError
36
+ false
37
+ end
38
+ end
39
+
40
+ # only works for TTLed keys
41
+ def ttl(key)
42
+ parse(read(key))[:ttl] rescue nil
43
+ end
44
+
45
+ private
46
+
47
+ def time_for(seconds)
48
+ Time.now.to_i + seconds.to_i
49
+ end
50
+
51
+ def parse(val)
52
+ Yajl::Parser.new(:symbolize_keys => true).parse(val)
53
+ end
54
+
55
+ def encode(val)
56
+ Yajl::Encoder.encode(val)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,2 @@
1
+ require "spec"
2
+ require File.dirname(__FILE__) + '/../lib/that_old_cache'
@@ -0,0 +1,79 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe ActiveSupport::Cache::TTLedMemCacheStore do
4
+ # Since this is about interface to a cache, I think it makes sense to run a
5
+ # real cache in this case and not mock/stub it out. TODO: Rake to start/detach
6
+ # a memcached?
7
+ before(:all) do
8
+ begin
9
+ # Run on non-default port so not to accidentally mess with a real cache
10
+ @cache = ActiveSupport::Cache::TTLedMemCacheStore.new("127.0.0.1:12345")
11
+ # Call to make sure we have a live connection
12
+ @cache.exist?("cache_key")
13
+ rescue => e
14
+ $stderr.puts e.message
15
+ $stderr.puts "Make sure memcached is listening on tcpport 12345: /path/to/memcached -p 12345"
16
+ exit
17
+ end
18
+
19
+ @key = "example_key"
20
+ @value = "example_value"
21
+ end
22
+
23
+ after(:each) do
24
+ @cache.clear
25
+ end
26
+
27
+ context "ttl'd keys" do
28
+ before(:each) do
29
+ @valid_for = 10
30
+ @cache.write(@key, @value, :valid_for => @valid_for)
31
+ end
32
+
33
+ it "should set the expected value in the cache" do
34
+ @cache.read(@key, :valid_for => true).should == @value
35
+ end
36
+
37
+ it "should have the proper ttl" do
38
+ @cache.ttl(@key).should be_close(Time.now.to_i + @valid_for, 1)
39
+ end
40
+
41
+ # Vendor something to time_travel if this sleep stuff gets annoying
42
+ it "should be expired if the ttl is less than now" do
43
+ @cache.write(@key, @value, :valid_for => 0.1)
44
+ sleep 1
45
+ @cache.expired?(@key).should be_true
46
+ end
47
+
48
+ it "should not be expired if the ttl is greater than now" do
49
+ @cache.write(@key, @value, :valid_for => 5)
50
+ @cache.expired?(@key).should be_false
51
+ end
52
+ end
53
+
54
+ context "non-ttl'd keys" do
55
+ before(:each) do
56
+ @cache.write(@key, @value)
57
+ end
58
+
59
+ it "should set the non-serialized value in the cache" do
60
+ @cache.read(@key).should == @value
61
+ end
62
+
63
+ it "should have a nil ttl" do
64
+ @cache.ttl(@key).should be_nil
65
+ end
66
+
67
+ it "should not be expired" do
68
+ @cache.expired?(@key).should be_false
69
+ end
70
+
71
+ it "should not raise an exception if trying a ttl'd read on a non-ttl'd key" do
72
+ lambda { @cache.read(@key, :valid_for => true) }.should_not raise_error
73
+ end
74
+
75
+ it "should return nil if trying a ttl'd read on a non-ttl'd key" do
76
+ @cache.read(@key, :valid_for => true).should be_nil
77
+ end
78
+ end
79
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: that_old_cache
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Joey Robert
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-13 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: yajl-ruby
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 7
30
+ - x
31
+ version: 0.7.x
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: activesupport
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 2
43
+ - 3
44
+ - x
45
+ version: 2.3.x
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ description: An ActiveSupport MemCache store that requires serves keys until they are explicitly overwritten
49
+ email: joey@joeyrobert.org
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - lib/that_old_cache.rb
58
+ - lib/that_old_cache/ttled_mem_cache_store.rb
59
+ - spec/spec_helper.rb
60
+ - spec/that_old_cache_spec.rb
61
+ - Rakefile
62
+ - README.md
63
+ - VERSION
64
+ has_rdoc: true
65
+ homepage: http://github.com/joeyrobert/that_old_cache
66
+ licenses: []
67
+
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.6
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Serve old caches from memcached while you update in Rails
94
+ test_files: []
95
+