jodosha-redis-store 0.1.0 → 0.2.0

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.textile CHANGED
@@ -4,7 +4,7 @@ h2. Installation
4
4
 
5
5
  Download and install Redis from http://code.google.com/p/redis/
6
6
 
7
- wget http://redis.googlecode.com/files/redis-0.094.tar.gz
7
+ wget "http://redis.googlecode.com/files/redis-0.094.tar.gz":http://redis.googlecode.com/files/redis-0.094.tar.gz
8
8
  tar -zxvf redis-0.094.tar.gz
9
9
  cd redis-0.094
10
10
  make
@@ -14,37 +14,51 @@ Install the gems
14
14
  sudo gem install ezmobius-redis-rb -s http://gems.github.com
15
15
  sudo gem install jodosha-redis-store -s http://gems.github.com
16
16
 
17
- h2. How to use with Rails
17
+ h2. Cache store
18
18
 
19
- In your configuration files:
19
+ Provides a cache store for your Ruby web framework of choice.
20
+
21
+ h3. How to use with Rails
20
22
 
21
23
  config.gem "jodosha-redis-store", :source => "http://gems.github.com", :lib => "redis-store"
22
24
  require "redis-store" # HACK Rails tries to instantiate cache first, then load configured gems
23
25
  config.cache_store = :redis_store
24
26
 
25
- h2. How to use with Merb
26
-
27
- dependency "jodosha-redis-store", "0.1.0"
27
+ h3. How to use with Merb
28
+
29
+ dependency "jodosha-redis-store", "0.2.0"
28
30
  dependency("merb-cache", merb_gems_version) do
29
31
  Merb::Cache.setup do
30
32
  register(:redis, Merb::Cache::RedisStore, :servers => ["127.0.0.1:6379"])
31
33
  end
32
34
  end
33
35
 
34
- h2. How to use with Sinatra
36
+ h3. How to use with Sinatra
35
37
 
36
38
  require 'rubygems'
37
39
  require 'sinatra'
38
40
  require 'jodosha-redis-store'
39
-
40
41
  class MyApp < Sinatra::Base
41
42
  register Sinatra::Cache
42
-
43
43
  get '/hi' do
44
44
  cache.fetch("greet") { "Hello, World!" }
45
45
  end
46
46
  end
47
47
 
48
+ h2. Rack::Cache
49
+
50
+ Provides a Redis store for HTTP caching. See "http://github.com/rtomayko/rack-cache":http://github.com/rtomayko/rack-cache
51
+
52
+ require "rubygems"
53
+ require "rack"
54
+ require "rack/cache"
55
+ require "jodosha-redis-store"
56
+ require "application"
57
+ use Rack::Cache,
58
+ :metastore => 'redis://localhost:6379/0',
59
+ :entitystore => 'redis://localhost:6380/1'
60
+ run Application.new
61
+
48
62
  h2. Copyright
49
63
 
50
- (c) 2009 Luca Guidi - http://lucaguidi.com, released under the MIT license
64
+ (c) 2009 Luca Guidi - "http://lucaguidi.com":http://lucaguidi.com, released under the MIT license
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake/testtask'
5
5
  require 'rake/rdoctask'
6
6
  require 'spec/rake/spectask'
7
7
 
8
- REDIS_STORE_VERSION = "0.1.0"
8
+ REDIS_STORE_VERSION = "0.2.0"
9
9
 
10
10
  task :default => :spec
11
11
 
@@ -0,0 +1,51 @@
1
+ module Rack
2
+ module Cache
3
+ class EntityStore
4
+ class RedisBase < EntityStore
5
+ # The underlying ::Redis instance used to communicate with the Redis daemon.
6
+ attr_reader :cache
7
+
8
+ extend Rack::Utils
9
+
10
+ def open(key)
11
+ data = read(key)
12
+ data && [data]
13
+ end
14
+
15
+ def self.resolve(uri)
16
+ db = uri.path.sub(/^\//, '')
17
+ db = "0" if db.empty?
18
+ server = { :host => uri.host, :port => uri.port || "6379", :db => db }
19
+ new server
20
+ end
21
+ end
22
+
23
+ class Redis < RedisBase
24
+ def initialize(server, options = {})
25
+ @cache = ::Redis.new server
26
+ end
27
+
28
+ def exist?(key)
29
+ cache.key? key
30
+ end
31
+
32
+ def read(key)
33
+ cache.get key
34
+ end
35
+
36
+ def write(body)
37
+ buf = StringIO.new
38
+ key, size = slurp(body){|part| buf.write(part) }
39
+ [key, size] if cache.set(key, buf.string)
40
+ end
41
+
42
+ def purge(key)
43
+ cache.delete key
44
+ nil
45
+ end
46
+ end
47
+
48
+ REDIS = Redis
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,42 @@
1
+ module Rack
2
+ module Cache
3
+ class MetaStore
4
+ class RedisBase < MetaStore
5
+ extend Rack::Utils
6
+
7
+ # The ::MarshaledRedis object used to communicate with the Redis daemon.
8
+ attr_reader :cache
9
+
10
+ def self.resolve(uri)
11
+ db = uri.path.sub(/^\//, '')
12
+ db = "0" if db.empty?
13
+ server = { :host => uri.host, :port => uri.port || "6379", :db => db }
14
+ new server
15
+ end
16
+ end
17
+
18
+ class Redis < RedisBase
19
+ def initialize(server, options = {})
20
+ @cache = ::MarshaledRedis.new server
21
+ end
22
+
23
+ def read(key)
24
+ key = hexdigest(key)
25
+ cache.get(key) || []
26
+ end
27
+
28
+ def write(key, entries)
29
+ key = hexdigest(key)
30
+ cache.set(key, entries)
31
+ end
32
+
33
+ def purge(key)
34
+ cache.delete(hexdigest(key))
35
+ nil
36
+ end
37
+ end
38
+
39
+ REDIS = Redis
40
+ end
41
+ end
42
+ end
data/lib/redis-store.rb CHANGED
@@ -3,13 +3,19 @@ require "dist_redis"
3
3
  require "redis/marshaled_redis"
4
4
  require "redis/distributed_marshaled_redis"
5
5
 
6
+ # Cache store
6
7
  if defined?(Sinatra)
7
8
  require "cache/sinatra/redis_store"
8
9
  elsif defined?(Merb)
9
10
  # HACK for cyclic dependency: redis-store is required before merb-cache
10
11
  module Merb; module Cache; class AbstractStore; end end end
11
12
  require "cache/merb/redis_store"
12
- else # rails or ruby application
13
- require "activesupport"
13
+ elsif defined?(Rails)
14
14
  require "cache/rails/redis_store"
15
15
  end
16
+
17
+ # Rack::Cache
18
+ if defined?(Rack::Cache)
19
+ require "rack/cache/redis_metastore"
20
+ require "rack/cache/redis_entitystore"
21
+ end
data/redis-store.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "redis-store"
3
- s.version = "0.1.0"
3
+ s.version = "0.2.0"
4
4
  s.date = "2009-04-30"
5
5
  s.summary = "Redis cache and session stores for Ruby web frameworks"
6
6
  s.author = "Luca Guidi"
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.homepage = "http://lucaguidi.com"
9
9
  s.description = "Redis cache and session stores for Ruby web frameworks"
10
10
  s.has_rdoc = true
11
- s.files = ["MIT-LICENSE", "README.textile", "Rakefile", "lib/cache/merb/redis_store.rb", "lib/cache/rails/redis_store.rb", "lib/cache/sinatra/redis_store.rb", "lib/redis-store.rb", "lib/redis/distributed_marshaled_redis.rb", "lib/redis/marshaled_redis.rb", "redis-store.gemspec", "spec/cache/merb/redis_store_spec.rb", "spec/cache/rails/redis_store_spec.rb", "spec/cache/sinatra/redis_store_spec.rb", "spec/config/master.conf", "spec/config/single.conf", "spec/config/slave.conf", "spec/redis/distributed_marshaled_redis_spec.rb", "spec/redis/marshaled_redis_spec.rb", "spec/spec_helper.rb"]
12
- s.test_files = ["spec/cache/merb/redis_store_spec.rb", "spec/cache/rails/redis_store_spec.rb", "spec/cache/sinatra/redis_store_spec.rb", "spec/redis/distributed_marshaled_redis_spec.rb", "spec/redis/marshaled_redis_spec.rb"]
11
+ s.files = ["MIT-LICENSE", "README.textile", "Rakefile", "lib/cache/merb/redis_store.rb", "lib/cache/rails/redis_store.rb", "lib/cache/sinatra/redis_store.rb", "lib/rack/cache/redis_entitystore.rb", "lib/rack/cache/redis_metastore.rb", "lib/redis-store.rb", "lib/redis/distributed_marshaled_redis.rb", "lib/redis/marshaled_redis.rb", "redis-store.gemspec", "spec/cache/merb/redis_store_spec.rb", "spec/cache/rails/redis_store_spec.rb", "spec/cache/sinatra/redis_store_spec.rb", "spec/config/master.conf", "spec/config/single.conf", "spec/config/slave.conf", "spec/rack/cache/entitystore/pony.jpg", "spec/rack/cache/entitystore/redis_spec.rb", "spec/rack/cache/metastore/redis_spec.rb", "spec/redis/distributed_marshaled_redis_spec.rb", "spec/redis/marshaled_redis_spec.rb", "spec/spec_helper.rb"]
12
+ s.test_files = ["spec/cache/merb/redis_store_spec.rb", "spec/cache/rails/redis_store_spec.rb", "spec/cache/sinatra/redis_store_spec.rb", "spec/rack/cache/entitystore/redis_spec.rb", "spec/rack/cache/metastore/redis_spec.rb", "spec/redis/distributed_marshaled_redis_spec.rb", "spec/redis/marshaled_redis_spec.rb"]
13
13
  s.extra_rdoc_files = ["README.textile"]
14
14
  end
@@ -0,0 +1,108 @@
1
+ require File.join(File.dirname(__FILE__), "/../../../spec_helper")
2
+
3
+ module Rack
4
+ module Cache
5
+ class MetaStore
6
+ describe "Redis" do
7
+ before(:each) do
8
+ @store = Rack::Cache::EntityStore::Redis.new :host => "localhost"
9
+ end
10
+
11
+ it "should have the class referenced by homonym constant" do
12
+ Rack::Cache::EntityStore::REDIS.should be(Rack::Cache::EntityStore::Redis)
13
+ end
14
+
15
+ it "should resolve the connection uri" do
16
+ cache = Redis.resolve(uri("redis://127.0.0.1")).cache
17
+ cache.should be_kind_of(::MarshaledRedis)
18
+ cache.host.should == "127.0.0.1"
19
+ cache.port.should == "6379"
20
+ cache.instance_variable_get(:@db).should == "0"
21
+
22
+ cache = Redis.resolve(uri("redis://127.0.0.1:6380")).cache
23
+ cache.port.should == 6380
24
+
25
+ cache = Redis.resolve(uri("redis://127.0.0.1/11")).cache
26
+ cache.instance_variable_get(:@db).should == "11"
27
+ end
28
+
29
+ it 'responds to all required messages' do
30
+ %w[read open write exist?].each do |message|
31
+ @store.should respond_to(message)
32
+ end
33
+ end
34
+
35
+ it 'stores bodies with #write' do
36
+ key, size = @store.write(['My wild love went riding,'])
37
+ key.should_not be_nil
38
+ # key.should be_sha_like TODO re-enable
39
+
40
+ data = @store.read(key)
41
+ data.should == 'My wild love went riding,'
42
+ end
43
+
44
+ it 'correctly determines whether cached body exists for key with #exist?' do
45
+ key, size = @store.write(['She rode to the devil,'])
46
+ @store.should be_exist(key)
47
+ @store.should_not be_exist('938jasddj83jasdh4438021ksdfjsdfjsdsf')
48
+ end
49
+
50
+ it 'can read data written with #write' do
51
+ key, size = @store.write(['And asked him to pay.'])
52
+ data = @store.read(key)
53
+ data.should == 'And asked him to pay.'
54
+ end
55
+
56
+ it 'gives a 40 character SHA1 hex digest from #write' do
57
+ key, size = @store.write(['she rode to the sea;'])
58
+ key.should_not be_nil
59
+ key.length.should == 40
60
+ key.should =~ /^[0-9a-z]+$/
61
+ key.should == '90a4c84d51a277f3dafc34693ca264531b9f51b6'
62
+ end
63
+
64
+ it 'returns the entire body as a String from #read' do
65
+ key, size = @store.write(['She gathered together'])
66
+ @store.read(key).should == 'She gathered together'
67
+ end
68
+
69
+ it 'returns nil from #read when key does not exist' do
70
+ @store.read('87fe0a1ae82a518592f6b12b0183e950b4541c62').should be_nil
71
+ end
72
+
73
+ it 'returns a Rack compatible body from #open' do
74
+ key, size = @store.write(['Some shells for her hair.'])
75
+ body = @store.open(key)
76
+ body.should respond_to(:each)
77
+ buf = ''
78
+ body.each { |part| buf << part }
79
+ buf.should == 'Some shells for her hair.'
80
+ end
81
+
82
+ it 'returns nil from #open when key does not exist' do
83
+ @store.open('87fe0a1ae82a518592f6b12b0183e950b4541c62').should be_nil
84
+ end
85
+
86
+ it 'can store largish bodies with binary data' do
87
+ pony = ::File.open(::File.dirname(__FILE__) + '/pony.jpg', 'rb') { |f| f.read }
88
+ key, size = @store.write([pony])
89
+ key.should == 'd0f30d8659b4d268c5c64385d9790024c2d78deb'
90
+ data = @store.read(key)
91
+ data.length.should == pony.length
92
+ data.hash.should == pony.hash
93
+ end
94
+
95
+ it 'deletes stored entries with #purge' do
96
+ key, size = @store.write(['My wild love went riding,'])
97
+ @store.purge(key).should be_nil
98
+ @store.read(key).should be_nil
99
+ end
100
+
101
+ private
102
+ def uri(uri)
103
+ URI.parse uri
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,102 @@
1
+ require File.join(File.dirname(__FILE__), "/../../../spec_helper")
2
+
3
+ module Rack
4
+ module Cache
5
+ class MetaStore
6
+ describe "Redis" do
7
+ before(:each) do
8
+ @store = Redis.resolve uri("redis://127.0.0.1")
9
+ end
10
+
11
+ it "should have the class referenced by homonym constant" do
12
+ Rack::Cache::MetaStore::REDIS.should be(Rack::Cache::MetaStore::Redis)
13
+ end
14
+
15
+ it "should resolve the connection uri" do
16
+ cache = Redis.resolve(uri("redis://127.0.0.1")).cache
17
+ cache.should be_kind_of(::MarshaledRedis)
18
+ cache.host.should == "127.0.0.1"
19
+ cache.port.should == "6379"
20
+ cache.instance_variable_get(:@db).should == "0"
21
+
22
+ cache = Redis.resolve(uri("redis://127.0.0.1:6380")).cache
23
+ cache.port.should == 6380
24
+
25
+ cache = Redis.resolve(uri("redis://127.0.0.1/11")).cache
26
+ cache.instance_variable_get(:@db).should == "11"
27
+ end
28
+
29
+ it 'writes a list of negotation tuples with #write' do
30
+ lambda { @store.write('/test', [[{}, {}]]) }.should_not raise_error
31
+ end
32
+
33
+ it 'reads a list of negotation tuples with #read' do
34
+ @store.write('/test', [[{},{}],[{},{}]])
35
+ tuples = @store.read('/test')
36
+ tuples.should == [ [{},{}], [{},{}] ]
37
+ end
38
+
39
+ it 'reads an empty list with #read when nothing cached at key' do
40
+ @store.read('/nothing').should be_empty
41
+ end
42
+
43
+ it 'removes entries for key with #purge' do
44
+ @store.write('/test', [[{},{}]])
45
+ @store.read('/test').should_not be_empty
46
+
47
+ @store.purge('/test')
48
+ @store.read('/test').should be_empty
49
+ end
50
+
51
+ it 'succeeds when purging non-existing entries' do
52
+ @store.read('/test').should be_empty
53
+ @store.purge('/test')
54
+ end
55
+
56
+ it 'returns nil from #purge' do
57
+ @store.write('/test', [[{},{}]])
58
+ @store.purge('/test').should be_nil
59
+ @store.read('/test').should == []
60
+ end
61
+
62
+ %w[/test http://example.com:8080/ /test?x=y /test?x=y&p=q].each do |key|
63
+ it "can read and write key: '#{key}'" do
64
+ lambda { @store.write(key, [[{},{}]]) }.should_not raise_error
65
+ @store.read(key).should == [[{},{}]]
66
+ end
67
+ end
68
+
69
+ it "can read and write fairly large keys" do
70
+ key = "b" * 4096
71
+ lambda { @store.write(key, [[{},{}]]) }.should_not raise_error
72
+ @store.read(key).should == [[{},{}]]
73
+ end
74
+
75
+ it "allows custom cache keys from block" do
76
+ request = mock_request('/test', {})
77
+ request.env['rack-cache.cache_key'] =
78
+ lambda { |request| request.path_info.reverse }
79
+ @store.cache_key(request).should == 'tset/'
80
+ end
81
+
82
+ it "allows custom cache keys from class" do
83
+ request = mock_request('/test', {})
84
+ request.env['rack-cache.cache_key'] = Class.new do
85
+ def self.call(request); request.path_info.reverse end
86
+ end
87
+ @store.cache_key(request).should == 'tset/'
88
+ end
89
+
90
+ private
91
+ def mock_request(uri, opts)
92
+ env = Rack::MockRequest.env_for(uri, opts || {})
93
+ Rack::Cache::Request.new(env)
94
+ end
95
+
96
+ def uri(uri)
97
+ URI.parse uri
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
data/spec/spec_helper.rb CHANGED
@@ -4,6 +4,9 @@ require "ostruct"
4
4
  require "spec"
5
5
  require "redis"
6
6
  require "merb"
7
+ require "rack/cache"
8
+ require "rack/cache/metastore"
9
+ require "rack/cache/entitystore"
7
10
  require "redis-store"
8
11
  require "activesupport"
9
12
  require "cache/rails/redis_store"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jodosha-redis-store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
@@ -28,6 +28,8 @@ files:
28
28
  - lib/cache/merb/redis_store.rb
29
29
  - lib/cache/rails/redis_store.rb
30
30
  - lib/cache/sinatra/redis_store.rb
31
+ - lib/rack/cache/redis_entitystore.rb
32
+ - lib/rack/cache/redis_metastore.rb
31
33
  - lib/redis-store.rb
32
34
  - lib/redis/distributed_marshaled_redis.rb
33
35
  - lib/redis/marshaled_redis.rb
@@ -38,6 +40,9 @@ files:
38
40
  - spec/config/master.conf
39
41
  - spec/config/single.conf
40
42
  - spec/config/slave.conf
43
+ - spec/rack/cache/entitystore/pony.jpg
44
+ - spec/rack/cache/entitystore/redis_spec.rb
45
+ - spec/rack/cache/metastore/redis_spec.rb
41
46
  - spec/redis/distributed_marshaled_redis_spec.rb
42
47
  - spec/redis/marshaled_redis_spec.rb
43
48
  - spec/spec_helper.rb
@@ -71,5 +76,7 @@ test_files:
71
76
  - spec/cache/merb/redis_store_spec.rb
72
77
  - spec/cache/rails/redis_store_spec.rb
73
78
  - spec/cache/sinatra/redis_store_spec.rb
79
+ - spec/rack/cache/entitystore/redis_spec.rb
80
+ - spec/rack/cache/metastore/redis_spec.rb
74
81
  - spec/redis/distributed_marshaled_redis_spec.rb
75
82
  - spec/redis/marshaled_redis_spec.rb