cache_store_redis 0.5.5 → 0.6.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.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27eeddfa958f35d2bace14b86093d3dfab8c2a23
|
4
|
+
data.tar.gz: ac17f9dd859655f8493f8d4abc9e7f98223c91e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f04c7cc83c4d9fa6a8b49b443029909a56d6fb2760f387aaafaae6af9745309ac7d5081e546d39edaa2a2329ab50a2387d4bde5c6e7c73cdb40eb27e6d27892
|
7
|
+
data.tar.gz: a78cda144717405ffe7987e781afadb76cc4d093af26f122851dadb99a0dcd93842e9f271161b5dfd13154ed61defeaba27c3082dc042e7003f23f061996d10a
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
# This class is used to define a redis cache store that logs failures as warnings but does not raise errors for
|
4
|
+
# cache connections
|
5
|
+
class OptionalRedisCacheStore
|
6
|
+
def initialize(namespace: nil, config: nil, logger: nil)
|
7
|
+
@cache_store = RedisCacheStore.new(namespace, config)
|
8
|
+
@logger = logger || Logger.new(STDOUT)
|
9
|
+
end
|
10
|
+
|
11
|
+
def redis_store
|
12
|
+
@cache_store
|
13
|
+
end
|
14
|
+
|
15
|
+
# This method is called to configure the connection to the cache store.
|
16
|
+
def configure(
|
17
|
+
host = 'localhost',
|
18
|
+
port = 6379,
|
19
|
+
db = 'default',
|
20
|
+
password = nil,
|
21
|
+
driver: nil,
|
22
|
+
url: nil,
|
23
|
+
connect_timeout: 0.5,
|
24
|
+
read_timeout: 1,
|
25
|
+
write_timeout: 0.5)
|
26
|
+
redis_store.configure(
|
27
|
+
host,
|
28
|
+
port,
|
29
|
+
db,
|
30
|
+
password,
|
31
|
+
driver: driver,
|
32
|
+
url: url,
|
33
|
+
connect_timeout: connect_timeout,
|
34
|
+
read_timeout: read_timeout,
|
35
|
+
write_timeout: write_timeout
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def optional_get(key, expires_in = 0)
|
40
|
+
redis_store.get(key, expires_in)
|
41
|
+
rescue => e
|
42
|
+
@logger.error(
|
43
|
+
"[#{self.class}] - An error occurred requesting data from the cache. " \
|
44
|
+
"Key: #{key} | Error: #{e.message} | Backtrace: #{e.backtrace}"
|
45
|
+
)
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def get(key, expires_in = 0, &block)
|
50
|
+
value = optional_get(key, expires_in)
|
51
|
+
|
52
|
+
if value.nil? && block_given?
|
53
|
+
value = yield
|
54
|
+
set(key, value, expires_in)
|
55
|
+
end
|
56
|
+
|
57
|
+
value
|
58
|
+
end
|
59
|
+
|
60
|
+
def set(key, value, expires_in = 0)
|
61
|
+
redis_store.set(key, value, expires_in)
|
62
|
+
rescue => e
|
63
|
+
@logger.error(
|
64
|
+
"[#{self.class}] - An error occurred storing data in the cache. " \
|
65
|
+
"Key: #{key} | Error: #{e.message} | Backtrace: #{e.backtrace}"
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
def remove(key)
|
70
|
+
redis_store.remove(key)
|
71
|
+
rescue => e
|
72
|
+
@logger.error(
|
73
|
+
"[#{self.class}] - An error occurred removing data from the cache. " \
|
74
|
+
"Key: #{key} | Error: #{e.message} | Backtrace: #{e.backtrace}"
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def exist?(key)
|
79
|
+
redis_store.exist?(key)
|
80
|
+
rescue => e
|
81
|
+
@logger.error(
|
82
|
+
"[#{self.class}] - An error occurred checking if a key exists in the cache. " \
|
83
|
+
"Key: #{key} | Error: #{e.message} | Backtrace: #{e.backtrace}"
|
84
|
+
)
|
85
|
+
false
|
86
|
+
end
|
87
|
+
|
88
|
+
def ping
|
89
|
+
redis_store.ping
|
90
|
+
rescue => e
|
91
|
+
@logger.error(
|
92
|
+
"[#{self.class}] - An error occurred checking pinging the cache. " \
|
93
|
+
"Error: #{e.message} | Backtrace: #{e.backtrace}"
|
94
|
+
)
|
95
|
+
false
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
# This class is used to implement a redis cache store.
|
2
|
+
class RedisCacheStore
|
3
|
+
def initialize(namespace = nil, config = nil)
|
4
|
+
unless RUBY_PLATFORM == 'java'
|
5
|
+
require 'oj'
|
6
|
+
end
|
7
|
+
|
8
|
+
@namespace = namespace
|
9
|
+
@config = config
|
10
|
+
@queue = Queue.new
|
11
|
+
|
12
|
+
@connections_created = 0
|
13
|
+
@connections_in_use = 0
|
14
|
+
@mutex = Mutex.new
|
15
|
+
@enable_stats = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def enable_stats=(value)
|
19
|
+
@enable_stats = value
|
20
|
+
end
|
21
|
+
|
22
|
+
def increment_created_stat
|
23
|
+
@mutex.synchronize do
|
24
|
+
@connections_created += 1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def increment_using_stat
|
29
|
+
@mutex.synchronize do
|
30
|
+
@connections_in_use += 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def decrement_using_stat
|
35
|
+
@mutex.synchronize do
|
36
|
+
@connections_in_use -= 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# This method is called to configure the connection to the cache store.
|
41
|
+
def configure(host = 'localhost',
|
42
|
+
port = 6379,
|
43
|
+
db = 'default',
|
44
|
+
password = nil,
|
45
|
+
driver: nil,
|
46
|
+
url: nil,
|
47
|
+
connect_timeout: 0.5,
|
48
|
+
read_timeout: 1,
|
49
|
+
write_timeout: 0.5)
|
50
|
+
if !url.nil?
|
51
|
+
@config = {}
|
52
|
+
@config[:url] = url
|
53
|
+
@config[:db] = db
|
54
|
+
else
|
55
|
+
@config = { host: host, port: port, db: db }
|
56
|
+
end
|
57
|
+
|
58
|
+
@config[:password] = password unless password.nil?
|
59
|
+
@config[:driver] = driver unless driver.nil?
|
60
|
+
|
61
|
+
@config[:connect_timeout] = connect_timeout
|
62
|
+
@config[:read_timeout] = read_timeout
|
63
|
+
@config[:write_timeout] = write_timeout
|
64
|
+
end
|
65
|
+
|
66
|
+
def fetch_client
|
67
|
+
begin
|
68
|
+
@queue.pop(true)
|
69
|
+
rescue
|
70
|
+
increment_created_stat
|
71
|
+
Redis.new(@config)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def clean
|
76
|
+
while @queue.length.positive?
|
77
|
+
client = @queue.pop(true)
|
78
|
+
client.close
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def log_stats
|
83
|
+
return unless @enable_stats == true
|
84
|
+
S1Logging.logger.debug do
|
85
|
+
"[#{self.class}] - REDIS Connection Stats. Process: #{Process.pid} | " \
|
86
|
+
"Created: #{@connections_created} | Pending: #{@queue.length} | In use: #{@connections_in_use}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def with_client
|
91
|
+
log_stats
|
92
|
+
begin
|
93
|
+
client = fetch_client
|
94
|
+
increment_using_stat
|
95
|
+
log_stats
|
96
|
+
yield client
|
97
|
+
ensure
|
98
|
+
@queue.push(client)
|
99
|
+
decrement_using_stat
|
100
|
+
log_stats
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# This method is called to set a value within this cache store by it's key.
|
105
|
+
#
|
106
|
+
# @param key [String] This is the unique key to reference the value being set within this cache store.
|
107
|
+
# @param value [Object] This is the value to set within this cache store.
|
108
|
+
# @param expires_in [Integer] This is the number of seconds from the current time that this value should expire.
|
109
|
+
def set(key, value, expires_in = 0)
|
110
|
+
k = build_key(key)
|
111
|
+
|
112
|
+
v = if value.nil? || (value.is_a?(String) && value.strip.empty?)
|
113
|
+
nil
|
114
|
+
else
|
115
|
+
serialize(value)
|
116
|
+
end
|
117
|
+
|
118
|
+
with_client do |client|
|
119
|
+
client.multi do
|
120
|
+
client.set(k, v)
|
121
|
+
|
122
|
+
client.expire(k, expires_in) if expires_in.positive?
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# This method is called to get a value from this cache store by it's unique key.
|
128
|
+
#
|
129
|
+
# @param key [String] This is the unique key to reference the value to fetch from within this cache store.
|
130
|
+
# @param expires_in [Integer] This is the number of seconds from the current time that this value should expire.
|
131
|
+
# (This is used in conjunction with the block to hydrate the cache key if it is empty.)
|
132
|
+
# @param &block [Block] This block is provided to hydrate this cache store with the value for the request key
|
133
|
+
# when it is not found.
|
134
|
+
# @return [Object] The value for the specified unique key within the cache store.
|
135
|
+
def get(key, expires_in = 0, &block)
|
136
|
+
k = build_key(key)
|
137
|
+
|
138
|
+
value = with_client do |client|
|
139
|
+
client.get(k)
|
140
|
+
end
|
141
|
+
|
142
|
+
if !value.nil? && value.strip.empty?
|
143
|
+
value = nil
|
144
|
+
else
|
145
|
+
value = deserialize(value) unless value.nil?
|
146
|
+
end
|
147
|
+
|
148
|
+
if value.nil? && block_given?
|
149
|
+
value = yield
|
150
|
+
set(key, value, expires_in)
|
151
|
+
end
|
152
|
+
|
153
|
+
value
|
154
|
+
end
|
155
|
+
|
156
|
+
# This method is called to remove a value from this cache store by it's unique key.
|
157
|
+
#
|
158
|
+
# @param key [String] This is the unique key to reference the value to remove from this cache store.
|
159
|
+
def remove(key)
|
160
|
+
with_client do |client|
|
161
|
+
client.del(build_key(key))
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# This method is called to check if a value exists within this cache store for a specific key.
|
166
|
+
#
|
167
|
+
# @param key [String] This is the unique key to reference the value to check for within this cache store.
|
168
|
+
# @return [Boolean] True or False to specify if the key exists in the cache store.
|
169
|
+
def exist?(key)
|
170
|
+
with_client do |client|
|
171
|
+
client.exists(build_key(key))
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Ping the cache store.
|
176
|
+
#
|
177
|
+
# @return [String] `PONG`
|
178
|
+
def ping
|
179
|
+
with_client do |client|
|
180
|
+
client.ping
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def serialize(object)
|
187
|
+
if RUBY_PLATFORM == 'java'
|
188
|
+
Marshal::dump(object)
|
189
|
+
else
|
190
|
+
Oj.dump(object)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def deserialize(object)
|
195
|
+
if RUBY_PLATFORM == 'java'
|
196
|
+
Marshal::load(object)
|
197
|
+
else
|
198
|
+
Oj.load(object)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def build_key(key)
|
203
|
+
if !@namespace.nil?
|
204
|
+
@namespace + ':' + key.to_s
|
205
|
+
else
|
206
|
+
key.to_s
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
data/lib/cache_store_redis.rb
CHANGED
@@ -5,212 +5,5 @@ require 'cache_store_redis/version'
|
|
5
5
|
require 'redis'
|
6
6
|
require 'securerandom'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(namespace = nil, config = nil)
|
11
|
-
unless RUBY_PLATFORM == 'java'
|
12
|
-
require 'oj'
|
13
|
-
end
|
14
|
-
|
15
|
-
@namespace = namespace
|
16
|
-
@config = config
|
17
|
-
@queue = Queue.new
|
18
|
-
|
19
|
-
@connections_created = 0
|
20
|
-
@connections_in_use = 0
|
21
|
-
@mutex = Mutex.new
|
22
|
-
@enable_stats = false
|
23
|
-
end
|
24
|
-
|
25
|
-
def enable_stats=(value)
|
26
|
-
@enable_stats = value
|
27
|
-
end
|
28
|
-
|
29
|
-
def increment_created_stat
|
30
|
-
@mutex.synchronize do
|
31
|
-
@connections_created += 1
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def increment_using_stat
|
36
|
-
@mutex.synchronize do
|
37
|
-
@connections_in_use += 1
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def decrement_using_stat
|
42
|
-
@mutex.synchronize do
|
43
|
-
@connections_in_use -= 1
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# This method is called to configure the connection to the cache store.
|
48
|
-
def configure(host = 'localhost',
|
49
|
-
port = 6379,
|
50
|
-
db = 'default',
|
51
|
-
password = nil,
|
52
|
-
driver: nil,
|
53
|
-
url: nil,
|
54
|
-
connect_timeout: 0.5,
|
55
|
-
read_timeout: 1,
|
56
|
-
write_timeout: 0.5)
|
57
|
-
if !url.nil?
|
58
|
-
@config = {}
|
59
|
-
@config[:url] = url
|
60
|
-
@config[:db] = db
|
61
|
-
else
|
62
|
-
@config = { host: host, port: port, db: db }
|
63
|
-
end
|
64
|
-
|
65
|
-
@config[:password] = password unless password.nil?
|
66
|
-
@config[:driver] = driver unless driver.nil?
|
67
|
-
|
68
|
-
@config[:connect_timeout] = connect_timeout
|
69
|
-
@config[:read_timeout] = read_timeout
|
70
|
-
@config[:write_timeout] = write_timeout
|
71
|
-
end
|
72
|
-
|
73
|
-
def fetch_client
|
74
|
-
begin
|
75
|
-
@queue.pop(true)
|
76
|
-
rescue
|
77
|
-
increment_created_stat
|
78
|
-
Redis.new(@config)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def clean
|
83
|
-
while @queue.length.positive?
|
84
|
-
client = @queue.pop(true)
|
85
|
-
client.close
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def log_stats
|
90
|
-
return unless @enable_stats == true
|
91
|
-
S1Logging.logger.debug do
|
92
|
-
"[#{self.class}] - REDIS Connection Stats. Process: #{Process.pid} | " \
|
93
|
-
"Created: #{@connections_created} | Pending: #{@queue.length} | In use: #{@connections_in_use}"
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def with_client
|
98
|
-
log_stats
|
99
|
-
begin
|
100
|
-
client = fetch_client
|
101
|
-
increment_using_stat
|
102
|
-
log_stats
|
103
|
-
yield client
|
104
|
-
ensure
|
105
|
-
@queue.push(client)
|
106
|
-
decrement_using_stat
|
107
|
-
log_stats
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# This method is called to set a value within this cache store by it's key.
|
112
|
-
#
|
113
|
-
# @param key [String] This is the unique key to reference the value being set within this cache store.
|
114
|
-
# @param value [Object] This is the value to set within this cache store.
|
115
|
-
# @param expires_in [Integer] This is the number of seconds from the current time that this value should expire.
|
116
|
-
def set(key, value, expires_in = 0)
|
117
|
-
k = build_key(key)
|
118
|
-
|
119
|
-
v = if value.nil? || (value.is_a?(String) && value.strip.empty?)
|
120
|
-
nil
|
121
|
-
else
|
122
|
-
serialize(value)
|
123
|
-
end
|
124
|
-
|
125
|
-
with_client do |client|
|
126
|
-
client.multi do
|
127
|
-
client.set(k, v)
|
128
|
-
|
129
|
-
client.expire(k, expires_in) if expires_in.positive?
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
# This method is called to get a value from this cache store by it's unique key.
|
135
|
-
#
|
136
|
-
# @param key [String] This is the unique key to reference the value to fetch from within this cache store.
|
137
|
-
# @param expires_in [Integer] This is the number of seconds from the current time that this value should expire.
|
138
|
-
# (This is used in conjunction with the block to hydrate the cache key if it is empty.)
|
139
|
-
# @param &block [Block] This block is provided to hydrate this cache store with the value for the request key
|
140
|
-
# when it is not found.
|
141
|
-
# @return [Object] The value for the specified unique key within the cache store.
|
142
|
-
def get(key, expires_in = 0, &block)
|
143
|
-
k = build_key(key)
|
144
|
-
|
145
|
-
value = with_client do |client|
|
146
|
-
client.get(k)
|
147
|
-
end
|
148
|
-
|
149
|
-
if !value.nil? && value.strip.empty?
|
150
|
-
value = nil
|
151
|
-
else
|
152
|
-
value = deserialize(value) unless value.nil?
|
153
|
-
end
|
154
|
-
|
155
|
-
if value.nil? && block_given?
|
156
|
-
value = yield
|
157
|
-
set(key, value, expires_in)
|
158
|
-
end
|
159
|
-
|
160
|
-
value
|
161
|
-
end
|
162
|
-
|
163
|
-
# This method is called to remove a value from this cache store by it's unique key.
|
164
|
-
#
|
165
|
-
# @param key [String] This is the unique key to reference the value to remove from this cache store.
|
166
|
-
def remove(key)
|
167
|
-
with_client do |client|
|
168
|
-
client.del(build_key(key))
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
# This method is called to check if a value exists within this cache store for a specific key.
|
173
|
-
#
|
174
|
-
# @param key [String] This is the unique key to reference the value to check for within this cache store.
|
175
|
-
# @return [Boolean] True or False to specify if the key exists in the cache store.
|
176
|
-
def exist?(key)
|
177
|
-
with_client do |client|
|
178
|
-
client.exists(build_key(key))
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
# Ping the cache store.
|
183
|
-
#
|
184
|
-
# @return [String] `PONG`
|
185
|
-
def ping
|
186
|
-
with_client do |client|
|
187
|
-
client.ping
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
private
|
192
|
-
|
193
|
-
def serialize(object)
|
194
|
-
if RUBY_PLATFORM == 'java'
|
195
|
-
Marshal::dump(object)
|
196
|
-
else
|
197
|
-
Oj.dump(object)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def deserialize(object)
|
202
|
-
if RUBY_PLATFORM == 'java'
|
203
|
-
Marshal::load(object)
|
204
|
-
else
|
205
|
-
Oj.load(object)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def build_key(key)
|
210
|
-
if !@namespace.nil?
|
211
|
-
@namespace + ':' + key.to_s
|
212
|
-
else
|
213
|
-
key.to_s
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
8
|
+
require_relative 'cache_store_redis/redis_cache_store'
|
9
|
+
require_relative 'cache_store_redis/optional_redis_cache_store'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cache_store_redis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- vaughanbrittonsage
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -90,6 +90,8 @@ files:
|
|
90
90
|
- bin/console
|
91
91
|
- bin/setup
|
92
92
|
- lib/cache_store_redis.rb
|
93
|
+
- lib/cache_store_redis/optional_redis_cache_store.rb
|
94
|
+
- lib/cache_store_redis/redis_cache_store.rb
|
93
95
|
- lib/cache_store_redis/version.rb
|
94
96
|
homepage: https://github.com/vaughanbrittonsage/cache_store
|
95
97
|
licenses:
|
@@ -111,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
113
|
version: '0'
|
112
114
|
requirements: []
|
113
115
|
rubyforge_project:
|
114
|
-
rubygems_version: 2.5.1
|
116
|
+
rubygems_version: 2.5.2.1
|
115
117
|
signing_key:
|
116
118
|
specification_version: 4
|
117
119
|
summary: This is the redis cache_store implementation.
|