redis-store-pika 1.9.2.1

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.
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