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.

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
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.beta2
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
- def prefixed(sid)
37
- "#{@options[:key_prefix]}#{sid}"
38
- end
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
- def get_session(env, sid)
41
- sid ||= generate_sid
42
- begin
43
- session = @pool.marshalled_get(prefixed(sid)) || {}
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
- session = {}
51
+ return false
46
52
  end
47
- [sid, session]
48
- end
49
53
 
50
- def set_session(env, sid, session_data)
51
- options = env['rack.session.options']
52
- @pool.marshalled_set(prefixed(sid), session_data, options)
53
- return true
54
- rescue Errno::ECONNREFUSED
55
- return false
56
- end
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 ::RedisStore.rails3?
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] ? :marshalled_setnx : :marshalled_set
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.marshalled_get key, options
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] ? :marshalled_setnx : :marshalled_set
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.marshalled_get key, options
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 ::RedisStore.rails3? ? Rails3 : Rails2
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 # => host: localhost, port: 6379, db: 0
66
- # RedisStore.new "example.com" # => host: example.com, port: 6379, db: 0
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
- # Example:
77
- # cache.del_matched "rab*"
78
- def delete_matched(matcher, options = nil)
79
- instrument(:delete_matched, matcher, options) do
80
- @data.keys(matcher).each { |key| @data.del key }
81
- end
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.marshalled_mget *names
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 # => host: localhost, port: 6379, db: 0
8
- # RedisStore.new :servers => ["example.com"] # => host: example.com, port: 6379, db: 0
9
- # RedisStore.new :servers => ["example.com:23682"] # => host: example.com, port: 23682, db: 0
10
- # RedisStore.new :servers => ["example.com:23682/1"] # => host: example.com, port: 23682, db: 1
11
- # RedisStore.new :servers => ["localhost:6379/0", "localhost:6380/0"] # => instantiate a cluster
12
- def initialize(config = {})
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.marshalled_get normalize(key, parameters), conditions
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] ? :marshalled_setnx : :marshalled_set
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 # => 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
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.marshalled_setnx key, value, options
36
+ @data.setnx key, value, options
25
37
  else
26
- @data.marshalled_set key, value, options
38
+ @data.set key, value, options
27
39
  end
28
40
  end
29
41
 
30
42
  def read(key, options = nil)
31
- @data.marshalled_get(key, options)
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::MarshaledClient object used to communicate with the Redis daemon.
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::MarshaledClient.new server
20
+ @cache = ::Redis::Factory.create server
21
21
  end
22
22
 
23
23
  def read(key)
24
24
  key = hexdigest(key)
25
- cache.marshalled_get(key) || []
25
+ cache.get(key) || []
26
26
  end
27
27
 
28
28
  def write(key, entries)
29
29
  key = hexdigest(key)
30
- cache.marshalled_set(key, entries)
30
+ cache.set(key, entries)
31
31
  end
32
32
 
33
33
  def purge(key)