redis_buddy 0.1.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,27 @@
1
+ # a namespaced Redis Cache Store for Rails 3
2
+
3
+ ## Installation
4
+
5
+ gem install redis_buddy
6
+
7
+
8
+ ## Configuration
9
+
10
+ ### Gemfile
11
+
12
+ gem "redis_buddy"
13
+
14
+ ### config/application.rb
15
+
16
+ config.cache_store = :redis_buddy_store
17
+
18
+ or
19
+
20
+ config.cache_store = :redis_buddy_store, ['127.0.0.1', '1.2.3.4']
21
+
22
+
23
+ ## Copyright
24
+
25
+ (c) 2010 Ole Riesenberg, released under the MIT license
26
+
27
+ redis-store (c) 2009 Luca Guidi - [http://lucaguidi.com](http://lucaguidi.com), released under the MIT license
@@ -0,0 +1,13 @@
1
+ # (c) 2009 Luca Guidi
2
+
3
+ class DistributedMarshaledRedis < DistRedis
4
+ def initialize(addresses)
5
+ nodes = addresses.map do |address|
6
+ MarshaledRedis.new address
7
+ end
8
+ @ring = RedisRb::HashRing.new nodes
9
+ end
10
+
11
+ alias_method :flush_db, :delete_cloud!
12
+ end
13
+
@@ -0,0 +1,36 @@
1
+ # (c) 2009 Luca Guidi
2
+
3
+ class MarshaledRedis < Redis
4
+ def set(key, val, options = nil)
5
+ val = Marshal.dump val unless raw?(options)
6
+ super key, val, expires_in(options)
7
+ end
8
+
9
+ def set_unless_exists(key, val, options = nil)
10
+ val = Marshal.dump val unless raw?(options)
11
+ super key, val
12
+ end
13
+
14
+ def get(key, options = nil)
15
+ result = call_command([:get, key])
16
+ result = Marshal.load result if unmarshal?(result, options)
17
+ result
18
+ end
19
+
20
+ private
21
+ def unmarshal?(result, options)
22
+ result && result.size > 0 && !raw?(options)
23
+ end
24
+
25
+ def raw?(options)
26
+ options && options[:raw]
27
+ end
28
+
29
+ def expires_in(options)
30
+ if options
31
+ # Rack::Session Merb Rails/Sinatra
32
+ options[:expire_after] || options[:expires_in] || options[:expire_in]
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,29 @@
1
+ # (c) 2009 Luca Guidi
2
+
3
+ class RedisFactory
4
+ class << self
5
+ def create(*addresses)
6
+ addresses = extract_addresses(addresses)
7
+ if addresses.size > 1
8
+ DistributedMarshaledRedis.new addresses
9
+ else
10
+ MarshaledRedis.new addresses.first || {}
11
+ end
12
+ end
13
+
14
+ private
15
+ def extract_addresses(addresses)
16
+ addresses = addresses.flatten.compact
17
+ addresses.inject([]) do |result, address|
18
+ host, port = address.split /\:/
19
+ port, db = port.split /\// if port
20
+ address = {}
21
+ address[:host] = host if host
22
+ address[:port] = port if port
23
+ address[:db] = db.to_i if db
24
+ result << address
25
+ result
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,64 @@
1
+ module ActiveSupport
2
+ module Cache
3
+ class RedisBuddyStore < Store
4
+ def initialize(*adresses)
5
+ ns = Rails.application.class.to_s.split('::').first.downcase
6
+ @r = RedisFactory.create(adresses)
7
+ @data = Redis::Namespace.new(ns, :redis => @r)
8
+ end
9
+
10
+ def write(key, value, options = nil)
11
+ super do
12
+ method = options && options[:unless_exist] ? :set_unless_exists : :set
13
+ @data.send method, key, value, options
14
+ @data.expire key, options[:expire] if options && options[:expire]
15
+ end
16
+ end
17
+
18
+ def read(key, options = nil)
19
+ super do
20
+ @data.get key, options
21
+ end
22
+ end
23
+
24
+ def ttl(key, options = nil)
25
+ @data.ttl key, options
26
+ end
27
+
28
+ def delete(key, options = nil)
29
+ super do
30
+ @data.delete key
31
+ end
32
+ end
33
+
34
+ def exist?(key, options = nil)
35
+ super do
36
+ @data.key? key
37
+ end
38
+ end
39
+
40
+ def increment(key, amount = 1)
41
+ @data.incr key, amount
42
+ end
43
+
44
+ def decrement(key, amount = 1)
45
+ @data.decr key, amount
46
+ end
47
+
48
+ def delete_matched(matcher, options = nil)
49
+ super do
50
+ @data.keys(matcher).each { |key| @data.delete key }
51
+ end
52
+ end
53
+
54
+ def clear
55
+ @data.flush_db
56
+ end
57
+
58
+ def info
59
+ @data.info
60
+ end
61
+ end
62
+ end
63
+ end
64
+
@@ -0,0 +1,9 @@
1
+ require 'redis'
2
+ require 'redis/dist_redis'
3
+ require 'redis/namespace'
4
+
5
+ require 'redis/redis_factory'
6
+ require 'redis/marshaled_redis'
7
+ require 'redis/distributed_marshaled_redis'
8
+
9
+ require 'redis_buddy/cache_store'
@@ -0,0 +1,173 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper")
2
+
3
+ module ActiveSupport
4
+ module Cache
5
+ describe "ActiveSupport::Cache::RedisBuddyStore" do
6
+ before(:each) do
7
+ @store = ActiveSupport::Cache::RedisBuddyStore.new
8
+ @dstore = ActiveSupport::Cache::RedisBuddyStore.new "localhost:6380/1", "localhost:6381/1"
9
+ @rabbit = OpenStruct.new :name => "bunny"
10
+ @white_rabbit = OpenStruct.new :color => "white"
11
+ with_store_management do |store|
12
+ store.write "rabbit", @rabbit
13
+ store.delete "counter"
14
+ store.delete "rub-a-dub"
15
+ end
16
+ end
17
+
18
+ it "should accept connection params" do
19
+ redis = instantiate_store
20
+ redis.host.should == "127.0.0.1"
21
+ redis.port.should == 6379
22
+ redis.db.should == 0
23
+
24
+ redis = instantiate_store "localhost"
25
+ redis.host.should == "localhost"
26
+
27
+ redis = instantiate_store "localhost:6380"
28
+ redis.host.should == "localhost"
29
+ redis.port.should == 6380
30
+
31
+ redis = instantiate_store "localhost:6380/13"
32
+ redis.host.should == "localhost"
33
+ redis.port.should == 6380
34
+ redis.db.should == 13
35
+ end
36
+
37
+ it "should instantiate a ring" do
38
+ store = instantiate_store
39
+ store.should be_kind_of(MarshaledRedis)
40
+ store = instantiate_store ["localhost:6379/0", "localhost:6379/1"]
41
+ store.should be_kind_of(DistributedMarshaledRedis)
42
+ end
43
+
44
+ it "should read the data" do
45
+ with_store_management do |store|
46
+ store.read("rabbit").should === @rabbit
47
+ end
48
+ end
49
+
50
+ it "should write the data" do
51
+ with_store_management do |store|
52
+ store.write "rabbit", @white_rabbit
53
+ store.read("rabbit").should === @white_rabbit
54
+ end
55
+ end
56
+
57
+ it "should write the data with expiration time" do
58
+ with_store_management do |store|
59
+ store.write "rabbit", @white_rabbit, :expires_in => 1.second
60
+ store.read("rabbit").should === @white_rabbit ; sleep 2
61
+ store.read("rabbit").should be_nil
62
+ end
63
+ end
64
+
65
+ it "should not write data if :unless_exist option is true" do
66
+ with_store_management do |store|
67
+ store.write "rabbit", @white_rabbit, :unless_exist => true
68
+ store.read("rabbit").should === @rabbit
69
+ end
70
+ end
71
+
72
+ it "should read raw data" do
73
+ with_store_management do |store|
74
+ store.read("rabbit", :raw => true).should == "\004\bU:\017OpenStruct{\006:\tname\"\nbunny"
75
+ end
76
+ end
77
+
78
+ it "should write raw data" do
79
+ with_store_management do |store|
80
+ store.write "rabbit", @white_rabbit, :raw => true
81
+ store.read("rabbit", :raw => true).should == %(#<OpenStruct color="white">)
82
+ end
83
+ end
84
+
85
+ it "should delete data" do
86
+ with_store_management do |store|
87
+ store.delete "rabbit"
88
+ store.read("rabbit").should be_nil
89
+ end
90
+ end
91
+
92
+ it "should delete matched data" do
93
+ with_store_management do |store|
94
+ store.delete_matched "rabb*"
95
+ store.read("rabbit").should be_nil
96
+ end
97
+ end
98
+
99
+ it "should verify existence of an object in the store" do
100
+ with_store_management do |store|
101
+ store.exist?("rabbit").should be_true
102
+ store.exist?("rab-a-dub").should be_false
103
+ end
104
+ end
105
+
106
+ it "should increment a key" do
107
+ with_store_management do |store|
108
+ 3.times { store.increment "counter" }
109
+ store.read("counter", :raw => true).to_i.should == 3
110
+ end
111
+ end
112
+
113
+ it "should decrement a key" do
114
+ with_store_management do |store|
115
+ 3.times { store.increment "counter" }
116
+ 2.times { store.decrement "counter" }
117
+ store.read("counter", :raw => true).to_i.should == 1
118
+ end
119
+ end
120
+
121
+ it "should increment a key by given value" do
122
+ with_store_management do |store|
123
+ store.increment "counter", 3
124
+ store.read("counter", :raw => true).to_i.should == 3
125
+ end
126
+ end
127
+
128
+ it "should decrement a key by given value" do
129
+ with_store_management do |store|
130
+ 3.times { store.increment "counter" }
131
+ store.decrement "counter", 2
132
+ store.read("counter", :raw => true).to_i.should == 1
133
+ end
134
+ end
135
+
136
+ it "should clear the store" do
137
+ with_store_management do |store|
138
+ store.clear
139
+ store.instance_variable_get(:@data).keys("*").flatten.should be_empty
140
+ end
141
+ end
142
+
143
+ it "should return store stats" do
144
+ with_store_management do |store|
145
+ store.stats.should_not be_empty
146
+ end
147
+ end
148
+
149
+ it "should fetch data" do
150
+ with_store_management do |store|
151
+ store.fetch("rabbit").should == @rabbit
152
+ store.fetch("rub-a-dub").should be_nil
153
+ store.fetch("rub-a-dub") { "Flora de Cana" }
154
+ store.fetch("rub-a-dub").should === "Flora de Cana"
155
+ store.fetch("rabbit", :force => true).should be_nil # force cache miss
156
+ store.fetch("rabbit", :force => true, :expires_in => 1.second) { @white_rabbit }
157
+ store.fetch("rabbit").should === @white_rabbit ; sleep 2
158
+ store.fetch("rabbit").should be_nil
159
+ end
160
+ end
161
+
162
+ private
163
+ def instantiate_store(addresses = nil)
164
+ ActiveSupport::Cache::RedisBuddyStore.new(addresses).instance_variable_get(:@data)
165
+ end
166
+
167
+ def with_store_management
168
+ yield @store
169
+ yield @dstore
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper")
2
+
3
+ describe "DistributedMarshaledRedis" do
4
+ before(:each) do
5
+ @dmr = DistributedMarshaledRedis.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.flush_db }
16
+ end
17
+
18
+ it "should accept connection params" do
19
+ dmr = DistributedMarshaledRedis.new [ :host => "localhost", :port => "6380", :db => "1" ]
20
+ dmr.ring.should have(1).node
21
+ mr = dmr.ring.nodes.first
22
+ mr.host.should == "localhost"
23
+ mr.port.should == 6380
24
+ mr.db.should == 1
25
+ end
26
+
27
+ it "should set an object" do
28
+ @dmr.set "rabbit", @white_rabbit
29
+ @dmr.get("rabbit").should == @white_rabbit
30
+ end
31
+
32
+ it "should get an object" do
33
+ @dmr.get("rabbit").should == @rabbit
34
+ end
35
+ end
@@ -0,0 +1,54 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper")
2
+
3
+ describe "MarshaledRedis" do
4
+ before(:each) do
5
+ @store = MarshaledRedis.new
6
+ @rabbit = OpenStruct.new :name => "bunny"
7
+ @white_rabbit = OpenStruct.new :color => "white"
8
+ @store.set "rabbit", @rabbit
9
+ @store.delete "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
+ it "should not unmarshal object on get if raw option is true" do
26
+ @store.get("rabbit", :raw => true).should == "\004\bU:\017OpenStruct{\006:\tname\"\nbunny"
27
+ end
28
+
29
+ it "should not marshal object on set if raw option is true" do
30
+ @store.set "rabbit", @white_rabbit, :raw => true
31
+ @store.get("rabbit", :raw => true).should == %(#<OpenStruct color="white">)
32
+ end
33
+
34
+ it "should not unmarshal object if getting an empty string" do
35
+ @store.set "empty_string", ""
36
+ lambda { @store.get("empty_string").should == "" }.should_not raise_error
37
+ end
38
+
39
+ it "should not set an object if already exist" do
40
+ @store.set_unless_exists "rabbit", @white_rabbit
41
+ @store.get("rabbit").should === @rabbit
42
+ end
43
+
44
+ it "should marshal object on set_unless_exists" do
45
+ @store.set_unless_exists "rabbit2", @white_rabbit
46
+ @store.get("rabbit2").should === @white_rabbit
47
+ end
48
+
49
+ it "should not marshal object on set_unless_exists if raw option is true" do
50
+ @store.set_unless_exists "rabbit2", @white_rabbit, :raw => true
51
+ @store.get("rabbit2", :raw => true).should == %(#<OpenStruct color="white">)
52
+ end
53
+ end
54
+
@@ -0,0 +1,34 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper")
2
+
3
+ describe "RedisFactory" do
4
+ it "should instantiate a MarshaledRedis store" do
5
+ store = RedisFactory.create
6
+ store.should be_kind_of(MarshaledRedis)
7
+ store.host.should == "127.0.0.1"
8
+ store.port.should == 6379
9
+ store.db.should == 0
10
+ end
11
+
12
+ it "should allow to specify host" do
13
+ store = RedisFactory.create "localhost"
14
+ store.host.should == "localhost"
15
+ end
16
+
17
+ it "should allow to specify port" do
18
+ store = RedisFactory.create "localhost:6380"
19
+ store.host.should == "localhost"
20
+ store.port.should == 6380
21
+ end
22
+
23
+ it "should allow to specify db" do
24
+ store = RedisFactory.create "localhost:6380/13"
25
+ store.host.should == "localhost"
26
+ store.port.should == 6380
27
+ store.db.should == 13
28
+ end
29
+
30
+ it "should instantiate a DistributedMarshaledRedis store" do
31
+ store = RedisFactory.create "localhost:6379", "localhost:6380"
32
+ store.should be_kind_of(DistributedMarshaledRedis)
33
+ end
34
+ end
@@ -0,0 +1,14 @@
1
+ $: << File.join(File.dirname(__FILE__), "/../lib")
2
+ require 'bundler'
3
+ Bundler.setup :testing
4
+ require "ostruct"
5
+ require "spec"
6
+ require "redis"
7
+ require "rails"
8
+ require "redis_buddy"
9
+
10
+ require "cache/redis_buddy_store"
11
+
12
+ class Redis; attr_reader :host, :port, :db end
13
+ $DEBUG = ENV["DEBUG"] === "true"
14
+
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis_buddy
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 1
9
+ version: 0.1.1
10
+ platform: ruby
11
+ authors:
12
+ - Ole Riesenberg
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-26 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: redis
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 2
30
+ - 0
31
+ version: 0.2.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: redis-namespace
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 3
44
+ - 0
45
+ version: 0.3.0
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ description: A namespaced Redis Cache Store for Rails 3, based on redis-store
49
+ email: labs@buddybrand.de
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ extra_rdoc_files:
55
+ - README.md
56
+ files:
57
+ - lib/redis/distributed_marshaled_redis.rb
58
+ - lib/redis/marshaled_redis.rb
59
+ - lib/redis/redis_factory.rb
60
+ - lib/redis_buddy.rb
61
+ - lib/redis_buddy/cache_store.rb
62
+ - README.md
63
+ has_rdoc: true
64
+ homepage: http://buddybrand.de
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options:
69
+ - --charset=UTF-8
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 0
85
+ version: "0"
86
+ requirements: []
87
+
88
+ rubyforge_project:
89
+ rubygems_version: 1.3.6
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: A namespaced Redis Cache Store for Rails 3
93
+ test_files:
94
+ - spec/spec_helper.rb
95
+ - spec/redis/distributed_marshaled_redis_spec.rb
96
+ - spec/redis/marshaled_redis_spec.rb
97
+ - spec/redis/redis_factory_spec.rb
98
+ - spec/cache/redis_buddy_store.rb