redis-store-pika 1.9.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # This is a fork!
2
+
3
+ This is a fork of official redis-store gem published to let people use fixes unavailable on official one yet.
4
+ Be sure to check updates from official [`redis-store`](https://github.com/redis-store/redis-store) gem sometimes in case the fixes included in this fork are already merged there.
5
+ (You can subscribe specific issues/PRs/releases on GitHub)
6
+
7
+ To install this fork place `redis-store-pika` into Gemfile (no special `require` option needed, I think).
8
+ Be sure not to install/require `redis-store` at the same time (maybe comment that line out in `Gemfile`)
9
+
10
+ ## Versioning
11
+ Since this is a fork (as a temporary measure) semantic versioning won't be used.
12
+ It would be like `(last offical version)` + `.x` (`x` = how many times it's released)
13
+ (e.g. Based on `1.9.2` + 1st release = `1.9.2.1`)
14
+
15
+ # Redis stores for Ruby frameworks
16
+
17
+ __Redis Store__ provides a full set of stores (*Cache*, *I18n*, *Session*, *HTTP Cache*) for modern Ruby frameworks like: __Ruby on Rails__, __Sinatra__, __Rack__, __Rack::Cache__ and __I18n__. It supports object marshalling, timeouts, single or multiple nodes, and namespaces.
18
+
19
+ Please check the *README* file of each gem for usage and installation guidelines.
20
+
21
+ ## Redis Installation
22
+
23
+ ### Option 1: Homebrew
24
+
25
+ MacOS X users should use [Homebrew](https://github.com/mxcl/homebrew) to install Redis:
26
+
27
+ ```shell
28
+ brew install redis
29
+ ```
30
+
31
+ ### Option 2: From Source
32
+
33
+ Download and install Redis from [the download page](http://redis.io//download) and follow the instructions.
34
+
35
+ ## Running tests
36
+
37
+ ```ruby
38
+ git clone git://github.com/redis-store/redis-store.git
39
+ cd redis-store
40
+ bundle install
41
+ bundle exec rake
42
+ ```
43
+
44
+ If you are on **Snow Leopard** you have to run `env ARCHFLAGS="-arch x86_64" ruby ci/run.rb`
45
+
46
+ ## Contributors
47
+
48
+ https://github.com/redis-store/redis-store/graphs/contributors
49
+
50
+ ## Versioning
51
+
52
+ The **redis-store** family of gems uses [Semantic Versioning](http://semver.org), meaning gems depending on **redis-store**
53
+ can be reliably inclusive of any version between the current and the next major. We recommend the following dependency
54
+ in your library's gemspec:
55
+
56
+ ```ruby
57
+ s.add_dependency 'redis-store', '>= 1.4', '< 2'
58
+ ```
59
+
60
+ ## Status
61
+
62
+ [![Gem Version](https://badge.fury.io/rb/redis-store.svg)](http://badge.fury.io/rb/redis-store)
63
+ [![Build Status](https://secure.travis-ci.org/redis-store/redis-store.svg?branch=master)](http://travis-ci.org/redis-store/redis-store?branch=master)
64
+ [![Code Climate](https://codeclimate.com/github/redis-store/redis-store.svg)](https://codeclimate.com/github/redis-store/redis-store)
65
+
66
+ ## Copyright
67
+
68
+ 2009 - 2013 Luca Guidi - [http://lucaguidi.com](http://lucaguidi.com), released under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'bundler/setup'
2
+ require 'rake'
3
+ require 'bundler/gem_tasks'
4
+ require 'appraisal'
5
+ require 'rubocop/rake_task'
6
+
7
+ RuboCop::RakeTask.new :lint
8
+
9
+ if !ENV["APPRAISAL_INITIALIZED"] && !ENV["CI"]
10
+ task :default do
11
+ sh "appraisal install && rake appraisal default"
12
+ end
13
+ else
14
+ require 'redis-store/testing/tasks'
15
+ end
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "redis", "~> 4.0.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "redis", "~> 4.1.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "redis", "~> 4.6.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "redis", "~> 4.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "redis", "~> 5.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,68 @@
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
+ _extend_namespace options
10
+ # `@tag` introduced in `redis-rb` 5.0
11
+ @tag = options[:tag] || /^\{(.+?)\}/
12
+ @ring = options[:ring] || Redis::HashRing.new([], options[:replicas] || Redis::HashRing::POINTS_PER_SERVER)
13
+
14
+ addresses.each do |address|
15
+ @ring.add_node(::Redis::Store.new _merge_options(address, options))
16
+ end
17
+ end
18
+
19
+ def nodes
20
+ ring.nodes
21
+ end
22
+
23
+ def reconnect
24
+ nodes.each { |node| node.reconnect }
25
+ end
26
+
27
+ def set(key, value, options = nil)
28
+ node_for(key).set(key, value, options)
29
+ end
30
+
31
+ def get(key, options = nil)
32
+ node_for(key).get(key, options)
33
+ end
34
+
35
+ def setnx(key, value, options = nil)
36
+ node_for(key).setnx(key, value, options)
37
+ end
38
+
39
+ def redis_version
40
+ nodes.first.redis_version unless nodes.empty?
41
+ end
42
+
43
+ def supports_redis_version?(version)
44
+ if nodes.empty?
45
+ false
46
+ else
47
+ nodes.first.supports_redis_version?(version)
48
+ end
49
+ end
50
+
51
+ def setex(key, expiry, value, options = nil)
52
+ node_for(key).setex(key, expiry, value, options)
53
+ end
54
+
55
+ private
56
+ def _extend_namespace(options)
57
+ @namespace = options[:namespace]
58
+ extend ::Redis::Store::Namespace if @namespace
59
+ end
60
+
61
+ def _merge_options(address, options)
62
+ address.merge(
63
+ :timeout => options[:timeout] || @@timeout,
64
+ :namespace => options[:namespace]
65
+ )
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,111 @@
1
+ require 'cgi'
2
+ require 'uri'
3
+
4
+ class Redis
5
+ class Store < self
6
+ class Factory
7
+ DEFAULT_PORT = 6379
8
+
9
+ def self.create(*options)
10
+ new(options).create
11
+ end
12
+
13
+ def initialize(*options)
14
+ @addresses = []
15
+ @options = {}
16
+ extract_addresses_and_options(options)
17
+ end
18
+
19
+ def create
20
+ if @addresses.empty?
21
+ @addresses << {}
22
+ end
23
+
24
+ if @addresses.size > 1
25
+ ::Redis::DistributedStore.new @addresses, @options
26
+ else
27
+ ::Redis::Store.new @addresses.first.merge(@options)
28
+ end
29
+ end
30
+
31
+ def self.resolve(uri) #:api: private
32
+ if uri.is_a?(Hash)
33
+ extract_host_options_from_hash(uri)
34
+ else
35
+ extract_host_options_from_uri(uri)
36
+ end
37
+ end
38
+
39
+ def self.extract_host_options_from_hash(options)
40
+ options = normalize_key_names(options)
41
+ if host_options?(options)
42
+ options
43
+ else
44
+ nil
45
+ end
46
+ end
47
+
48
+ def self.normalize_key_names(options)
49
+ options = options.dup
50
+ if options.key?(:key_prefix) && !options.key?(:namespace)
51
+ options[:namespace] = options.delete(:key_prefix) # RailsSessionStore
52
+ end
53
+ options[:raw] = case
54
+ when options.key?(:serializer)
55
+ options[:serializer].nil?
56
+ when options.key?(:marshalling)
57
+ !options[:marshalling]
58
+ else
59
+ false
60
+ end
61
+ options
62
+ end
63
+
64
+ def self.host_options?(options)
65
+ options.keys.any? { |n| [:host, :db, :port, :path].include?(n) }
66
+ end
67
+
68
+ def self.extract_host_options_from_uri(uri)
69
+ uri = URI.parse(uri)
70
+ if uri.scheme == "unix"
71
+ options = { :path => uri.path }
72
+ else
73
+ _, db, namespace = if uri.path
74
+ uri.path.split(/\//)
75
+ end
76
+
77
+ options = {
78
+ :scheme => uri.scheme,
79
+ :host => uri.hostname,
80
+ :port => uri.port || DEFAULT_PORT,
81
+ :password => uri.password.nil? ? nil : CGI.unescape(uri.password.to_s)
82
+ }
83
+
84
+ options[:db] = db.to_i if db
85
+ options[:namespace] = namespace if namespace
86
+ end
87
+ if uri.query
88
+ query = Hash[URI.decode_www_form(uri.query)]
89
+ query.each do |(key, value)|
90
+ options[key.to_sym] = value
91
+ end
92
+ end
93
+
94
+ options
95
+ end
96
+
97
+ private
98
+
99
+ def extract_addresses_and_options(*options)
100
+ options.flatten.compact.each do |token|
101
+ resolved = self.class.resolve(token)
102
+ if resolved
103
+ @addresses << resolved
104
+ else
105
+ @options.merge!(self.class.normalize_key_names(token))
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,29 @@
1
+ class Redis
2
+ class Store < self
3
+ module Interface
4
+ def get(key, options = nil)
5
+ super(key)
6
+ end
7
+
8
+ REDIS_SET_OPTIONS = %i(ex px nx xx keepttl).freeze
9
+ private_constant :REDIS_SET_OPTIONS
10
+
11
+ def set(key, value, options = nil)
12
+ if options && REDIS_SET_OPTIONS.any? { |k| options.key?(k) }
13
+ kwargs = REDIS_SET_OPTIONS.each_with_object({}) { |key, h| h[key] = options[key] if options.key?(key) }
14
+ super(key, value, **kwargs)
15
+ else
16
+ super(key, value)
17
+ end
18
+ end
19
+
20
+ def setnx(key, value, options = nil)
21
+ super(key, value)
22
+ end
23
+
24
+ def setex(key, expiry, value, options = nil)
25
+ super(key, expiry, value)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,211 @@
1
+ class Redis
2
+ class Store < self
3
+ module Namespace
4
+ FLUSHDB_BATCH_SIZE = 1000
5
+
6
+ def set(key, *args)
7
+ namespace(key) { |k| super(k, *args) }
8
+ end
9
+
10
+ def setex(key, *args)
11
+ namespace(key) { |k| super(k, *args) }
12
+ end
13
+
14
+ def setnx(key, *args)
15
+ namespace(key) { |k| super(k, *args) }
16
+ end
17
+
18
+ def ttl(key, options = nil)
19
+ namespace(key) { |k| super(k) }
20
+ end
21
+
22
+ def get(key, *args)
23
+ namespace(key) { |k| super(k, *args) }
24
+ end
25
+
26
+ def exists(*keys)
27
+ super(*keys.map { |key| interpolate(key) })
28
+ end
29
+
30
+ def exists?(*keys)
31
+ super(*keys.map { |key| interpolate(key) })
32
+ end
33
+
34
+ def incrby(key, increment)
35
+ namespace(key) { |k| super(k, increment) }
36
+ end
37
+
38
+ def decrby(key, increment)
39
+ namespace(key) { |k| super(k, increment) }
40
+ end
41
+
42
+ def keys(pattern = "*")
43
+ namespace(pattern) { |p| super(p).map { |key| strip_namespace(key) } }
44
+ end
45
+
46
+ def scan(cursor, match: nil, **kwargs)
47
+ if match
48
+ namespace(match) do |pattern|
49
+ cursor, keys = super(cursor, match: pattern, **kwargs)
50
+ [ cursor, keys.map { |key| strip_namespace(key) } ]
51
+ end
52
+ else
53
+ super(cursor, **kwargs)
54
+ end
55
+ end
56
+
57
+ def del(*keys)
58
+ super(*keys.map { |key| interpolate(key) }) if keys.any?
59
+ end
60
+
61
+ def unlink(*keys)
62
+ super(*keys.map { |key| interpolate(key) }) if keys.any?
63
+ end
64
+
65
+ def watch(*keys)
66
+ super(*keys.map { |key| interpolate(key) }) if keys.any?
67
+ end
68
+
69
+ def mget(*keys, &blk)
70
+ options = (keys.pop if keys.last.is_a? Hash) || {}
71
+ if keys.any?
72
+ # Serialization gets extended before Namespace does, so we need to pass options further
73
+ if singleton_class.ancestors.include? Serialization
74
+ super(*keys.map { |key| interpolate(key) }, options, &blk)
75
+ else
76
+ super(*keys.map { |key| interpolate(key) }, &blk)
77
+ end
78
+ end
79
+ end
80
+
81
+ def expire(key, ttl)
82
+ namespace(key) { |k| super(k, ttl) }
83
+ end
84
+
85
+ def hdel(key, *fields)
86
+ namespace(key) { |k| super(k, *fields) }
87
+ end
88
+
89
+ def hget(key, field)
90
+ namespace(key) { |k| super(k, field) }
91
+ end
92
+
93
+ def hgetall(key)
94
+ namespace(key) { |k| super(k) }
95
+ end
96
+
97
+ def hexists(key, field)
98
+ namespace(key) { |k| super(k, field) }
99
+ end
100
+
101
+ def hincrby(key, field, increment)
102
+ namespace(key) { |k| super(k, field, increment) }
103
+ end
104
+
105
+ def hincrbyfloat(key, field, increment)
106
+ namespace(key) { |k| super(k, field, increment) }
107
+ end
108
+
109
+ def hkeys(key)
110
+ namespace(key) { |k| super(k) }
111
+ end
112
+
113
+ def hlen(key)
114
+ namespace(key) { |k| super(k) }
115
+ end
116
+
117
+ def hmget(key, *fields, &blk)
118
+ namespace(key) { |k| super(k, *fields, &blk) }
119
+ end
120
+
121
+ def hmset(key, *attrs)
122
+ namespace(key) { |k| super(k, *attrs) }
123
+ end
124
+
125
+ def hset(key, *args)
126
+ namespace(key) { |k| super(k, *args) }
127
+ end
128
+
129
+ def hsetnx(key, field, val)
130
+ namespace(key) { |k| super(k, field, val) }
131
+ end
132
+
133
+ def hvals(key)
134
+ namespace(key) { |k| super(k) }
135
+ end
136
+
137
+ def hscan(key, *args)
138
+ namespace(key) { |k| super(k, *args) }
139
+ end
140
+
141
+ def hscan_each(key, *args)
142
+ namespace(key) { |k| super(k, *args) }
143
+ end
144
+
145
+ def zincrby(key, increment, member)
146
+ namespace(key) { |k| super(k, increment, member) }
147
+ end
148
+
149
+ def zscore(key, member)
150
+ namespace(key) { |k| super(k, member) }
151
+ end
152
+
153
+ def zadd(key, *args)
154
+ namespace(key) { |k| super(k, *args) }
155
+ end
156
+
157
+ def zrem(key, member)
158
+ namespace(key) { |k| super(k, member) }
159
+ end
160
+
161
+ if respond_to?(:ruby2_keywords, true)
162
+ ruby2_keywords :set, :setex, :setnx, :hscan, :hscan_each
163
+ end
164
+
165
+ def to_s
166
+ if namespace_str
167
+ "#{super} with namespace #{namespace_str}"
168
+ else
169
+ super
170
+ end
171
+ end
172
+
173
+ def flushdb
174
+ return super unless namespace_str
175
+ keys.each_slice(FLUSHDB_BATCH_SIZE) { |key_slice| del(*key_slice) }
176
+ end
177
+
178
+ def with_namespace(ns)
179
+ old_ns = @namespace
180
+ @namespace = ns
181
+ yield self
182
+ ensure
183
+ @namespace = old_ns
184
+ end
185
+
186
+ private
187
+ def namespace(key)
188
+ yield interpolate(key)
189
+ end
190
+
191
+ def namespace_str
192
+ @namespace.is_a?(Proc) ? @namespace.call : @namespace
193
+ end
194
+
195
+ def interpolate(key)
196
+ return key unless namespace_str
197
+ key.match(namespace_regexp) ? key : "#{namespace_str}:#{key}"
198
+ end
199
+
200
+ def strip_namespace(key)
201
+ return key unless namespace_str
202
+ key.gsub namespace_regexp, ""
203
+ end
204
+
205
+ def namespace_regexp
206
+ @namespace_regexps ||= {}
207
+ @namespace_regexps[namespace_str] ||= %r{^#{namespace_str}\:}
208
+ end
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,13 @@
1
+ class Redis
2
+ class Store < self
3
+ module RedisVersion
4
+ def redis_version
5
+ info('server')['redis_version']
6
+ end
7
+
8
+ def supports_redis_version?(version)
9
+ (redis_version.split(".").map(&:to_i) <=> version.split(".").map(&:to_i)) >= 0
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,67 @@
1
+ class Redis
2
+ class Store < self
3
+ module Serialization
4
+ def set(key, value, options = nil)
5
+ _marshal(value, options) { |v| super encode(key), encode(v), options }
6
+ end
7
+
8
+ def setnx(key, value, options = nil)
9
+ _marshal(value, options) { |v| super encode(key), encode(v), options }
10
+ end
11
+
12
+ def setex(key, expiry, value, options = nil)
13
+ _marshal(value, options) { |v| super encode(key), expiry, encode(v), options }
14
+ end
15
+
16
+ def get(key, options = nil)
17
+ _unmarshal super(key), options
18
+ end
19
+
20
+ def mget(*keys, &blk)
21
+ options = keys.pop if keys.last.is_a?(Hash)
22
+ super(*keys) do |reply|
23
+ reply.map! { |value| _unmarshal value, options }
24
+ blk ? blk.call(reply) : reply
25
+ end
26
+ end
27
+
28
+ def mset(*args)
29
+ options = args.pop if args.length.odd?
30
+ updates = []
31
+ args.each_slice(2) do |(key, value)|
32
+ updates << encode(key)
33
+ _marshal(value, options) { |v| updates << encode(v) }
34
+ end
35
+ super(*updates)
36
+ end
37
+
38
+ private
39
+ def _marshal(val, options)
40
+ yield marshal?(options) ? @serializer.dump(val) : val
41
+ end
42
+
43
+ def _unmarshal(val, options)
44
+ unmarshal?(val, options) ? @serializer.load(val) : val
45
+ end
46
+
47
+ def marshal?(options)
48
+ !(options && options[:raw])
49
+ end
50
+
51
+ def unmarshal?(result, options)
52
+ result && result.size > 0 && marshal?(options)
53
+ end
54
+
55
+ if defined?(Encoding)
56
+ def encode(string)
57
+ key = string.to_s.dup
58
+ key.force_encoding(Encoding::BINARY)
59
+ end
60
+ else
61
+ def encode(string)
62
+ string
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,47 @@
1
+ class Redis
2
+ class Store < self
3
+ module Ttl
4
+ def set(key, value, options = nil)
5
+ if ttl = expires_in(options)
6
+ setex(key, ttl.to_i, value, :raw => true)
7
+ else
8
+ super(key, value, options)
9
+ end
10
+ end
11
+
12
+ def setnx(key, value, options = nil)
13
+ if ttl = expires_in(options)
14
+ setnx_with_expire(key, value, ttl.to_i, options)
15
+ else
16
+ super(key, value)
17
+ end
18
+ end
19
+
20
+ protected
21
+ def setnx_with_expire(key, value, ttl, options = {})
22
+ with_multi_or_pipelined(options) do |transaction|
23
+ if transaction.is_a?(Redis::Store) # for redis < 4.6
24
+ setnx(key, value, :raw => true)
25
+ expire(key, ttl)
26
+ else
27
+ transaction.setnx(key, value)
28
+ transaction.expire(key, ttl)
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+ def expires_in(options)
35
+ if options
36
+ # Rack::Session Merb Rails/Sinatra
37
+ options[:expire_after] || options[:expires_in] || options[:expire_in]
38
+ end
39
+ end
40
+
41
+ def with_multi_or_pipelined(options, &block)
42
+ return pipelined(&block) if options.key?(:cluster) || options[:avoid_multi_commands]
43
+ multi(&block)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,13 @@
1
+ class Redis
2
+ class Store < self
3
+ # Official version + `.x`
4
+ VERSION = '1.9.2.1'
5
+
6
+ def self.redis_client_defined?
7
+ # Doesn't work if declared as constant
8
+ # due to unpredictable gem loading order
9
+ # https://github.com/redis-rb/redis-client
10
+ defined?(::RedisClient::VERSION)
11
+ end
12
+ end
13
+ end