cache_store_redis 0.5.5-java → 2.3.0.rc3-java

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
  SHA256:
3
- metadata.gz: dfc6c2e6bb1e88dd36e7d6ea2075be4ecb7fe0dfdd9d18bc101417ea00d57daa
4
- data.tar.gz: 6c83cf91258353f0843c8156ae602dcffe25ea7125e40cfa6e7457cefe0ffd65
3
+ metadata.gz: bcd6deebd0a5218acfe216ff3d4862ed618ada2113a0321f5c9cea74388cc705
4
+ data.tar.gz: fe2b1bf505d8217eea0abc5794c23edaf98fa2c1a2cfe18704cdb7905e3f7e20
5
5
  SHA512:
6
- metadata.gz: 33f7b9366d8d1839009c62f582a1a275643a27f7d1d4d5a24444fe520dde352b7f08fd6f4cee0ddeaad0ab12677c1db54de3bce82b166069d53d166868f8ba2a
7
- data.tar.gz: 9ab7c3a42c14fcd1c08afa0fc960d6b39d3b7a4d2eddb7447f4d6f941be66e7f054d5cecc5f8a828fde1fddafa251d319cd600d4d28c2d7b54e399dbf24f583a
6
+ metadata.gz: d89b13c62ca6b6b71d1589f056f65b883b5d250abf7e2d146e89411c0567bc3240d8384ac1478dfdbf22804c602469e880a143c77d0ef65a2a83577fc6101ae6
7
+ data.tar.gz: 7c565db2efc21a7deccea7529e283bdd0dc9813809501220f23bce9f36dd825a296df499fc781a3708ac376a43eaa3908b217cd28a850f22fd64697626202073
@@ -0,0 +1,100 @@
1
+ # This class is used to define a redis cache store that logs failures as warnings but does not raise errors for
2
+ # cache connections
3
+ class OptionalRedisCacheStore
4
+ def initialize(namespace: nil, config: nil, logger: nil)
5
+ @cache_store = RedisCacheStore.new(namespace, config)
6
+ @logger = logger || Logger.new(STDOUT)
7
+ end
8
+
9
+ def redis_store
10
+ @cache_store
11
+ end
12
+
13
+ # This method is called to configure the connection to the cache store.
14
+ def configure(
15
+ host = 'localhost',
16
+ port = 6379,
17
+ db = 'default',
18
+ password = nil,
19
+ driver: nil,
20
+ url: nil,
21
+ connect_timeout: 0.5,
22
+ read_timeout: 1,
23
+ write_timeout: 0.5)
24
+ redis_store.configure(
25
+ host,
26
+ port,
27
+ db,
28
+ password,
29
+ driver: driver,
30
+ url: url,
31
+ connect_timeout: connect_timeout,
32
+ read_timeout: read_timeout,
33
+ write_timeout: write_timeout
34
+ )
35
+ end
36
+
37
+ def optional_get(key, expires_in = 0)
38
+ redis_store.get(key, expires_in)
39
+ rescue => e
40
+ handle_error(e, 'requesting data from the cache')
41
+ nil
42
+ end
43
+
44
+ def get(key, expires_in = 0, &block)
45
+ value = optional_get(key, expires_in)
46
+
47
+ if value.nil? && block_given?
48
+ value = yield
49
+ set(key, value, expires_in)
50
+ end
51
+
52
+ value
53
+ end
54
+
55
+ def set(key, value, expires_in = 0)
56
+ redis_store.set(key, value, expires_in)
57
+ rescue => e
58
+ handle_error(e, 'storing data in the cache')
59
+ end
60
+
61
+ def remove(key)
62
+ redis_store.remove(key)
63
+ rescue => e
64
+ handle_error(e, 'removing data from the cache')
65
+ end
66
+
67
+ def exist?(key)
68
+ redis_store.exist?(key)
69
+ rescue => e
70
+ handle_error(e, 'checking if a key exists in the cache')
71
+ false
72
+ end
73
+
74
+ def ping
75
+ redis_store.ping
76
+ rescue => e
77
+ handle_error(e, 'pinging the cache')
78
+ false
79
+ end
80
+
81
+ def shutdown
82
+ redis_store.shutdown
83
+ rescue => e
84
+ handle_error(e, 'shutting down the connection pool')
85
+ false
86
+ end
87
+
88
+ alias read get
89
+ alias write set
90
+ alias delete remove
91
+
92
+ private
93
+
94
+ def handle_error(ex, msg)
95
+ @logger.error do
96
+ "[#{self.class}] - An error occurred #{msg}. " \
97
+ "Error: #{ex.message} | Backtrace: #{ex.backtrace}"
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,172 @@
1
+ # This class is used to implement a redis cache store.
2
+ class RedisCacheStore
3
+ # Default expiry time if not provided. (1 hour)
4
+ DEFAULT_TTL = 3_600
5
+
6
+ def initialize(namespace = nil, config = nil)
7
+ unless RUBY_PLATFORM == 'java'
8
+ require 'oj'
9
+ end
10
+
11
+ @connection_pool = RedisConnectionPool.new(namespace, config)
12
+
13
+ @namespace = namespace
14
+ @config = config
15
+
16
+ @connections_created = 0
17
+ @connections_in_use = 0
18
+ @mutex = Mutex.new
19
+ @enable_stats = false
20
+ end
21
+
22
+ attr_reader :connection_pool
23
+
24
+ # This method is called to configure the connection to the cache store.
25
+ def configure(host = 'localhost',
26
+ port = 6379,
27
+ db = 0,
28
+ password = nil,
29
+ driver: nil,
30
+ url: nil,
31
+ connect_timeout: 0.5,
32
+ read_timeout: 1,
33
+ write_timeout: 0.5)
34
+ if !url.nil?
35
+ @config = {}
36
+ @config[:url] = url
37
+ @config[:db] = db
38
+ else
39
+ @config = { host: host, port: port, db: db }
40
+ end
41
+
42
+ @config[:password] = password unless password.nil?
43
+ @config[:driver] = driver unless driver.nil?
44
+
45
+ @config[:connect_timeout] = connect_timeout
46
+ @config[:read_timeout] = read_timeout
47
+ @config[:write_timeout] = write_timeout
48
+ connection_pool.config = @config
49
+ end
50
+
51
+ def clean
52
+ connection_pool.shutdown
53
+ end
54
+ alias shutdown clean
55
+
56
+ def with_client(&block)
57
+ connection_pool.with_connection(&block)
58
+ end
59
+
60
+ # This method is called to set a value within this cache store by it's key.
61
+ #
62
+ # @param key [String] This is the unique key to reference the value being set within this cache store.
63
+ # @param value [Object] This is the value to set within this cache store.
64
+ # @param expires_in [Integer] This is the number of seconds from the current time that this value should expire.
65
+ def set(key, value, expires_in = DEFAULT_TTL)
66
+ k = build_key(key)
67
+
68
+ v = if value.nil? || (value.is_a?(String) && value.strip.empty?)
69
+ nil
70
+ else
71
+ serialize(value)
72
+ end
73
+
74
+ expiry_int = Integer(expires_in)
75
+ expire_value = expiry_int.positive? ? expiry_int : Integer(DEFAULT_TTL)
76
+
77
+ with_client do |client|
78
+ client.multi do
79
+ client.set(k, v)
80
+
81
+ client.expire(k, expire_value)
82
+ end
83
+ end
84
+ end
85
+
86
+ # This method is called to get a value from this cache store by it's unique key.
87
+ #
88
+ # @param key [String] This is the unique key to reference the value to fetch from within this cache store.
89
+ # @param expires_in [Integer] This is the number of seconds from the current time that this value should expire.
90
+ # (This is used in conjunction with the block to hydrate the cache key if it is empty.)
91
+ # @param &block [Block] This block is provided to hydrate this cache store with the value for the request key
92
+ # when it is not found.
93
+ # @return [Object] The value for the specified unique key within the cache store.
94
+ def get(key, expires_in = 0)
95
+ k = build_key(key)
96
+
97
+ value = with_client do |client|
98
+ client.get(k)
99
+ end
100
+
101
+ if !value.nil? && value.strip.empty?
102
+ value = nil
103
+ else
104
+ value = deserialize(value) unless value.nil?
105
+ end
106
+
107
+ if value.nil? && block_given?
108
+ value = yield
109
+ set(key, value, expires_in)
110
+ end
111
+
112
+ value
113
+ end
114
+
115
+ # This method is called to remove a value from this cache store by it's unique key.
116
+ #
117
+ # @param key [String] This is the unique key to reference the value to remove from this cache store.
118
+ def remove(key)
119
+ with_client do |client|
120
+ client.del(build_key(key))
121
+ end
122
+ end
123
+
124
+ # This method is called to check if a value exists within this cache store for a specific key.
125
+ #
126
+ # @param key [String] This is the unique key to reference the value to check for within this cache store.
127
+ # @return [Boolean] True or False to specify if the key exists in the cache store.
128
+ def exist?(key)
129
+ with_client do |client|
130
+ !client.exists(build_key(key)).zero?
131
+ end
132
+ end
133
+
134
+ # Ping the cache store.
135
+ #
136
+ # @return [String] `PONG`
137
+ def ping
138
+ with_client do |client|
139
+ client.ping
140
+ end
141
+ end
142
+
143
+ alias write set
144
+ alias read get
145
+ alias delete remove
146
+
147
+ private
148
+
149
+ def serialize(object)
150
+ if RUBY_PLATFORM == 'java'
151
+ Marshal::dump(object)
152
+ else
153
+ Oj.dump(object)
154
+ end
155
+ end
156
+
157
+ def deserialize(object)
158
+ if RUBY_PLATFORM == 'java'
159
+ Marshal::load(object)
160
+ else
161
+ Oj.load(object)
162
+ end
163
+ end
164
+
165
+ def build_key(key)
166
+ if !@namespace.nil?
167
+ @namespace + ':' + key.to_s
168
+ else
169
+ key.to_s
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,29 @@
1
+ class RedisConnection
2
+ attr_accessor :created
3
+ attr_accessor :client
4
+
5
+ def initialize(config)
6
+ self.client = Redis.new(config)
7
+ self.created = Time.now
8
+ end
9
+
10
+ # This method is called to determine if this connection has been open for longer than the keep alive timeout or not.
11
+ def expired?
12
+ return false if self.created.nil?
13
+ Time.now >= (self.created + keep_alive_timeout)
14
+ end
15
+
16
+ def open
17
+ self.created = Time.now if self.created.nil?
18
+ end
19
+
20
+ def close
21
+ self.client.close
22
+ self.created = nil
23
+ end
24
+
25
+ # This method is called to get the keep alive timeout value to use for this connection.
26
+ def keep_alive_timeout
27
+ Float(ENV['REDIS_KEEP_ALIVE_TIMEOUT'] || 30)
28
+ end
29
+ end
@@ -0,0 +1,84 @@
1
+ # This class is used to define a pool of re-usable redis connections.
2
+ class RedisConnectionPool
3
+ attr_accessor :config
4
+
5
+ def initialize(namespace = nil, config = nil)
6
+ @namespace = namespace
7
+ @config = config
8
+ @queue = Queue.new
9
+ @connections = []
10
+ @mutex = Mutex.new
11
+ @monitor_thread = Thread.new do
12
+ loop do
13
+ sleep(1)
14
+ @mutex.synchronize do
15
+ connections.select { |con| con.expired? }.each do |con|
16
+ con.close
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ # This method is called to get the namespace for redis keys.
24
+ def namespace
25
+ @namespace
26
+ end
27
+
28
+ # This method is called to get the idle connection queue for this pool.
29
+ def queue
30
+ @queue
31
+ end
32
+
33
+ # This method is called to fetch a connection from the queue or create a new connection if no idle connections
34
+ # are available.
35
+ def fetch_connection
36
+ queue.pop(true)
37
+ rescue
38
+ RedisConnection.new(config)
39
+ end
40
+
41
+ # This method is called to checkout a connection from the pool before use.
42
+ def check_out
43
+ connection = nil
44
+ @mutex.synchronize do
45
+ connection = fetch_connection
46
+ connections.delete(connection)
47
+ connection.open
48
+ end
49
+ connection
50
+ end
51
+
52
+ # This method is called to checkin a connection to the pool after use.
53
+ def check_in(connection)
54
+ if connection.expired?
55
+ connection.close
56
+ end
57
+ @mutex.synchronize do
58
+ connections.push(connection)
59
+ queue.push(connection)
60
+ end
61
+ end
62
+
63
+ # This method is called to use a connection from this pool.
64
+ def with_connection
65
+ connection = check_out
66
+ return yield connection.client
67
+ ensure
68
+ check_in(connection)
69
+ end
70
+
71
+ # This method is called to get an array of idle connections in this pool.
72
+ def connections
73
+ @connections
74
+ end
75
+
76
+ def shutdown
77
+ connections.each do |con|
78
+ con.client.close
79
+ end
80
+ @connections = []
81
+ @monitor_thread.kill
82
+ @queue = Queue.new
83
+ end
84
+ end
@@ -1,3 +1,3 @@
1
1
  module CacheStoreRedis
2
- VERSION = '0.5.5'
2
+ VERSION = '2.3.0.rc3'
3
3
  end
@@ -4,213 +4,9 @@ require 'thread'
4
4
  require 'cache_store_redis/version'
5
5
  require 'redis'
6
6
  require 'securerandom'
7
+ require 'logger'
7
8
 
8
- # This class is used to implement a redis cache store.
9
- class RedisCacheStore
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
9
+ require_relative 'cache_store_redis/redis_connection'
10
+ require_relative 'cache_store_redis/redis_connection_pool'
11
+ require_relative 'cache_store_redis/redis_cache_store'
12
+ require_relative 'cache_store_redis/optional_redis_cache_store'
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cache_store_redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5
4
+ version: 2.3.0.rc3
5
5
  platform: java
6
6
  authors:
7
7
  - vaughanbrittonsage
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-01-26 00:00:00.000000000 Z
11
+ date: 2024-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '1.11'
18
+ version: '0'
19
19
  name: bundler
20
- prerelease: false
21
20
  type: :development
21
+ prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.11'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
@@ -31,8 +31,8 @@ dependencies:
31
31
  - !ruby/object:Gem::Version
32
32
  version: '10.0'
33
33
  name: rake
34
- prerelease: false
35
34
  type: :development
35
+ prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
@@ -41,17 +41,45 @@ dependencies:
41
41
  - !ruby/object:Gem::Dependency
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "~>"
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: '3.0'
46
+ version: '0'
47
47
  name: rspec
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ name: simplecov
62
+ type: :development
48
63
  prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ name: timecop
49
76
  type: :development
77
+ prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
- - - "~>"
80
+ - - ">="
53
81
  - !ruby/object:Gem::Version
54
- version: '3.0'
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  requirement: !ruby/object:Gem::Requirement
57
85
  requirements:
@@ -59,8 +87,8 @@ dependencies:
59
87
  - !ruby/object:Gem::Version
60
88
  version: '0'
61
89
  name: redis
62
- prerelease: false
63
90
  type: :runtime
91
+ prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
94
  - - ">="
@@ -76,8 +104,12 @@ files:
76
104
  - bin/console
77
105
  - bin/setup
78
106
  - lib/cache_store_redis.rb
107
+ - lib/cache_store_redis/optional_redis_cache_store.rb
108
+ - lib/cache_store_redis/redis_cache_store.rb
109
+ - lib/cache_store_redis/redis_connection.rb
110
+ - lib/cache_store_redis/redis_connection_pool.rb
79
111
  - lib/cache_store_redis/version.rb
80
- homepage: https://github.com/vaughanbrittonsage/cache_store
112
+ homepage: https://github.com/sage/cache_store
81
113
  licenses:
82
114
  - MIT
83
115
  metadata: {}
@@ -92,12 +124,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
124
  version: '0'
93
125
  required_rubygems_version: !ruby/object:Gem::Requirement
94
126
  requirements:
95
- - - ">="
127
+ - - ">"
96
128
  - !ruby/object:Gem::Version
97
- version: '0'
129
+ version: 1.3.1
98
130
  requirements: []
99
- rubyforge_project:
100
- rubygems_version: 2.7.3
131
+ rubygems_version: 3.3.26
101
132
  signing_key:
102
133
  specification_version: 4
103
134
  summary: This is the redis cache_store implementation.