jodosha-redis-store 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -24,13 +24,27 @@ In your configuration files:
24
24
 
25
25
  h2. How to use with Merb
26
26
 
27
- dependency "redis-store", "0.0.3"
27
+ dependency "jodosha-redis-store", "0.1.0"
28
28
  dependency("merb-cache", merb_gems_version) do
29
29
  Merb::Cache.setup do
30
30
  register(:redis, Merb::Cache::RedisStore, :servers => ["127.0.0.1:6379"])
31
31
  end
32
32
  end
33
33
 
34
+ h2. How to use with Sinatra
35
+
36
+ require 'rubygems'
37
+ require 'sinatra'
38
+ require 'jodosha-redis-store'
39
+
40
+ class MyApp < Sinatra::Base
41
+ register Sinatra::Cache
42
+
43
+ get '/hi' do
44
+ cache.fetch("greet") { "Hello, World!" }
45
+ end
46
+ end
47
+
34
48
  h2. Copyright
35
49
 
36
50
  (c) 2009 Luca Guidi - 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.0.3"
8
+ REDIS_STORE_VERSION = "0.1.0"
9
9
 
10
10
  task :default => :spec
11
11
 
@@ -0,0 +1,131 @@
1
+ module Sinatra
2
+ module Cache
3
+ class << self
4
+ def register(app)
5
+ app.set :cache, RedisStore.new
6
+ end
7
+ end
8
+
9
+ class RedisStore
10
+ # Instantiate the store.
11
+ #
12
+ # Example:
13
+ # RedisStore.new # => host: localhost, port: 6379, db: 0
14
+ # RedisStore.new "example.com" # => host: example.com, port: 6379, db: 0
15
+ # RedisStore.new "example.com:23682" # => host: example.com, port: 23682, db: 0
16
+ # RedisStore.new "example.com:23682/1" # => host: example.com, port: 23682, db: 1
17
+ # RedisStore.new "localhost:6379/0", "localhost:6380/0" # => instantiate a cluster
18
+ def initialize(*addresses)
19
+ addresses = extract_addresses(addresses)
20
+ @data = if addresses.size > 1
21
+ DistributedMarshaledRedis.new addresses
22
+ else
23
+ MarshaledRedis.new addresses.first || {}
24
+ end
25
+ end
26
+
27
+ def write(key, value, options = nil)
28
+ method = options && options[:unless_exist] ? :set_unless_exists : :set
29
+ @data.send method, key, value, options
30
+ end
31
+
32
+ def read(key, options = nil)
33
+ @data.get key, options
34
+ end
35
+
36
+ def delete(key, options = nil)
37
+ @data.delete key
38
+ end
39
+
40
+ def exist?(key, options = nil)
41
+ @data.key? key
42
+ end
43
+
44
+ # Increment a key in the store.
45
+ #
46
+ # If the key doesn't exist it will be initialized on 0.
47
+ # If the key exist but it isn't a Fixnum it will be initialized on 0.
48
+ #
49
+ # Example:
50
+ # We have two objects in cache:
51
+ # counter # => 23
52
+ # rabbit # => #<Rabbit:0x5eee6c>
53
+ #
54
+ # cache.increment "counter"
55
+ # cache.read "counter", :raw => true # => "24"
56
+ #
57
+ # cache.increment "counter", 6
58
+ # cache.read "counter", :raw => true # => "30"
59
+ #
60
+ # cache.increment "a counter"
61
+ # cache.read "a counter", :raw => true # => "1"
62
+ #
63
+ # cache.increment "rabbit"
64
+ # cache.read "rabbit", :raw => true # => "1"
65
+ def increment(key, amount = 1)
66
+ @data.incr key, amount
67
+ end
68
+
69
+ # Decrement a key in the store
70
+ #
71
+ # If the key doesn't exist it will be initialized on 0.
72
+ # If the key exist but it isn't a Fixnum it will be initialized on 0.
73
+ #
74
+ # Example:
75
+ # We have two objects in cache:
76
+ # counter # => 23
77
+ # rabbit # => #<Rabbit:0x5eee6c>
78
+ #
79
+ # cache.decrement "counter"
80
+ # cache.read "counter", :raw => true # => "22"
81
+ #
82
+ # cache.decrement "counter", 2
83
+ # cache.read "counter", :raw => true # => "20"
84
+ #
85
+ # cache.decrement "a counter"
86
+ # cache.read "a counter", :raw => true # => "-1"
87
+ #
88
+ # cache.decrement "rabbit"
89
+ # cache.read "rabbit", :raw => true # => "-1"
90
+ def decrement(key, amount = 1)
91
+ @data.decr key, amount
92
+ end
93
+
94
+ # Delete objects for matched keys.
95
+ #
96
+ # Example:
97
+ # cache.delete_matched "rab*"
98
+ def delete_matched(matcher, options = nil)
99
+ @data.keys(matcher).each { |key| @data.delete key }
100
+ end
101
+
102
+ def fetch(key, options = {})
103
+ (!options[:force] && data = read(key, options)) || (write key, yield, options if block_given?)
104
+ end
105
+
106
+ # Clear all the data from the store.
107
+ def clear
108
+ @data.flush_db
109
+ end
110
+
111
+ def stats
112
+ @data.info
113
+ end
114
+
115
+ private
116
+ def extract_addresses(addresses) # TODO extract in a module or a class
117
+ addresses = addresses.flatten.compact
118
+ addresses.inject([]) do |result, address|
119
+ host, port = address.split /\:/
120
+ port, db = port.split /\// if port
121
+ address = {}
122
+ address[:host] = host if host
123
+ address[:port] = port if port
124
+ address[:db] = db.to_i if db
125
+ result << address
126
+ result
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -3,7 +3,9 @@ require "dist_redis"
3
3
  require "redis/marshaled_redis"
4
4
  require "redis/distributed_marshaled_redis"
5
5
 
6
- if defined?(Merb)
6
+ if defined?(Sinatra)
7
+ require "cache/sinatra/redis_store"
8
+ elsif defined?(Merb)
7
9
  # HACK for cyclic dependency: redis-store is required before merb-cache
8
10
  module Merb; module Cache; class AbstractStore; end end end
9
11
  require "cache/merb/redis_store"
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "redis-store"
3
- s.version = "0.0.3"
3
+ s.version = "0.1.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/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/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/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/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"]
13
13
  s.extra_rdoc_files = ["README.textile"]
14
14
  end
@@ -11,6 +11,7 @@ module ActiveSupport
11
11
  with_store_management do |store|
12
12
  store.write "rabbit", @rabbit
13
13
  store.delete "counter"
14
+ store.delete "rub-a-dub"
14
15
  end
15
16
  end
16
17
 
@@ -0,0 +1,192 @@
1
+ require File.join(File.dirname(__FILE__), "/../../spec_helper")
2
+
3
+ class App
4
+ def initialize
5
+ @values = {}
6
+ end
7
+
8
+ def set(key, value)
9
+ @values[key] = value
10
+ end
11
+
12
+ def get(key)
13
+ @values[key]
14
+ end
15
+ end
16
+
17
+ module Sinatra
18
+ module Cache
19
+ describe "RedisStore" do
20
+ before(:each) do
21
+ @store = RedisStore.new
22
+ @dstore = RedisStore.new "localhost:6380/1", "localhost:6381/1"
23
+ @rabbit = OpenStruct.new :name => "bunny"
24
+ @white_rabbit = OpenStruct.new :color => "white"
25
+ with_store_management do |store|
26
+ store.write "rabbit", @rabbit
27
+ store.delete "counter"
28
+ store.delete "rub-a-dub"
29
+ end
30
+ end
31
+
32
+ it "should register as extension" do
33
+ app = App.new
34
+ Sinatra::Cache.register(app)
35
+ store = app.get(:cache)
36
+ store.should be_kind_of(RedisStore)
37
+ end
38
+
39
+ it "should accept connection params" do
40
+ redis = instantiate_store
41
+ redis.instance_variable_get(:@db).should == 0
42
+ redis.host.should == "localhost"
43
+ redis.port.should == "6379"
44
+
45
+ redis = instantiate_store "redis.com"
46
+ redis.host.should == "redis.com"
47
+
48
+ redis = instantiate_store "redis.com:6380"
49
+ redis.host.should == "redis.com"
50
+ redis.port.should == "6380"
51
+
52
+ redis = instantiate_store "redis.com:6380/23"
53
+ redis.instance_variable_get(:@db).should == 23
54
+ redis.host.should == "redis.com"
55
+ redis.port.should == "6380"
56
+ end
57
+
58
+ it "should instantiate a ring" do
59
+ store = instantiate_store
60
+ store.should be_kind_of(MarshaledRedis)
61
+ store = instantiate_store ["localhost:6379/0", "localhost:6379/1"]
62
+ store.should be_kind_of(DistributedMarshaledRedis)
63
+ end
64
+
65
+ it "should read the data" do
66
+ with_store_management do |store|
67
+ store.read("rabbit").should === @rabbit
68
+ end
69
+ end
70
+
71
+ it "should write the data" do
72
+ with_store_management do |store|
73
+ store.write "rabbit", @white_rabbit
74
+ store.read("rabbit").should === @white_rabbit
75
+ end
76
+ end
77
+
78
+ # it "should write the data with expiration time" do
79
+ # @store.write "rabbit", @white_rabbit, :expires_in => 1.second
80
+ # @store.read("rabbit").should === @white_rabbit ; sleep 2
81
+ # @store.read("rabbit").should be_nil
82
+ # end
83
+
84
+ it "should not write data if :unless_exist option is true" do
85
+ with_store_management do |store|
86
+ store.write "rabbit", @white_rabbit, :unless_exist => true
87
+ store.read("rabbit").should === @rabbit
88
+ end
89
+ end
90
+
91
+ it "should read raw data" do
92
+ with_store_management do |store|
93
+ store.read("rabbit", :raw => true).should == "\004\bU:\017OpenStruct{\006:\tname\"\nbunny"
94
+ end
95
+ end
96
+
97
+ it "should write raw data" do
98
+ with_store_management do |store|
99
+ store.write "rabbit", @white_rabbit, :raw => true
100
+ store.read("rabbit", :raw => true).should == %(#<OpenStruct color="white">)
101
+ end
102
+ end
103
+
104
+ it "should delete data" do
105
+ with_store_management do |store|
106
+ store.delete "rabbit"
107
+ store.read("rabbit").should be_nil
108
+ end
109
+ end
110
+
111
+ it "should delete matched data" do
112
+ with_store_management do |store|
113
+ store.delete_matched "rabb*"
114
+ store.read("rabbit").should be_nil
115
+ end
116
+ end
117
+
118
+ it "should verify existence of an object in the store" do
119
+ with_store_management do |store|
120
+ store.exist?("rabbit").should be_true
121
+ store.exist?("rab-a-dub").should be_false
122
+ end
123
+ end
124
+
125
+ it "should increment a key" do
126
+ with_store_management do |store|
127
+ 3.times { store.increment "counter" }
128
+ store.read("counter", :raw => true).to_i.should == 3
129
+ end
130
+ end
131
+
132
+ it "should decrement a key" do
133
+ with_store_management do |store|
134
+ 3.times { store.increment "counter" }
135
+ 2.times { store.decrement "counter" }
136
+ store.read("counter", :raw => true).to_i.should == 1
137
+ end
138
+ end
139
+
140
+ it "should increment a key by given value" do
141
+ with_store_management do |store|
142
+ store.increment "counter", 3
143
+ store.read("counter", :raw => true).to_i.should == 3
144
+ end
145
+ end
146
+
147
+ it "should decrement a key by given value" do
148
+ with_store_management do |store|
149
+ 3.times { store.increment "counter" }
150
+ store.decrement "counter", 2
151
+ store.read("counter", :raw => true).to_i.should == 1
152
+ end
153
+ end
154
+
155
+ it "should clear the store" do
156
+ with_store_management do |store|
157
+ store.clear
158
+ store.instance_variable_get(:@data).keys("*").should be_empty
159
+ end
160
+ end
161
+
162
+ it "should return store stats" do
163
+ with_store_management do |store|
164
+ store.stats.should_not be_empty
165
+ end
166
+ end
167
+
168
+ it "should fetch data" do
169
+ with_store_management do |store|
170
+ store.fetch("rabbit").should == @rabbit
171
+ store.fetch("rub-a-dub").should be_nil
172
+ store.fetch("rub-a-dub") { "Flora de Cana" }
173
+ store.fetch("rub-a-dub").should === "Flora de Cana"
174
+ store.fetch("rabbit", :force => true).should be_nil # force cache miss
175
+ # store.fetch("rabbit", :force => true, :expires_in => 1.second) { @white_rabbit }
176
+ # store.fetch("rabbit").should === @white_rabbit ; sleep 2
177
+ # store.fetch("rabbit").should be_nil
178
+ end
179
+ end
180
+
181
+ private
182
+ def instantiate_store(addresses = nil)
183
+ RedisStore.new(addresses).instance_variable_get(:@data)
184
+ end
185
+
186
+ def with_store_management
187
+ yield @store
188
+ yield @dstore
189
+ end
190
+ end
191
+ end
192
+ end
@@ -7,3 +7,4 @@ require "merb"
7
7
  require "redis-store"
8
8
  require "activesupport"
9
9
  require "cache/rails/redis_store"
10
+ require "cache/sinatra/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.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
@@ -27,12 +27,14 @@ files:
27
27
  - Rakefile
28
28
  - lib/cache/merb/redis_store.rb
29
29
  - lib/cache/rails/redis_store.rb
30
+ - lib/cache/sinatra/redis_store.rb
30
31
  - lib/redis-store.rb
31
32
  - lib/redis/distributed_marshaled_redis.rb
32
33
  - lib/redis/marshaled_redis.rb
33
34
  - redis-store.gemspec
34
35
  - spec/cache/merb/redis_store_spec.rb
35
36
  - spec/cache/rails/redis_store_spec.rb
37
+ - spec/cache/sinatra/redis_store_spec.rb
36
38
  - spec/config/master.conf
37
39
  - spec/config/single.conf
38
40
  - spec/config/slave.conf
@@ -68,5 +70,6 @@ summary: Redis cache and session stores for Ruby web frameworks
68
70
  test_files:
69
71
  - spec/cache/merb/redis_store_spec.rb
70
72
  - spec/cache/rails/redis_store_spec.rb
73
+ - spec/cache/sinatra/redis_store_spec.rb
71
74
  - spec/redis/distributed_marshaled_redis_spec.rb
72
75
  - spec/redis/marshaled_redis_spec.rb