redis-store 1.0.0.beta2 → 1.0.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of redis-store might be problematic. Click here for more details.
- data/CHANGELOG +74 -23
- data/Gemfile +12 -7
- data/Gemfile.lock +183 -0
- data/MIT-LICENSE +1 -1
- data/README.md +49 -14
- data/Rakefile +8 -4
- data/VERSION +1 -1
- data/lib/{rack/session/rails.rb → action_controller/session/redis_session_store.rb} +24 -20
- data/lib/{cache/rails → active_support/cache}/redis_store.rb +64 -22
- data/lib/cache/merb/redis_store.rb +20 -8
- data/lib/cache/sinatra/redis_store.rb +20 -8
- data/lib/i18n/backend/redis.rb +67 -0
- data/lib/rack/cache/redis_metastore.rb +4 -4
- data/lib/rack/session/redis.rb +7 -7
- data/lib/redis-store.rb +16 -14
- data/lib/redis/distributed_store.rb +35 -0
- data/lib/redis/factory.rb +29 -10
- data/lib/redis/store.rb +30 -0
- data/lib/redis/store/interface.rb +17 -0
- data/lib/redis/store/marshalling.rb +41 -0
- data/lib/redis/store/namespace.rb +54 -0
- data/lib/redis/store/ttl.rb +37 -0
- data/lib/redis/store/version.rb +12 -0
- data/redis-store.gemspec +32 -20
- data/spec/action_controller/session/redis_session_store_spec.rb +121 -0
- data/spec/{cache/rails → active_support/cache}/redis_store_spec.rb +93 -19
- data/spec/cache/merb/redis_store_spec.rb +14 -11
- data/spec/cache/sinatra/redis_store_spec.rb +14 -11
- data/spec/config/master.conf +1 -1
- data/spec/config/single.conf +1 -1
- data/spec/config/slave.conf +1 -1
- data/spec/i18n/backend/redis_spec.rb +56 -0
- data/spec/rack/cache/entitystore/redis_spec.rb +10 -8
- data/spec/rack/cache/metastore/redis_spec.rb +2 -2
- data/spec/rack/session/redis_spec.rb +6 -6
- data/spec/redis/distributed_store_spec.rb +47 -0
- data/spec/redis/factory_spec.rb +58 -16
- data/spec/redis/store/interface_spec.rb +23 -0
- data/spec/redis/store/marshalling_spec.rb +83 -0
- data/spec/redis/store/namespace_spec.rb +76 -0
- data/spec/redis/store/version_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -5
- data/tasks/redis.tasks.rb +19 -12
- metadata +33 -21
- data/lib/redis/distributed_marshaled.rb +0 -28
- data/lib/redis/marshaled_client.rb +0 -65
- data/lib/redis_store/version.rb +0 -10
- data/spec/rack/session/redis_session_store_spec.rb +0 -75
- data/spec/redis/distributed_marshaled_redis_spec.rb +0 -33
- data/spec/redis/marshaled_client_spec.rb +0 -83
- data/spec/redis_store/version_spec.rb +0 -7
data/Rakefile
CHANGED
@@ -11,8 +11,8 @@ begin
|
|
11
11
|
require "jeweler"
|
12
12
|
Jeweler::Tasks.new do |gemspec|
|
13
13
|
gemspec.name = "#{ENV["GEM_PREFIX"]}redis-store"
|
14
|
-
gemspec.summary = "Rack::Session, Rack::Cache and cache Redis stores for Ruby web frameworks."
|
15
|
-
gemspec.description = "Rack::Session, Rack::Cache and cache Redis stores for Ruby web frameworks."
|
14
|
+
gemspec.summary = "Namespaced Rack::Session, Rack::Cache, I18n and cache Redis stores for Ruby web frameworks."
|
15
|
+
gemspec.description = "Namespaced Rack::Session, Rack::Cache, I18n and cache Redis stores for Ruby web frameworks."
|
16
16
|
gemspec.email = "guidi.luca@gmail.com"
|
17
17
|
gemspec.homepage = "http://github.com/jodosha/redis-store"
|
18
18
|
gemspec.authors = [ "Luca Guidi" ]
|
@@ -27,7 +27,7 @@ end
|
|
27
27
|
|
28
28
|
namespace :spec do
|
29
29
|
desc "Run all the examples by starting a detached Redis instance"
|
30
|
-
task :suite do
|
30
|
+
task :suite => :prepare do
|
31
31
|
invoke_with_redis_cluster "spec:run"
|
32
32
|
end
|
33
33
|
|
@@ -38,7 +38,7 @@ namespace :spec do
|
|
38
38
|
end
|
39
39
|
|
40
40
|
desc "Run all examples with RCov"
|
41
|
-
task :rcov do
|
41
|
+
task :rcov => :prepare do
|
42
42
|
invoke_with_redis_cluster "rcov_run"
|
43
43
|
end
|
44
44
|
|
@@ -47,6 +47,10 @@ Spec::Rake::SpecTask.new(:rcov_run) do |t|
|
|
47
47
|
t.rcov = true
|
48
48
|
end
|
49
49
|
|
50
|
+
task :prepare do
|
51
|
+
`mkdir -p tmp && rm tmp/*.rdb`
|
52
|
+
end
|
53
|
+
|
50
54
|
namespace :bundle do
|
51
55
|
task :clean do
|
52
56
|
system "rm -rf ~/.bundle/ ~/.gem/ .bundle/ Gemfile.lock"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.0.
|
1
|
+
1.0.0.beta3
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "redis-store"
|
2
|
+
|
1
3
|
module RedisStore
|
2
4
|
module Rack
|
3
5
|
module Session
|
@@ -19,10 +21,8 @@ module RedisStore
|
|
19
21
|
|
20
22
|
super
|
21
23
|
|
22
|
-
@options = { :key_prefix => "" }.update(options)
|
23
24
|
servers = [options[:servers]].flatten.compact.map do |server_options|
|
24
25
|
{
|
25
|
-
:namespace => 'rack:session',
|
26
26
|
:host => 'localhost',
|
27
27
|
:port => '6379',
|
28
28
|
:db => 0
|
@@ -33,33 +33,37 @@ module RedisStore
|
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
def get_session(env, sid)
|
37
|
+
sid ||= generate_sid
|
38
|
+
begin
|
39
|
+
session = @pool.get(sid) || {}
|
40
|
+
rescue Errno::ECONNREFUSED
|
41
|
+
session = {}
|
42
|
+
end
|
43
|
+
[sid, session]
|
44
|
+
end
|
39
45
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
46
|
+
def set_session(env, sid, session_data)
|
47
|
+
options = env['rack.session.options']
|
48
|
+
@pool.set(sid, session_data, options)
|
49
|
+
return true
|
44
50
|
rescue Errno::ECONNREFUSED
|
45
|
-
|
51
|
+
return false
|
46
52
|
end
|
47
|
-
[sid, session]
|
48
|
-
end
|
49
53
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
def destroy(env)
|
55
|
+
if sid = current_session_id(env)
|
56
|
+
@pool.del(sid)
|
57
|
+
end
|
58
|
+
rescue Errno::ECONNREFUSED
|
59
|
+
false
|
60
|
+
end
|
57
61
|
end
|
58
62
|
end
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
62
|
-
if ::
|
66
|
+
if ::Redis::Store.rails3?
|
63
67
|
class ActionDispatch::Session::RedisSessionStore < ActionDispatch::Session::AbstractStore
|
64
68
|
include RedisStore::Rack::Session::Rails
|
65
69
|
end
|
@@ -1,15 +1,17 @@
|
|
1
|
+
require "redis-store"
|
2
|
+
|
1
3
|
module ::RedisStore
|
2
4
|
module Cache
|
3
5
|
module Rails2
|
4
6
|
def write(key, value, options = nil)
|
5
7
|
super
|
6
|
-
method = options && options[:unless_exist] ? :
|
8
|
+
method = options && options[:unless_exist] ? :setnx : :set
|
7
9
|
@data.send method, key, value, options
|
8
10
|
end
|
9
11
|
|
10
12
|
def read(key, options = nil)
|
11
13
|
super
|
12
|
-
@data.
|
14
|
+
@data.get key, options
|
13
15
|
end
|
14
16
|
|
15
17
|
def delete(key, options = nil)
|
@@ -22,6 +24,16 @@ module ::RedisStore
|
|
22
24
|
@data.exists key
|
23
25
|
end
|
24
26
|
|
27
|
+
# Delete objects for matched keys.
|
28
|
+
#
|
29
|
+
# Example:
|
30
|
+
# cache.del_matched "rab*"
|
31
|
+
def delete_matched(matcher, options = nil)
|
32
|
+
instrument(:delete_matched, matcher, options) do
|
33
|
+
@data.keys(matcher).each { |key| @data.del key }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
25
37
|
private
|
26
38
|
def instrument(operation, key, options = nil)
|
27
39
|
log(operation.to_s, key, options)
|
@@ -30,14 +42,26 @@ module ::RedisStore
|
|
30
42
|
end
|
31
43
|
|
32
44
|
module Rails3
|
45
|
+
# Delete objects for matched keys.
|
46
|
+
#
|
47
|
+
# Example:
|
48
|
+
# cache.del_matched "rab*"
|
49
|
+
def delete_matched(matcher, options = nil)
|
50
|
+
options = merged_options(options)
|
51
|
+
instrument(:delete_matched, matcher.inspect) do
|
52
|
+
matcher = key_matcher(matcher, options)
|
53
|
+
@data.keys(matcher).each { |key| delete_entry(key, options) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
33
57
|
protected
|
34
58
|
def write_entry(key, entry, options)
|
35
|
-
method = options && options[:unless_exist] ? :
|
59
|
+
method = options && options[:unless_exist] ? :setnx : :set
|
36
60
|
@data.send method, key, entry, options
|
37
61
|
end
|
38
62
|
|
39
63
|
def read_entry(key, options)
|
40
|
-
entry = @data.
|
64
|
+
entry = @data.get key, options
|
41
65
|
if entry
|
42
66
|
entry.is_a?(ActiveSupport::Cache::Entry) ? entry : ActiveSupport::Cache::Entry.new(entry)
|
43
67
|
end
|
@@ -46,10 +70,25 @@ module ::RedisStore
|
|
46
70
|
def delete_entry(key, options)
|
47
71
|
@data.del key
|
48
72
|
end
|
73
|
+
|
74
|
+
# Add the namespace defined in the options to a pattern designed to match keys.
|
75
|
+
#
|
76
|
+
# This implementation is __different__ than ActiveSupport:
|
77
|
+
# __it doesn't accept Regular expressions__, because the Redis matcher is designed
|
78
|
+
# only for strings with wildcards.
|
79
|
+
def key_matcher(pattern, options)
|
80
|
+
prefix = options[:namespace].is_a?(Proc) ? options[:namespace].call : options[:namespace]
|
81
|
+
if prefix
|
82
|
+
raise "Regexps aren't supported, please use string with wildcards." if pattern.is_a?(Regexp)
|
83
|
+
"#{prefix}:#{pattern}"
|
84
|
+
else
|
85
|
+
pattern
|
86
|
+
end
|
87
|
+
end
|
49
88
|
end
|
50
89
|
|
51
90
|
module Store
|
52
|
-
include ::
|
91
|
+
include ::Redis::Store.rails3? ? Rails3 : Rails2
|
53
92
|
end
|
54
93
|
end
|
55
94
|
end
|
@@ -62,23 +101,26 @@ module ActiveSupport
|
|
62
101
|
# Instantiate the store.
|
63
102
|
#
|
64
103
|
# Example:
|
65
|
-
# RedisStore.new
|
66
|
-
#
|
67
|
-
# RedisStore.new "example.com:23682" # => host: example.com, port: 23682, db: 0
|
68
|
-
# RedisStore.new "example.com:23682/1" # => host: example.com, port: 23682, db: 1
|
69
|
-
# RedisStore.new "localhost:6379/0", "localhost:6380/0" # => instantiate a cluster
|
70
|
-
def initialize(*addresses)
|
71
|
-
@data = Redis::Factory.create(addresses)
|
72
|
-
end
|
73
|
-
|
74
|
-
# Delete objects for matched keys.
|
104
|
+
# RedisStore.new
|
105
|
+
# # => host: localhost, port: 6379, db: 0
|
75
106
|
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
107
|
+
# RedisStore.new "example.com"
|
108
|
+
# # => host: example.com, port: 6379, db: 0
|
109
|
+
#
|
110
|
+
# RedisStore.new "example.com:23682"
|
111
|
+
# # => host: example.com, port: 23682, db: 0
|
112
|
+
#
|
113
|
+
# RedisStore.new "example.com:23682/1"
|
114
|
+
# # => host: example.com, port: 23682, db: 1
|
115
|
+
#
|
116
|
+
# RedisStore.new "example.com:23682/1/theplaylist"
|
117
|
+
# # => host: example.com, port: 23682, db: 1, namespace: theplaylist
|
118
|
+
#
|
119
|
+
# RedisStore.new "localhost:6379/0", "localhost:6380/0"
|
120
|
+
# # => instantiate a cluster
|
121
|
+
def initialize(*addresses)
|
122
|
+
@data = ::Redis::Factory.create(addresses)
|
123
|
+
super(addresses.extract_options!)
|
82
124
|
end
|
83
125
|
|
84
126
|
# Reads multiple keys from the cache using a single call to the
|
@@ -88,7 +130,7 @@ module ActiveSupport
|
|
88
130
|
# cache.read_multi "rabbit", "white-rabbit"
|
89
131
|
# cache.read_multi "rabbit", "white-rabbit", :raw => true
|
90
132
|
def read_multi(*names)
|
91
|
-
@data.
|
133
|
+
@data.mget *names
|
92
134
|
end
|
93
135
|
|
94
136
|
# Increment a key in the store.
|
@@ -4,12 +4,24 @@ module Merb
|
|
4
4
|
# Instantiate the store.
|
5
5
|
#
|
6
6
|
# Example:
|
7
|
-
# RedisStore.new
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# RedisStore.new :servers => ["example.com
|
11
|
-
#
|
12
|
-
|
7
|
+
# RedisStore.new
|
8
|
+
# # => host: localhost, port: 6379, db: 0
|
9
|
+
#
|
10
|
+
# RedisStore.new :servers => ["example.com"]
|
11
|
+
# # => host: example.com, port: 6379, db: 0
|
12
|
+
#
|
13
|
+
# RedisStore.new :servers => ["example.com:23682"]
|
14
|
+
# # => host: example.com, port: 23682, db: 0
|
15
|
+
#
|
16
|
+
# RedisStore.new :servers => ["example.com:23682/1"]
|
17
|
+
# # => host: example.com, port: 23682, db: 1
|
18
|
+
#
|
19
|
+
# RedisStore.new :servers => ["example.com:23682/1/theplaylist"]
|
20
|
+
# # => host: example.com, port: 23682, db: 1, namespace: theplaylist
|
21
|
+
#
|
22
|
+
# RedisStore.new :servers => ["localhost:6379/0", "localhost:6380/0"]
|
23
|
+
# # => instantiate a cluster
|
24
|
+
def initialize(config = { })
|
13
25
|
@data = Redis::Factory.create config[:servers]
|
14
26
|
end
|
15
27
|
|
@@ -18,12 +30,12 @@ module Merb
|
|
18
30
|
end
|
19
31
|
|
20
32
|
def read(key, parameters = {}, conditions = {})
|
21
|
-
@data.
|
33
|
+
@data.get normalize(key, parameters), conditions
|
22
34
|
end
|
23
35
|
|
24
36
|
def write(key, data = nil, parameters = {}, conditions = {})
|
25
37
|
if writable?(key, parameters, conditions)
|
26
|
-
method = conditions && conditions[:unless_exist] ? :
|
38
|
+
method = conditions && conditions[:unless_exist] ? :setnx : :set
|
27
39
|
@data.send method, normalize(key, parameters), data, conditions
|
28
40
|
end
|
29
41
|
end
|
@@ -10,25 +10,37 @@ module Sinatra
|
|
10
10
|
# Instantiate the store.
|
11
11
|
#
|
12
12
|
# Example:
|
13
|
-
# RedisStore.new
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# RedisStore.new "example.com
|
17
|
-
#
|
13
|
+
# RedisStore.new
|
14
|
+
# # => host: localhost, port: 6379, db: 0
|
15
|
+
#
|
16
|
+
# RedisStore.new "example.com"
|
17
|
+
# # => host: example.com, port: 6379, db: 0
|
18
|
+
#
|
19
|
+
# RedisStore.new "example.com:23682"
|
20
|
+
# # => host: example.com, port: 23682, db: 0
|
21
|
+
#
|
22
|
+
# RedisStore.new "example.com:23682/1"
|
23
|
+
# # => host: example.com, port: 23682, db: 1
|
24
|
+
#
|
25
|
+
# RedisStore.new "example.com:23682/1/theplaylist"
|
26
|
+
# # => host: example.com, port: 23682, db: 1, namespace: theplaylist
|
27
|
+
#
|
28
|
+
# RedisStore.new "localhost:6379/0", "localhost:6380/0"
|
29
|
+
# # => instantiate a cluster
|
18
30
|
def initialize(*addresses)
|
19
31
|
@data = Redis::Factory.create addresses
|
20
32
|
end
|
21
33
|
|
22
34
|
def write(key, value, options = nil)
|
23
35
|
if options && options[:unless_exist]
|
24
|
-
@data.
|
36
|
+
@data.setnx key, value, options
|
25
37
|
else
|
26
|
-
@data.
|
38
|
+
@data.set key, value, options
|
27
39
|
end
|
28
40
|
end
|
29
41
|
|
30
42
|
def read(key, options = nil)
|
31
|
-
@data.
|
43
|
+
@data.get(key, options)
|
32
44
|
end
|
33
45
|
|
34
46
|
def delete(key, options = nil)
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module I18n
|
2
|
+
module Backend
|
3
|
+
class Redis
|
4
|
+
include Base, Flatten
|
5
|
+
attr_accessor :store
|
6
|
+
|
7
|
+
# Instantiate the store.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
# RedisStore.new
|
11
|
+
# # => host: localhost, port: 6379, db: 0
|
12
|
+
#
|
13
|
+
# RedisStore.new "example.com"
|
14
|
+
# # => host: example.com, port: 6379, db: 0
|
15
|
+
#
|
16
|
+
# RedisStore.new "example.com:23682"
|
17
|
+
# # => host: example.com, port: 23682, db: 0
|
18
|
+
#
|
19
|
+
# RedisStore.new "example.com:23682/1"
|
20
|
+
# # => host: example.com, port: 23682, db: 1
|
21
|
+
#
|
22
|
+
# RedisStore.new "example.com:23682/1/theplaylist"
|
23
|
+
# # => host: example.com, port: 23682, db: 1, namespace: theplaylist
|
24
|
+
#
|
25
|
+
# RedisStore.new "localhost:6379/0", "localhost:6380/0"
|
26
|
+
# # => instantiate a cluster
|
27
|
+
def initialize(*addresses)
|
28
|
+
@store = ::Redis::Factory.create(addresses)
|
29
|
+
end
|
30
|
+
|
31
|
+
def translate(locale, key, options = {})
|
32
|
+
options[:resolve] ||= false
|
33
|
+
super locale, key, options
|
34
|
+
end
|
35
|
+
|
36
|
+
def store_translations(locale, data, options = {})
|
37
|
+
escape = options.fetch(:escape, true)
|
38
|
+
flatten_translations(locale, data, escape, false).each do |key, value|
|
39
|
+
case value
|
40
|
+
when Proc
|
41
|
+
raise "Key-value stores cannot handle procs"
|
42
|
+
else
|
43
|
+
@store.set "#{locale}.#{key}", value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def available_locales
|
49
|
+
locales = @store.keys.map { |k| k =~ /\./; $` }
|
50
|
+
locales.uniq!
|
51
|
+
locales.compact!
|
52
|
+
locales.map! { |k| k.to_sym }
|
53
|
+
locales
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
def lookup(locale, key, scope = [], options = {})
|
58
|
+
key = normalize_flat_keys(locale, key, scope, options[:separator])
|
59
|
+
@store.get "#{locale}.#{key}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def resolve_link(locale, key)
|
63
|
+
key
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -4,7 +4,7 @@ module Rack
|
|
4
4
|
class RedisBase < MetaStore
|
5
5
|
extend Rack::Utils
|
6
6
|
|
7
|
-
# The Redis::
|
7
|
+
# The Redis::Store object used to communicate with the Redis daemon.
|
8
8
|
attr_reader :cache
|
9
9
|
|
10
10
|
def self.resolve(uri)
|
@@ -17,17 +17,17 @@ module Rack
|
|
17
17
|
|
18
18
|
class Redis < RedisBase
|
19
19
|
def initialize(server, options = {})
|
20
|
-
@cache = ::Redis::
|
20
|
+
@cache = ::Redis::Factory.create server
|
21
21
|
end
|
22
22
|
|
23
23
|
def read(key)
|
24
24
|
key = hexdigest(key)
|
25
|
-
cache.
|
25
|
+
cache.get(key) || []
|
26
26
|
end
|
27
27
|
|
28
28
|
def write(key, entries)
|
29
29
|
key = hexdigest(key)
|
30
|
-
cache.
|
30
|
+
cache.set(key, entries)
|
31
31
|
end
|
32
32
|
|
33
33
|
def purge(key)
|