jodosha-redis-store 0.0.3 → 0.1.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.
@@ -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