redis-store 1.0.0.beta2 → 1.0.0.beta3

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.

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)