redis-actionpack-json 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +15 -0
- data/.travis.yml +7 -0
- data/CHANGELOG +450 -0
- data/README.md +23 -0
- data/redis-actionpack-json/.gitignore +4 -0
- data/redis-actionpack-json/Gemfile +6 -0
- data/redis-actionpack-json/MIT-LICENSE +20 -0
- data/redis-actionpack-json/Rakefile +8 -0
- data/redis-actionpack-json/lib/action_dispatch/middleware/session/redis_store_json.rb +24 -0
- data/redis-actionpack-json/lib/redis-actionpack-json.rb +4 -0
- data/redis-actionpack-json/lib/redis/actionpack/version.rb +5 -0
- data/redis-actionpack-json/redis-actionpack-json.gemspec +32 -0
- data/redis-actionpack-json/test/dummy/.gitignore +1 -0
- data/redis-actionpack-json/test/dummy/Rakefile +7 -0
- data/redis-actionpack-json/test/dummy/app/controllers/test_controller.rb +37 -0
- data/redis-actionpack-json/test/dummy/config.ru +4 -0
- data/redis-actionpack-json/test/dummy/config/application.rb +29 -0
- data/redis-actionpack-json/test/dummy/config/boot.rb +10 -0
- data/redis-actionpack-json/test/dummy/config/environment.rb +5 -0
- data/redis-actionpack-json/test/dummy/config/initializers/secret_token.rb +7 -0
- data/redis-actionpack-json/test/dummy/config/initializers/session_store.rb +11 -0
- data/redis-actionpack-json/test/dummy/config/routes.rb +3 -0
- data/redis-actionpack-json/test/dummy/script/rails +6 -0
- data/redis-actionpack-json/test/fixtures/session_autoload_test/session_autoload_test/foo.rb +10 -0
- data/redis-actionpack-json/test/integration/redis_store_integration_test.rb +130 -0
- data/redis-actionpack-json/test/integration/redis_store_json_integration_test.rb +130 -0
- data/redis-actionpack-json/test/redis/actionpack/version_test.rb +7 -0
- data/redis-actionpack-json/test/test_helper.rb +23 -0
- data/redis-rack-json/.gitignore +5 -0
- data/redis-rack-json/Gemfile +5 -0
- data/redis-rack-json/MIT-LICENSE +20 -0
- data/redis-rack-json/Rakefile +8 -0
- data/redis-rack-json/lib/rack/session/redis.rb +69 -0
- data/redis-rack-json/lib/redis-rack-json.rb +3 -0
- data/redis-rack-json/lib/redis/rack/version.rb +6 -0
- data/redis-rack-json/redis-rack-json.gemspec +29 -0
- data/redis-rack-json/test/rack/session/redis_test.rb +289 -0
- data/redis-rack-json/test/redis/rack/version_test.rb +7 -0
- data/redis-rack-json/test/test_helper.rb +7 -0
- data/redis-store-json/Gemfile +4 -0
- data/redis-store-json/MIT-LICENSE +20 -0
- data/redis-store-json/Rakefile +7 -0
- data/redis-store-json/lib/redis-store-json.rb +11 -0
- data/redis-store-json/lib/redis/distributed_store.rb +46 -0
- data/redis-store-json/lib/redis/factory.rb +41 -0
- data/redis-store-json/lib/redis/store.rb +47 -0
- data/redis-store-json/lib/redis/store/interface.rb +21 -0
- data/redis-store-json/lib/redis/store/namespace.rb +66 -0
- data/redis-store-json/lib/redis/store/strategy.rb +60 -0
- data/redis-store-json/lib/redis/store/strategy/json.rb +49 -0
- data/redis-store-json/lib/redis/store/strategy/json_session.rb +67 -0
- data/redis-store-json/lib/redis/store/strategy/marshal.rb +16 -0
- data/redis-store-json/lib/redis/store/strategy/yaml.rb +16 -0
- data/redis-store-json/lib/redis/store/ttl.rb +37 -0
- data/redis-store-json/lib/redis/store/version.rb +5 -0
- data/redis-store-json/lib/tasks/redis.tasks.rb +167 -0
- data/redis-store-json/redis-store-json.gemspec +29 -0
- data/redis-store-json/test/config/node-one.conf +46 -0
- data/redis-store-json/test/config/node-two.conf +46 -0
- data/redis-store-json/test/config/redis.conf +46 -0
- data/redis-store-json/test/redis/distributed_store_test.rb +53 -0
- data/redis-store-json/test/redis/factory_test.rb +120 -0
- data/redis-store-json/test/redis/store/interface_test.rb +27 -0
- data/redis-store-json/test/redis/store/namespace_test.rb +103 -0
- data/redis-store-json/test/redis/store/strategy/json_session_test.rb +160 -0
- data/redis-store-json/test/redis/store/strategy/json_test.rb +108 -0
- data/redis-store-json/test/redis/store/strategy/marshal_test.rb +121 -0
- data/redis-store-json/test/redis/store/strategy/yaml_test.rb +105 -0
- data/redis-store-json/test/redis/store/ttl_test.rb +107 -0
- data/redis-store-json/test/redis/store/version_test.rb +7 -0
- data/redis-store-json/test/redis/store_test.rb +45 -0
- data/redis-store-json/test/test_helper.rb +22 -0
- metadata +279 -0
@@ -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,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
|