cache_store_redis 0.5.5-java → 2.3.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfc6c2e6bb1e88dd36e7d6ea2075be4ecb7fe0dfdd9d18bc101417ea00d57daa
4
- data.tar.gz: 6c83cf91258353f0843c8156ae602dcffe25ea7125e40cfa6e7457cefe0ffd65
3
+ metadata.gz: f3c336fa1a5395bdaac8ac631081f502905b13f1fb171d95465e8a0bc26abd57
4
+ data.tar.gz: bfd8b276a84a795cebc0699d1b893f561b26e3c8568d9db92746cc50724f7d46
5
5
  SHA512:
6
- metadata.gz: 33f7b9366d8d1839009c62f582a1a275643a27f7d1d4d5a24444fe520dde352b7f08fd6f4cee0ddeaad0ab12677c1db54de3bce82b166069d53d166868f8ba2a
7
- data.tar.gz: 9ab7c3a42c14fcd1c08afa0fc960d6b39d3b7a4d2eddb7447f4d6f941be66e7f054d5cecc5f8a828fde1fddafa251d319cd600d4d28c2d7b54e399dbf24f583a
6
+ metadata.gz: c7c2d3341798bebd1c89626c0a7c6b901092cd55c09749453c4cf354c453eaebc26008cc222079c09349e09bac4f543781370c89229efeca5a2b9c719c4de7cf
7
+ data.tar.gz: 579efc76097b5f9cea183bf964cb5b0c50a9c5288d22240d01e93361dafe7843e31c6960c7168d30615617303593d6e84807d03366f43e5f6291929623730eec
@@ -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'
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
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-09-26 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: {}
@@ -96,8 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
128
  - !ruby/object:Gem::Version
97
129
  version: '0'
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.