redis-store-json 3.0.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.
Files changed (73) hide show
  1. data/.gitignore +15 -0
  2. data/.travis.yml +7 -0
  3. data/CHANGELOG +450 -0
  4. data/README.md +23 -0
  5. data/redis-actionpack-json/.gitignore +4 -0
  6. data/redis-actionpack-json/Gemfile +6 -0
  7. data/redis-actionpack-json/MIT-LICENSE +20 -0
  8. data/redis-actionpack-json/Rakefile +8 -0
  9. data/redis-actionpack-json/lib/action_dispatch/middleware/session/redis_store_json.rb +24 -0
  10. data/redis-actionpack-json/lib/redis-actionpack-json.rb +4 -0
  11. data/redis-actionpack-json/lib/redis/actionpack/version.rb +5 -0
  12. data/redis-actionpack-json/redis-actionpack-json.gemspec +32 -0
  13. data/redis-actionpack-json/test/dummy/.gitignore +1 -0
  14. data/redis-actionpack-json/test/dummy/Rakefile +7 -0
  15. data/redis-actionpack-json/test/dummy/app/controllers/test_controller.rb +37 -0
  16. data/redis-actionpack-json/test/dummy/config.ru +4 -0
  17. data/redis-actionpack-json/test/dummy/config/application.rb +29 -0
  18. data/redis-actionpack-json/test/dummy/config/boot.rb +10 -0
  19. data/redis-actionpack-json/test/dummy/config/environment.rb +5 -0
  20. data/redis-actionpack-json/test/dummy/config/initializers/secret_token.rb +7 -0
  21. data/redis-actionpack-json/test/dummy/config/initializers/session_store.rb +11 -0
  22. data/redis-actionpack-json/test/dummy/config/routes.rb +3 -0
  23. data/redis-actionpack-json/test/dummy/script/rails +6 -0
  24. data/redis-actionpack-json/test/fixtures/session_autoload_test/session_autoload_test/foo.rb +10 -0
  25. data/redis-actionpack-json/test/integration/redis_store_integration_test.rb +130 -0
  26. data/redis-actionpack-json/test/integration/redis_store_json_integration_test.rb +130 -0
  27. data/redis-actionpack-json/test/redis/actionpack/version_test.rb +7 -0
  28. data/redis-actionpack-json/test/test_helper.rb +23 -0
  29. data/redis-rack-json/.gitignore +5 -0
  30. data/redis-rack-json/Gemfile +5 -0
  31. data/redis-rack-json/MIT-LICENSE +20 -0
  32. data/redis-rack-json/Rakefile +8 -0
  33. data/redis-rack-json/lib/rack/session/redis.rb +69 -0
  34. data/redis-rack-json/lib/redis-rack-json.rb +3 -0
  35. data/redis-rack-json/lib/redis/rack/version.rb +6 -0
  36. data/redis-rack-json/redis-rack-json.gemspec +29 -0
  37. data/redis-rack-json/test/rack/session/redis_test.rb +289 -0
  38. data/redis-rack-json/test/redis/rack/version_test.rb +7 -0
  39. data/redis-rack-json/test/test_helper.rb +7 -0
  40. data/redis-store-json/Gemfile +4 -0
  41. data/redis-store-json/MIT-LICENSE +20 -0
  42. data/redis-store-json/Rakefile +7 -0
  43. data/redis-store-json/lib/redis-store-json.rb +11 -0
  44. data/redis-store-json/lib/redis/distributed_store.rb +46 -0
  45. data/redis-store-json/lib/redis/factory.rb +41 -0
  46. data/redis-store-json/lib/redis/store.rb +47 -0
  47. data/redis-store-json/lib/redis/store/interface.rb +21 -0
  48. data/redis-store-json/lib/redis/store/namespace.rb +66 -0
  49. data/redis-store-json/lib/redis/store/strategy.rb +60 -0
  50. data/redis-store-json/lib/redis/store/strategy/json.rb +49 -0
  51. data/redis-store-json/lib/redis/store/strategy/json_session.rb +67 -0
  52. data/redis-store-json/lib/redis/store/strategy/marshal.rb +16 -0
  53. data/redis-store-json/lib/redis/store/strategy/yaml.rb +16 -0
  54. data/redis-store-json/lib/redis/store/ttl.rb +37 -0
  55. data/redis-store-json/lib/redis/store/version.rb +5 -0
  56. data/redis-store-json/lib/tasks/redis.tasks.rb +167 -0
  57. data/redis-store-json/redis-store-json.gemspec +29 -0
  58. data/redis-store-json/test/config/node-one.conf +46 -0
  59. data/redis-store-json/test/config/node-two.conf +46 -0
  60. data/redis-store-json/test/config/redis.conf +46 -0
  61. data/redis-store-json/test/redis/distributed_store_test.rb +53 -0
  62. data/redis-store-json/test/redis/factory_test.rb +120 -0
  63. data/redis-store-json/test/redis/store/interface_test.rb +27 -0
  64. data/redis-store-json/test/redis/store/namespace_test.rb +103 -0
  65. data/redis-store-json/test/redis/store/strategy/json_session_test.rb +160 -0
  66. data/redis-store-json/test/redis/store/strategy/json_test.rb +108 -0
  67. data/redis-store-json/test/redis/store/strategy/marshal_test.rb +121 -0
  68. data/redis-store-json/test/redis/store/strategy/yaml_test.rb +105 -0
  69. data/redis-store-json/test/redis/store/ttl_test.rb +107 -0
  70. data/redis-store-json/test/redis/store/version_test.rb +7 -0
  71. data/redis-store-json/test/redis/store_test.rb +45 -0
  72. data/redis-store-json/test/test_helper.rb +22 -0
  73. metadata +215 -0
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ describe Redis::Rack::VERSION do
4
+ it "must be equal to 1.4.2" do
5
+ Redis::Rack::VERSION.must_equal '1.4.2'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ Bundler.setup
2
+ gem 'minitest'
3
+ require 'minitest/spec'
4
+ require 'minitest/autorun'
5
+ require 'mocha/setup'
6
+ require 'rack'
7
+ require 'rack/session/redis'
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
3
+
4
+ gem 'SystemTimer', :platform => :mri_18
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 - 2011 Luca Guidi
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+ require 'rake'
4
+ require 'bundler/gem_tasks'
5
+
6
+ load 'tasks/redis.tasks.rb'
7
+ task :default => 'redis:test:suite'
@@ -0,0 +1,11 @@
1
+ require 'redis'
2
+ require 'redis/store'
3
+ require 'redis/factory'
4
+ require 'redis/distributed_store'
5
+ require 'redis/store/namespace'
6
+ require 'redis/store/version'
7
+
8
+ class Redis
9
+ class Store < self
10
+ end
11
+ end
@@ -0,0 +1,46 @@
1
+ require 'redis/distributed'
2
+
3
+ class Redis
4
+ class DistributedStore < Distributed
5
+ @@timeout = 5
6
+ attr_reader :ring
7
+
8
+ def initialize(addresses, options = { })
9
+ nodes = addresses.map do |address|
10
+ ::Redis::Store.new _merge_options(address, options)
11
+ end
12
+ _extend_namespace options
13
+ @ring = Redis::HashRing.new nodes
14
+ end
15
+
16
+ def nodes
17
+ ring.nodes
18
+ end
19
+
20
+ def reconnect
21
+ nodes.each {|node| node.reconnect }
22
+ end
23
+
24
+ def set(key, value, options = nil)
25
+ node_for(key).set(key, value, options)
26
+ end
27
+
28
+ def get(key, options = nil)
29
+ node_for(key).get(key, options)
30
+ end
31
+
32
+ def setnx(key, value, options = nil)
33
+ node_for(key).setnx(key, value, options)
34
+ end
35
+
36
+ private
37
+ def _extend_namespace(options)
38
+ @namespace = options[:namespace]
39
+ extend ::Redis::Store::Namespace if @namespace
40
+ end
41
+
42
+ def _merge_options(address, options)
43
+ address.merge(:timeout => options[:timeout] || @@timeout)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,41 @@
1
+ require 'uri'
2
+
3
+ class Redis
4
+ class Factory
5
+ def self.create(*redis_client_options)
6
+ redis_client_options = redis_client_options.flatten.compact.inject([]) do |result, address|
7
+ result << resolve(address)
8
+ result
9
+ end
10
+ if redis_client_options.size > 1
11
+ ::Redis::DistributedStore.new redis_client_options
12
+ else
13
+ ::Redis::Store.new redis_client_options.first || {}
14
+ end
15
+ end
16
+
17
+ def self.resolve(uri) #:api: private
18
+ if uri.is_a?(Hash)
19
+ options = uri.dup
20
+ options[:namespace] ||= options.delete(:key_prefix) # RailsSessionStore
21
+ options
22
+ else
23
+ uri = URI.parse(uri)
24
+ _, db, namespace = if uri.path
25
+ uri.path.split /\//
26
+ end
27
+
28
+ options = {
29
+ :host => uri.host,
30
+ :port => uri.port || 6379,
31
+ :password => uri.password
32
+ }
33
+
34
+ options[:db] = db.to_i if db
35
+ options[:namespace] = namespace if namespace
36
+
37
+ options
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ require 'redis/store/ttl'
2
+ require 'redis/store/interface'
3
+ require 'redis/store/strategy'
4
+
5
+ class Redis
6
+ class Store < self
7
+ include Ttl, Interface
8
+
9
+ STRATEGIES = {
10
+ :marshal => Strategy::Marshal,
11
+ :json => Strategy::Json,
12
+ :json_session => Strategy::JsonSession,
13
+ :yaml => Strategy::Yaml,
14
+ }.freeze
15
+
16
+ def initialize(options = { })
17
+ super options.delete(:redis_server)
18
+
19
+ _extend_strategy options
20
+ _extend_namespace options
21
+ end
22
+
23
+ def reconnect
24
+ @client.reconnect
25
+ end
26
+
27
+ def to_s
28
+ "Redis Client connected to #{@client.host}:#{@client.port} against DB #{@client.db}"
29
+ end
30
+
31
+ private
32
+ def _extend_strategy(options)
33
+ strategy = options[:strategy]
34
+
35
+ unless strategy === false
36
+ strategy_class = STRATEGIES[strategy] || STRATEGIES[:marshal]
37
+ extend Strategy, strategy_class
38
+ end
39
+ end
40
+
41
+ def _extend_namespace(options)
42
+ @namespace = options[:namespace]
43
+ extend Namespace if @namespace
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,21 @@
1
+ class Redis
2
+ class Store < self
3
+ module Interface
4
+ def get(key, options = nil)
5
+ super(key)
6
+ end
7
+
8
+ def set(key, value, options = nil)
9
+ super(key, value)
10
+ end
11
+
12
+ def setnx(key, value, options = nil)
13
+ super(key, value)
14
+ end
15
+
16
+ def setex(key, expiry, value, options = nil)
17
+ super(key, expiry, value)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,66 @@
1
+ class Redis
2
+ class Store < self
3
+ module Namespace
4
+ def set(key, val, options = nil)
5
+ namespace(key) { |key| super(key, val, options) }
6
+ end
7
+
8
+ def setnx(key, val, options = nil)
9
+ namespace(key) { |key| super(key, val, options) }
10
+ end
11
+
12
+ def get(key, options = nil)
13
+ namespace(key) { |key| super(key, options) }
14
+ end
15
+
16
+ def exists(key)
17
+ namespace(key) { |key| super(key) }
18
+ end
19
+
20
+ def incrby(key, increment)
21
+ namespace(key) { |key| super(key, increment) }
22
+ end
23
+
24
+ def decrby(key, increment)
25
+ namespace(key) { |key| super(key, increment) }
26
+ end
27
+
28
+ def keys(pattern = "*")
29
+ namespace(pattern) { |pattern| super(pattern).map{|key| strip_namespace(key) } }
30
+ end
31
+
32
+ def del(*keys)
33
+ super *keys.map {|key| interpolate(key) } if keys.any?
34
+ end
35
+
36
+ def mget(*keys)
37
+ super *keys.map {|key| interpolate(key) } if keys.any?
38
+ end
39
+
40
+ def to_s
41
+ "#{super} with namespace #{@namespace}"
42
+ end
43
+
44
+ def flushdb
45
+ del *keys
46
+ end
47
+
48
+ private
49
+ def namespace(key)
50
+ yield interpolate(key)
51
+ end
52
+
53
+ def interpolate(key)
54
+ key.match(namespace_regexp) ? key : "#{@namespace}:#{key}"
55
+ end
56
+
57
+ def strip_namespace(key)
58
+ key.gsub namespace_regexp, ""
59
+ end
60
+
61
+ def namespace_regexp
62
+ @namespace_regexp ||= %r{^#{@namespace}\:}
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,60 @@
1
+ require 'redis/store/strategy/json'
2
+ require 'redis/store/strategy/json_session'
3
+ require 'redis/store/strategy/marshal'
4
+ require 'redis/store/strategy/yaml'
5
+
6
+ class Redis
7
+ class Store < self
8
+ module Strategy
9
+ def set(key, value, options = nil)
10
+ dump(value, options) { |value| super encode(key), encode(value), options }
11
+ end
12
+
13
+ def setnx(key, value, options = nil)
14
+ dump(value, options) { |value| super encode(key), encode(value), options }
15
+ end
16
+
17
+ def setex(key, expiry, value, options = nil)
18
+ dump(value, options) { |value| super encode(key), expiry, encode(value), options }
19
+ end
20
+
21
+ def get(key, options = nil)
22
+ load super(key), options
23
+ end
24
+
25
+ def mget(*keys)
26
+ options = keys.flatten.pop if keys.flatten.last.is_a?(Hash)
27
+ super(*keys).map do |result|
28
+ load result, options
29
+ end
30
+ end
31
+
32
+ private
33
+ def dump(val, options)
34
+ yield dump?(options) ? _dump(val) : val
35
+ end
36
+
37
+ def load(val, options)
38
+ load?(val, options) ? _load(val) : val
39
+ end
40
+
41
+ def dump?(options)
42
+ !(options && options[:raw])
43
+ end
44
+
45
+ def load?(result, options)
46
+ result && result.size > 0 && dump?(options)
47
+ end
48
+
49
+ if defined?(Encoding)
50
+ def encode(string)
51
+ string.to_s.force_encoding(Encoding::BINARY)
52
+ end
53
+ else
54
+ def encode(string)
55
+ string
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,49 @@
1
+ require 'json'
2
+
3
+ class Redis
4
+ class Store < self
5
+ module Strategy
6
+ module Json
7
+ private
8
+ SERIALIZABLE = [String, TrueClass, FalseClass, NilClass, Numeric, Date, Time].freeze
9
+ MARSHAL_INDICATORS = ["\x04", "\004", "\u0004"].freeze
10
+
11
+ def _dump(object)
12
+ object = _marshal(object)
13
+ object.to_json
14
+ end
15
+
16
+ def _load(string)
17
+ object = JSON.parse(string, :symbolize_names => true)
18
+ _unmarshal(object)
19
+ end
20
+
21
+ def _marshal(object)
22
+ case object
23
+ when Hash
24
+ object.each { |k,v| object[k] = _marshal(v) }
25
+ when Array
26
+ object.each_with_index { |v, i| object[i] = _marshal(v) }
27
+ when *SERIALIZABLE
28
+ object
29
+ else
30
+ ::Marshal.dump(object)
31
+ end
32
+ end
33
+
34
+ def _unmarshal(object)
35
+ case object
36
+ when Hash
37
+ object.each { |k,v| object[k] = _unmarshal(v) }
38
+ when Array
39
+ object.each_with_index { |v, i| object[i] = _unmarshal(v) }
40
+ when String
41
+ MARSHAL_INDICATORS.any?{ |indicator| object.start_with?(indicator) } ? ::Marshal.load(object) : object
42
+ else
43
+ object
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,67 @@
1
+ class Redis
2
+ class Store < self
3
+ module Strategy
4
+ module JsonSession
5
+
6
+ class Error < StandardError
7
+ end
8
+
9
+ class SerializationError < Redis::Store::Strategy::JsonSession::Error
10
+ def initialize(object)
11
+ super "Cannot correctly serialize object: #{object.inspect}"
12
+ end
13
+ end
14
+
15
+ private
16
+ SERIALIZABLE = [String, TrueClass, FalseClass, NilClass, Numeric, Date, Time, Symbol]
17
+ MARSHAL_INDICATORS = ["\x04", "\004", "\u0004"]
18
+
19
+ def _dump(object)
20
+ object = _marshal(object)
21
+ JSON.generate(object)
22
+ end
23
+
24
+ def _load(string)
25
+ object =
26
+ string.start_with?(*MARSHAL_INDICATORS) ? ::Marshal.load(string) : JSON.parse(string)
27
+ _unmarshal(object)
28
+ end
29
+
30
+ def _marshal(object)
31
+ case object
32
+ when Hash
33
+ marshal_hash(object)
34
+ when Array
35
+ object.each_with_index { |v, i| object[i] = _marshal(v) }
36
+ when Set
37
+ _marshal(object.to_a)
38
+ when String
39
+ object.encoding == Encoding::ASCII_8BIT ? object.to_json_raw_object : object
40
+ when *SERIALIZABLE
41
+ object
42
+ else
43
+ raise SerializationError.new(object)
44
+ end
45
+ end
46
+
47
+ def marshal_hash(object)
48
+ object.each { |k,v| object[k] = _marshal(v) }
49
+ end
50
+
51
+ def _unmarshal(object)
52
+ case object
53
+ when Hash
54
+ object.each { |k,v| object[k] = _unmarshal(v) }
55
+ when Array
56
+ object.each_with_index { |v, i| object[i] = _unmarshal(v) }
57
+ when String
58
+ object.start_with?(*MARSHAL_INDICATORS) ? ::Marshal.load(object) : object
59
+ else
60
+ object
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end