redis-store 1.0.0.beta2 → 1.0.0.beta3

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.

Potentially problematic release.


This version of redis-store might be problematic. Click here for more details.

Files changed (51) hide show
  1. data/CHANGELOG +74 -23
  2. data/Gemfile +12 -7
  3. data/Gemfile.lock +183 -0
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +49 -14
  6. data/Rakefile +8 -4
  7. data/VERSION +1 -1
  8. data/lib/{rack/session/rails.rb → action_controller/session/redis_session_store.rb} +24 -20
  9. data/lib/{cache/rails → active_support/cache}/redis_store.rb +64 -22
  10. data/lib/cache/merb/redis_store.rb +20 -8
  11. data/lib/cache/sinatra/redis_store.rb +20 -8
  12. data/lib/i18n/backend/redis.rb +67 -0
  13. data/lib/rack/cache/redis_metastore.rb +4 -4
  14. data/lib/rack/session/redis.rb +7 -7
  15. data/lib/redis-store.rb +16 -14
  16. data/lib/redis/distributed_store.rb +35 -0
  17. data/lib/redis/factory.rb +29 -10
  18. data/lib/redis/store.rb +30 -0
  19. data/lib/redis/store/interface.rb +17 -0
  20. data/lib/redis/store/marshalling.rb +41 -0
  21. data/lib/redis/store/namespace.rb +54 -0
  22. data/lib/redis/store/ttl.rb +37 -0
  23. data/lib/redis/store/version.rb +12 -0
  24. data/redis-store.gemspec +32 -20
  25. data/spec/action_controller/session/redis_session_store_spec.rb +121 -0
  26. data/spec/{cache/rails → active_support/cache}/redis_store_spec.rb +93 -19
  27. data/spec/cache/merb/redis_store_spec.rb +14 -11
  28. data/spec/cache/sinatra/redis_store_spec.rb +14 -11
  29. data/spec/config/master.conf +1 -1
  30. data/spec/config/single.conf +1 -1
  31. data/spec/config/slave.conf +1 -1
  32. data/spec/i18n/backend/redis_spec.rb +56 -0
  33. data/spec/rack/cache/entitystore/redis_spec.rb +10 -8
  34. data/spec/rack/cache/metastore/redis_spec.rb +2 -2
  35. data/spec/rack/session/redis_spec.rb +6 -6
  36. data/spec/redis/distributed_store_spec.rb +47 -0
  37. data/spec/redis/factory_spec.rb +58 -16
  38. data/spec/redis/store/interface_spec.rb +23 -0
  39. data/spec/redis/store/marshalling_spec.rb +83 -0
  40. data/spec/redis/store/namespace_spec.rb +76 -0
  41. data/spec/redis/store/version_spec.rb +7 -0
  42. data/spec/spec_helper.rb +16 -5
  43. data/tasks/redis.tasks.rb +19 -12
  44. metadata +33 -21
  45. data/lib/redis/distributed_marshaled.rb +0 -28
  46. data/lib/redis/marshaled_client.rb +0 -65
  47. data/lib/redis_store/version.rb +0 -10
  48. data/spec/rack/session/redis_session_store_spec.rb +0 -75
  49. data/spec/redis/distributed_marshaled_redis_spec.rb +0 -33
  50. data/spec/redis/marshaled_client_spec.rb +0 -83
  51. data/spec/redis_store/version_spec.rb +0 -7
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "/../../../spec_helper")
1
+ require 'spec_helper'
2
2
 
3
3
  class Object
4
4
  def sha_like?
@@ -92,13 +92,15 @@ module Rack
92
92
  @store.open('87fe0a1ae82a518592f6b12b0183e950b4541c62').should be_nil
93
93
  end
94
94
 
95
- it 'can store largish bodies with binary data' do
96
- pony = ::File.open(::File.dirname(__FILE__) + '/pony.jpg', 'rb') { |f| f.read }
97
- key, size = @store.write([pony])
98
- key.should == 'd0f30d8659b4d268c5c64385d9790024c2d78deb'
99
- data = @store.read(key)
100
- data.length.should == pony.length
101
- data.hash.should == pony.hash
95
+ if RUBY_VERSION < '1.9'
96
+ it 'can store largish bodies with binary data' do
97
+ pony = ::File.open(::File.dirname(__FILE__) + '/pony.jpg', 'rb') { |f| f.read }
98
+ key, size = @store.write([pony])
99
+ key.should == 'd0f30d8659b4d268c5c64385d9790024c2d78deb'
100
+ data = @store.read(key)
101
+ data.length.should == pony.length
102
+ data.hash.should == pony.hash
103
+ end
102
104
  end
103
105
 
104
106
  it 'deletes stored entries with #purge' do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "/../../../spec_helper")
1
+ require 'spec_helper'
2
2
 
3
3
  module Rack
4
4
  module Cache
@@ -23,7 +23,7 @@ module Rack
23
23
 
24
24
  it "should resolve the connection uri" do
25
25
  cache = Rack::Cache::MetaStore::Redis.resolve(uri("redis://127.0.0.1")).cache
26
- cache.should be_kind_of(::Redis::MarshaledClient)
26
+ cache.should be_kind_of(::Redis::Store)
27
27
  cache.to_s.should == "Redis Client connected to 127.0.0.1:6379 against DB 0"
28
28
 
29
29
  cache = Rack::Cache::MetaStore::Redis.resolve(uri("redis://127.0.0.1:6380")).cache
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "/../../spec_helper")
1
+ require 'spec_helper'
2
2
 
3
3
  module Rack
4
4
  module Session
@@ -26,12 +26,12 @@ module Rack
26
26
  end
27
27
 
28
28
  it "should specify connection params" do
29
- pool = Rack::Session::Redis.new(@incrementor, :redis_server => "localhost:6380/1").pool
30
- pool.should be_kind_of(::Redis::MarshaledClient)
31
- pool.to_s.should == "Redis Client connected to localhost:6380 against DB 1"
29
+ pool = Rack::Session::Redis.new(@incrementor, :redis_server => "redis://127.0.0.1:6380/1/theplaylist").pool
30
+ pool.should be_kind_of(::Redis::Store)
31
+ pool.to_s.should == "Redis Client connected to 127.0.0.1:6380 against DB 1 with namespace theplaylist"
32
32
 
33
- pool = Rack::Session::Redis.new(@incrementor, :redis_server => ["localhost:6379", "localhost:6380"]).pool
34
- pool.should be_kind_of(::Redis::DistributedMarshaled)
33
+ pool = Rack::Session::Redis.new(@incrementor, :redis_server => ["redis://127.0.0.1:6379", "redis://127.0.0.1:6380"]).pool
34
+ pool.should be_kind_of(::Redis::DistributedStore)
35
35
  end
36
36
 
37
37
  it "creates a new cookie" do
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Redis::DistributedStore" do
4
+ before(:each) do
5
+ @dmr = Redis::DistributedStore.new [
6
+ {:host => "localhost", :port => "6380", :db => 0},
7
+ {:host => "localhost", :port => "6381", :db => 0}
8
+ ]
9
+ @rabbit = OpenStruct.new :name => "bunny"
10
+ @white_rabbit = OpenStruct.new :color => "white"
11
+ @dmr.set "rabbit", @rabbit
12
+ end
13
+
14
+ after(:all) do
15
+ @dmr.ring.nodes.each { |server| server.flushdb }
16
+ end
17
+
18
+ it "should accept connection params" do
19
+ dmr = Redis::DistributedStore.new [ :host => "localhost", :port => "6380", :db => "1" ]
20
+ dmr.ring.nodes.size == 1
21
+ mr = dmr.ring.nodes.first
22
+ mr.to_s.should == "Redis Client connected to localhost:6380 against DB 1"
23
+ end
24
+
25
+ it "should set an object" do
26
+ @dmr.set "rabbit", @white_rabbit
27
+ @dmr.get("rabbit").should == @white_rabbit
28
+ end
29
+
30
+ it "should get an object" do
31
+ @dmr.get("rabbit").should == @rabbit
32
+ end
33
+
34
+ describe "namespace" do
35
+ before :each do
36
+ @dmr = Redis::DistributedStore.new [
37
+ {:host => "localhost", :port => "6380", :db => 0},
38
+ {:host => "localhost", :port => "6381", :db => 0}
39
+ ], :namespace => "theplaylist"
40
+ end
41
+
42
+ it "should use namespaced key" do
43
+ @dmr.should_receive(:node_for).with("theplaylist:rabbit").and_return @dmr.nodes.first
44
+ @dmr.get "rabbit"
45
+ end
46
+ end
47
+ end
@@ -1,11 +1,11 @@
1
- require File.join(File.dirname(__FILE__), "/../spec_helper")
1
+ require 'spec_helper'
2
2
 
3
3
  describe "Redis::Factory" do
4
4
  describe ".create" do
5
5
  context "when not given any arguments" do
6
- it "should instantiate a Redis::MarshaledClient store" do
6
+ it "should instantiate a Redis::Store store" do
7
7
  store = Redis::Factory.create
8
- store.should be_kind_of(Redis::MarshaledClient)
8
+ store.should be_kind_of(Redis::Store)
9
9
  store.to_s.should == "Redis Client connected to 127.0.0.1:6379 against DB 0"
10
10
  end
11
11
  end
@@ -26,12 +26,32 @@ describe "Redis::Factory" do
26
26
  store.to_s.should == "Redis Client connected to localhost:6380 against DB 13"
27
27
  end
28
28
 
29
- it "should instantiate a Redis::DistributedMarshaled store" do
29
+ it "should allow to specify namespace" do
30
+ store = Redis::Factory.create :namespace => "theplaylist"
31
+ store.to_s.should == "Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist"
32
+ end
33
+
34
+ it "should allow to specify key_prefix as namespace" do
35
+ store = Redis::Factory.create :key_prefix => "theplaylist"
36
+ store.to_s.should == "Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist"
37
+ end
38
+
39
+ it "should allow to specify marshalling" do
40
+ store = Redis::Factory.create :marshalling => false
41
+ store.instance_variable_get(:@marshalling).should be_false
42
+ end
43
+
44
+ it "should allow to specify password" do
45
+ store = Redis::Factory.create :password => "secret"
46
+ store.instance_variable_get(:@client).password.should == "secret"
47
+ end
48
+
49
+ it "should instantiate a Redis::DistributedStore store" do
30
50
  store = Redis::Factory.create(
31
51
  {:host => "localhost", :port => 6379},
32
52
  {:host => "localhost", :port => 6380}
33
53
  )
34
- store.should be_kind_of(Redis::DistributedMarshaled)
54
+ store.should be_kind_of(Redis::DistributedStore)
35
55
  store.nodes.map {|node| node.to_s}.should == [
36
56
  "Redis Client connected to localhost:6379 against DB 0",
37
57
  "Redis Client connected to localhost:6380 against DB 0",
@@ -41,26 +61,48 @@ describe "Redis::Factory" do
41
61
 
42
62
  context "when given a String" do
43
63
  it "should allow to specify host" do
44
- store = Redis::Factory.create "localhost"
45
- store.to_s.should == "Redis Client connected to localhost:6379 against DB 0"
64
+ store = Redis::Factory.create "redis://127.0.0.1"
65
+ store.to_s.should == "Redis Client connected to 127.0.0.1:6379 against DB 0"
46
66
  end
47
67
 
48
68
  it "should allow to specify port" do
49
- store = Redis::Factory.create "localhost:6380"
50
- store.to_s.should == "Redis Client connected to localhost:6380 against DB 0"
69
+ store = Redis::Factory.create "redis://127.0.0.1:6380"
70
+ store.to_s.should == "Redis Client connected to 127.0.0.1:6380 against DB 0"
51
71
  end
52
72
 
53
73
  it "should allow to specify db" do
54
- store = Redis::Factory.create "localhost:6380/13"
55
- store.to_s.should == "Redis Client connected to localhost:6380 against DB 13"
74
+ store = Redis::Factory.create "redis://127.0.0.1:6380/13"
75
+ store.to_s.should == "Redis Client connected to 127.0.0.1:6380 against DB 13"
76
+ end
77
+
78
+ it "should allow to specify namespace" do
79
+ store = Redis::Factory.create "redis://127.0.0.1:6379/0/theplaylist"
80
+ store.to_s.should == "Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist"
56
81
  end
57
82
 
58
- it "should instantiate a Redis::DistributedMarshaled store" do
59
- store = Redis::Factory.create "localhost:6379", "localhost:6380"
60
- store.should be_kind_of(Redis::DistributedMarshaled)
83
+ it "should allow to specify scheme" do
84
+ store = Redis::Factory.create "redis://127.0.0.1:6379/0/theplaylist"
85
+ store.to_s.should == "Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist"
86
+ end
87
+
88
+ it "should allow to specify password" do
89
+ store = Redis::Factory.create "redis://:secret@127.0.0.1:6379/0/theplaylist"
90
+ store.instance_variable_get(:@client).password.should == "secret"
91
+ end
92
+
93
+ it "should allow to specify password without scheme" do
94
+ suppress_warnings do
95
+ store = Redis::Factory.create ":secret@127.0.0.1:6379/0/theplaylist"
96
+ store.instance_variable_get(:@client).password.should == "secret"
97
+ end
98
+ end
99
+
100
+ it "should instantiate a Redis::DistributedStore store" do
101
+ store = Redis::Factory.create "redis://127.0.0.1:6379", "redis://127.0.0.1:6380"
102
+ store.should be_kind_of(Redis::DistributedStore)
61
103
  store.nodes.map {|node| node.to_s}.should == [
62
- "Redis Client connected to localhost:6379 against DB 0",
63
- "Redis Client connected to localhost:6380 against DB 0",
104
+ "Redis Client connected to 127.0.0.1:6379 against DB 0",
105
+ "Redis Client connected to 127.0.0.1:6380 against DB 0",
64
106
  ]
65
107
  end
66
108
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ class InterfacedRedis < Redis
4
+ include Redis::Store::Interface
5
+ end
6
+
7
+ describe "Redis::Store::Interface" do
8
+ before :each do
9
+ @r = InterfacedRedis.new
10
+ end
11
+
12
+ it "should get an element" do
13
+ lambda { @r.get("key", :option => true) }.should_not raise_error
14
+ end
15
+
16
+ it "should set an element" do
17
+ lambda { @r.set("key", "value", :option => true) }.should_not raise_error
18
+ end
19
+
20
+ it "should setnx an element" do
21
+ lambda { @r.setnx("key", "value", :option => true) }.should_not raise_error
22
+ end
23
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Redis::Marshalling" do
4
+ before(:each) do
5
+ @store = Redis::Store.new :marshalling => true
6
+ @rabbit = OpenStruct.new :name => "bunny"
7
+ @white_rabbit = OpenStruct.new :color => "white"
8
+ @store.set "rabbit", @rabbit
9
+ @store.del "rabbit2"
10
+ end
11
+
12
+ after :each do
13
+ @store.quit
14
+ end
15
+
16
+ it "should unmarshal an object on get" do
17
+ @store.get("rabbit").should === @rabbit
18
+ end
19
+
20
+ it "should marshal object on set" do
21
+ @store.set "rabbit", @white_rabbit
22
+ @store.get("rabbit").should === @white_rabbit
23
+ end
24
+
25
+ if RUBY_VERSION.match /1\.9/
26
+ it "should not unmarshal object on get if raw option is true" do
27
+ @store.get("rabbit", :raw => true).should == "\x04\bU:\x0FOpenStruct{\x06:\tnameI\"\nbunny\x06:\x06EF"
28
+ end
29
+ else
30
+ it "should not unmarshal object on get if raw option is true" do
31
+ @store.get("rabbit", :raw => true).should == "\004\bU:\017OpenStruct{\006:\tname\"\nbunny"
32
+ end
33
+ end
34
+
35
+ it "should not marshal object on set if raw option is true" do
36
+ @store.set "rabbit", @white_rabbit, :raw => true
37
+ @store.get("rabbit", :raw => true).should == %(#<OpenStruct color="white">)
38
+ end
39
+
40
+ it "should not unmarshal object if getting an empty string" do
41
+ @store.set "empty_string", ""
42
+ lambda { @store.get("empty_string").should == "" }.should_not raise_error
43
+ end
44
+
45
+ it "should not set an object if already exist" do
46
+ @store.setnx "rabbit", @white_rabbit
47
+ @store.get("rabbit").should === @rabbit
48
+ end
49
+
50
+ it "should marshal object on set_unless_exists" do
51
+ @store.setnx "rabbit2", @white_rabbit
52
+ @store.get("rabbit2").should === @white_rabbit
53
+ end
54
+
55
+ it "should not marshal object on set_unless_exists if raw option is true" do
56
+ @store.setnx "rabbit2", @white_rabbit, :raw => true
57
+ @store.get("rabbit2", :raw => true).should == %(#<OpenStruct color="white">)
58
+ end
59
+
60
+ it "should unmarshal object(s) on multi get" do
61
+ @store.set "rabbit2", @white_rabbit
62
+ rabbit, rabbit2 = @store.mget "rabbit", "rabbit2"
63
+ rabbit.should == @rabbit
64
+ rabbit2.should == @white_rabbit
65
+ end
66
+
67
+ if RUBY_VERSION.match /1\.9/
68
+ it "should not unmarshal object(s) on multi get if raw option is true" do
69
+ @store.set "rabbit2", @white_rabbit
70
+ rabbit, rabbit2 = @store.mget "rabbit", "rabbit2", :raw => true
71
+ rabbit.should == "\x04\bU:\x0FOpenStruct{\x06:\tnameI\"\nbunny\x06:\x06EF"
72
+ rabbit2.should == "\x04\bU:\x0FOpenStruct{\x06:\ncolorI\"\nwhite\x06:\x06EF"
73
+ end
74
+ else
75
+ it "should not unmarshal object(s) on multi get if raw option is true" do
76
+ @store.set "rabbit2", @white_rabbit
77
+ rabbit, rabbit2 = @store.mget "rabbit", "rabbit2", :raw => true
78
+ rabbit.should == "\004\bU:\017OpenStruct{\006:\tname\"\nbunny"
79
+ rabbit2.should == "\004\bU:\017OpenStruct{\006:\ncolor\"\nwhite"
80
+ end
81
+ end
82
+ end
83
+
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Redis::Store::Namespace" do
4
+ before :each do
5
+ @namespace = "theplaylist"
6
+ @store = Redis::Store.new :namespace => @namespace, :marshalling => false # TODO remove mashalling option
7
+ @client = @store.instance_variable_get(:@client)
8
+ @rabbit = "bunny"
9
+ end
10
+
11
+ after :each do
12
+ @store.should_receive(:quit) # stupid rspec, meh!
13
+ @store.quit
14
+ end
15
+
16
+ it "should only decorate instances that needs to be namespaced" do
17
+ @store = Redis::Store.new
18
+ client = @store.instance_variable_get(:@client)
19
+ client.should_receive(:call).with(:get, "rabbit")
20
+ @store.get("rabbit")
21
+ end
22
+
23
+ it "should not namespace a key which is already namespaced" do
24
+ @store.send(:interpolate, "#{@namespace}:rabbit").should == "#{@namespace}:rabbit"
25
+ end
26
+
27
+ it "should namespace get" do
28
+ @client.should_receive(:call).with(:get, "#{@namespace}:rabbit")
29
+ @store.get("rabbit")
30
+ end
31
+
32
+ it "should namespace set" do
33
+ @client.should_receive(:call).with(:set, "#{@namespace}:rabbit", @rabbit)
34
+ @store.set "rabbit", @rabbit
35
+ end
36
+
37
+ it "should namespace setnx" do
38
+ @client.should_receive(:call).with(:setnx, "#{@namespace}:rabbit", @rabbit)
39
+ @store.setnx "rabbit", @rabbit
40
+ end
41
+
42
+ it "should namespace del with single key" do
43
+ @client.should_receive(:call).with(:del, "#{@namespace}:rabbit")
44
+ @store.del "rabbit"
45
+ end
46
+
47
+ it "should namespace del with multiple keys" do
48
+ @client.should_receive(:call).with(:del, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit")
49
+ @store.del "rabbit", "white_rabbit"
50
+ end
51
+
52
+ it "should namespace keys" do
53
+ @client.should_receive(:call).with(:keys, "#{@namespace}:rabb*").and_return [ "#{@namespace}:rabbit" ]
54
+ @store.keys "rabb*"
55
+ end
56
+
57
+ it "should namespace exists" do
58
+ @client.should_receive(:call).with(:exists, "#{@namespace}:rabbit")
59
+ @store.exists "rabbit"
60
+ end
61
+
62
+ it "should namespace incrby" do
63
+ @client.should_receive(:call).with(:incrby, "#{@namespace}:counter", 1)
64
+ @store.incrby "counter", 1
65
+ end
66
+
67
+ it "should namespace decrby" do
68
+ @client.should_receive(:call).with(:decrby, "#{@namespace}:counter", 1)
69
+ @store.decrby "counter", 1
70
+ end
71
+
72
+ it "should namespace mget" do
73
+ @client.should_receive(:call).with(:mget, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit")
74
+ @store.mget "rabbit", "white_rabbit"
75
+ end
76
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Redis::Store::VERSION do
4
+ it "should describe Redis::Store version" do
5
+ Redis::Store::VERSION::STRING.should == "1.0.0.beta3"
6
+ end
7
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,13 +3,13 @@ ARGV << "-b"
3
3
  require "rubygems"
4
4
  require "bundler"
5
5
  Bundler.setup
6
-
7
- #require "vendor/gems/environment"
6
+ require "methopara" if RUBY_VERSION.match /1\.9/
8
7
  require "ostruct"
9
8
  require "spec"
10
9
  require "spec/autorun"
11
10
  require "redis"
12
11
  require "merb"
12
+ require "i18n"
13
13
  require "rack/cache"
14
14
  require "rack/cache/metastore"
15
15
  require "rack/cache/entitystore"
@@ -19,10 +19,21 @@ begin
19
19
  require "action_controller/session/abstract_store" # Rails 2.3.x
20
20
  rescue LoadError
21
21
  require "action_dispatch/middleware/session/abstract_store" # Rails 3.x
22
- module Rails; def self.version; "3.0.0.beta4" end end unless defined?(Rails)
22
+ module Rails; def self.version; "3.0.0" end end unless defined?(Rails)
23
23
  end
24
- require "cache/rails/redis_store"
25
- require "rack/session/rails"
24
+ require "active_support/cache/redis_store"
25
+ require "action_controller/session/redis_session_store"
26
26
  require "cache/sinatra/redis_store"
27
27
 
28
28
  $DEBUG = ENV["DEBUG"] === "true"
29
+
30
+ # http://mentalized.net/journal/2010/04/02/suppress_warnings_from_ruby/
31
+ module Kernel
32
+ def suppress_warnings
33
+ original_verbosity = $VERBOSE
34
+ $VERBOSE = nil
35
+ result = yield
36
+ $VERBOSE = original_verbosity
37
+ return result
38
+ end
39
+ end