stockpile_cache 1.2.0 → 1.4.0

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: e0cf5948f44622314a97af71ab6ce39aa3f59931092b7ac6d80f424e052be90d
4
- data.tar.gz: bec173c3c11807350c3b4d4cb05f638fc4a90c71837882f7b64931db1dce8416
3
+ metadata.gz: f7be09001963c6971d22e7538448f03c92f4be2d2c63da6cb69d3aaa4708e93e
4
+ data.tar.gz: 6db11eb490fd3387c5e17f5c6c6175cf99cddf0756883d5908ad6353ded57ed9
5
5
  SHA512:
6
- metadata.gz: '08218ce4ab3946ae6b418dd0d72c354170415eff8b041d0e02bbc261ffca83fe4afd7718d9bb7907d2b80093afaeeaa8f83dc57e7b9a7aa4d91c1384ccf965b7'
7
- data.tar.gz: fddd745d31dae1f5509cd3988e216d2fdfe5e520a971e58ef3ede3ed864c5b2e34191abef7b67bfab0115134fa4cdceec43fd404d8d8430c53df931b4f01bde1
6
+ metadata.gz: 3708ba5d7be994cf35b9ac0b98eef2a79b01bead9849234340b1cec61287b09f6e49b273ee87a73ce982d5aa45e61030ce0543664ff3821a0b0d61fadce538e5
7
+ data.tar.gz: 461d4d8adf44a2402f6e9d25338a2a49c52787225108acfd40cf1e2466cf18e1d67051230391d99c1bf14ba25d1792ad14c81cd6239f704831e05f4e95d94659
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.4.0
4
+ - Bump redis-rb dependency to >= 4.2.0
5
+
6
+ ## 1.3.2
7
+ - Fixing bug where cached content was not read
8
+
9
+ ## 1.3.1
10
+ - Parsing ERB in YAML configs
11
+ - Fill in missing README about cache expiration
12
+
13
+ ## 1.3.0
14
+ - Allowing optional compression of cached content
15
+
3
16
  ## 1.2.0
4
17
  - Adding support for multiple Redis databases/server
5
18
 
data/Gemfile.lock CHANGED
@@ -1,26 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stockpile_cache (1.2.0)
4
+ stockpile_cache (1.4.0)
5
5
  connection_pool
6
6
  oj
7
7
  rake
8
- redis
8
+ redis (>= 4.2.0)
9
9
 
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
13
  ast (2.4.0)
14
- connection_pool (2.2.2)
14
+ connection_pool (2.2.5)
15
15
  diff-lcs (1.3)
16
16
  jaro_winkler (1.5.3)
17
- oj (3.9.2)
17
+ oj (3.13.9)
18
18
  parallel (1.17.0)
19
19
  parser (2.6.4.1)
20
20
  ast (~> 2.4.0)
21
21
  rainbow (3.0.0)
22
- rake (13.0.1)
23
- redis (4.1.3)
22
+ rake (13.0.6)
23
+ redis (4.4.0)
24
24
  rspec (3.8.0)
25
25
  rspec-core (~> 3.8.0)
26
26
  rspec-expectations (~> 3.8.0)
@@ -53,4 +53,4 @@ DEPENDENCIES
53
53
  stockpile_cache!
54
54
 
55
55
  BUNDLED WITH
56
- 2.0.2
56
+ 2.1.4
data/README.md CHANGED
@@ -91,6 +91,12 @@ end
91
91
  | `db` | (optional) Name of the Redis database to cache value in. Defaults to `:default` |
92
92
  | `&block` | Block of code to execute; it's return value will be stored in cache. |
93
93
 
94
+ To expire your cache immediately run:
95
+
96
+ ```
97
+ Stockpile.expire_cached(key: 'meaning_of_life')
98
+ ```
99
+
94
100
  ### Multiple Database
95
101
  Stockpile comes with a support for multiple databases. A word of caution: unless
96
102
  you have very good reason to run multiple databases within single instance of
@@ -149,6 +155,44 @@ Using `configuration_file` setting will make Stockpile ignore all other
149
155
  Redis connection related settings and it will read configuration from `.yml`
150
156
  file instead.
151
157
 
158
+ ### Compression of Cached Content
159
+ Stockpile optionally supports compression of cached content; you will not see
160
+ much benefit from compressing small strings but once you start caching bigger
161
+ payloads like fragments of HTML you could see some improvements by using
162
+ compression. To use compression you will have to use configuration file set by
163
+ `STOCKPILE_CONFIGURATION_FILE`.
164
+
165
+ To enable compression you have to do two things. First you have to set
166
+ `configuration_file` setting to point at `.yml` containing your configuration.
167
+ You can do so by either setting a `STOCKPILE_CONFIGURATION_FILE` environment
168
+ variable or by executing a configuration block during runtime (for Rails create
169
+ `config/initializers/stockpile.rb` with following content):
170
+
171
+ ```
172
+ Stockpile.configure do |configuration|
173
+ configuration.configuration_file = <PATH/TO/FILE>
174
+ end
175
+ ```
176
+
177
+ Second thing to do is to create a `.yml` configuration file. It has to have at
178
+ least one database definition. Providing `sentinels` and `compression` is
179
+ optional. Everything else is mandatory:
180
+
181
+
182
+ ```
183
+ ---
184
+ master:
185
+ url: 'redis://redis-1-host:6379/1'
186
+ sentinels: '8.8.8.8:42,8.8.4.4:42'
187
+ compression: true
188
+ pool_options:
189
+ size: 5
190
+ timeout: 5
191
+ ```
192
+
193
+ From that point everything that will be cached in `master` database will be
194
+ compressed.
195
+
152
196
  ## Caveats
153
197
  There is no timeout or rescue set for code you will be running through the cache. If
154
198
  you need to do either you have to handle it outside of Stockpile.
@@ -22,21 +22,32 @@ module Stockpile
22
22
  module Cache
23
23
  module_function
24
24
 
25
- def get(db: :default, key:)
25
+ def get(db: :default, key:, compress: false)
26
26
  value_from_cache = Stockpile.redis(db: db) { |r| r.get(key) }
27
- Oj.load(value_from_cache) if value_from_cache
27
+
28
+ return unless value_from_cache
29
+
30
+ if compress && value_from_cache
31
+ Oj.load(Zlib::Inflate.inflate(Base64.decode64(value_from_cache)))
32
+ else
33
+ Oj.load(value_from_cache)
34
+ end
28
35
  end
29
36
 
30
- def get_deferred(db: :default, key:)
31
- sleep(Stockpile::SLUMBER_COOLDOWN) until Stockpile.redis(db: db) { |r| r.exists(key) }
32
- value_from_cache = Stockpile.redis(db: db) { |r| r.get(key) }
33
- Oj.load(value_from_cache)
37
+ def get_deferred(db: :default, key:, compress: false)
38
+ sleep(Stockpile::SLUMBER_COOLDOWN) until Stockpile.redis(db: db) { |r| r.exists?(key) }
39
+
40
+ get(db: db, key: key, compress: compress)
34
41
  end
35
42
 
36
- def set(db: :default, key:, payload:, ttl:)
37
- payload = Oj.dump(payload)
38
- Stockpile.redis(db: db) { |r| r.set(key, payload) }
39
- Stockpile.redis(db: db) { |r| r.expire(key, ttl) }
43
+ def set(db: :default, key:, payload:, ttl:, compress: false)
44
+ payload = if compress
45
+ Base64.encode64(Zlib::Deflate.deflate(Oj.dump(payload)))
46
+ else
47
+ Oj.dump(payload)
48
+ end
49
+
50
+ Stockpile.redis(db: db) { |r| r.setex(key, ttl, payload) }
40
51
  end
41
52
  end
42
53
  end
@@ -23,7 +23,7 @@ module Stockpile
23
23
  module_function
24
24
 
25
25
  def read_or_yield(db: :default, key:, ttl:, &block)
26
- if (result = Stockpile::Cache.get(db: db, key: key))
26
+ if (result = Stockpile::Cache.get(db: db, key: key, compress: RedisConnections.compression?(db: db)))
27
27
  result
28
28
  else
29
29
  Stockpile::Executor.perform(db: db, key: key, ttl: ttl, &block)
@@ -23,5 +23,5 @@ module Stockpile
23
23
  DEFAULT_TTL = 60 * 5
24
24
  LOCK_PREFIX = 'stockpile_lock::'
25
25
  SLUMBER_COOLDOWN = 0.05
26
- VERSION = '1.2.0'
26
+ VERSION = '1.4.0'
27
27
  end
@@ -44,6 +44,10 @@ module Stockpile
44
44
 
45
45
  private
46
46
 
47
+ def compress?
48
+ RedisConnections.compression?(db: db)
49
+ end
50
+
47
51
  def execution
48
52
  @execution ||= Stockpile::Lock.perform_locked(db: db, lock_key: lock_key) do
49
53
  yield
@@ -55,7 +59,8 @@ module Stockpile
55
59
  db: db,
56
60
  key: key,
57
61
  payload: execution.result,
58
- ttl: ttl
62
+ ttl: ttl,
63
+ compress: compress?
59
64
  )
60
65
 
61
66
  execution.release_lock
@@ -68,7 +73,7 @@ module Stockpile
68
73
 
69
74
  def wait_for_cache_or_yield
70
75
  Timeout.timeout(Stockpile.configuration.slumber) do
71
- Stockpile::Cache.get_deferred(db: db, key: key)
76
+ Stockpile::Cache.get_deferred(db: db, key: key, compress: compress?)
72
77
  end
73
78
  rescue Timeout::Error
74
79
  yield
@@ -22,6 +22,10 @@ module Stockpile
22
22
  module RedisConnections
23
23
  module_function
24
24
 
25
+ def compression?(db:)
26
+ instance_variable_get("@#{db}_compression".to_sym)
27
+ end
28
+
25
29
  def with(db:)
26
30
  instance_variable_get("@#{db}".to_sym).with do |connection|
27
31
  yield connection
@@ -29,10 +29,8 @@ module Stockpile
29
29
  Redis.new(database[:redis_configuration])
30
30
  end
31
31
 
32
- RedisConnections.instance_variable_set(
33
- "@#{database[:db]}".to_sym,
34
- pool
35
- )
32
+ RedisConnections.instance_variable_set("@#{database[:db]}".to_sym, pool)
33
+ RedisConnections.instance_variable_set("@#{database[:db]}_compression".to_sym, database[:compression])
36
34
  end
37
35
 
38
36
  RedisConnections
@@ -27,11 +27,18 @@ module Stockpile
27
27
  {
28
28
  db: database,
29
29
  pool_configuration: extract_pool(settings: settings),
30
- redis_configuration: extract_redis(settings: settings)
30
+ redis_configuration: extract_redis(settings: settings),
31
+ compression: extract_compression(settings: settings)
31
32
  }
32
33
  end
33
34
  end
34
35
 
36
+ def extract_compression(settings:)
37
+ return true if settings['compression'].eql?(true)
38
+
39
+ false
40
+ end
41
+
35
42
  def extract_redis(settings:)
36
43
  sentinels = Stockpile::RedisConnectionsFactory.process_sentinels(
37
44
  sentinels: settings['sentinels'] || ''
@@ -51,7 +58,11 @@ module Stockpile
51
58
  end
52
59
 
53
60
  def parsed_configuration
54
- YAML.safe_load(raw_configuration)
61
+ YAML.safe_load(
62
+ ERB.new(
63
+ raw_configuration
64
+ ).result
65
+ )
55
66
  end
56
67
 
57
68
  def raw_configuration
data/lib/stockpile.rb CHANGED
@@ -14,11 +14,13 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
+ require 'base64'
17
18
  require 'connection_pool'
18
19
  require 'oj'
19
20
  require 'redis'
20
21
  require 'timeout'
21
22
  require 'yaml'
23
+ require 'zlib'
22
24
 
23
25
  require 'stockpile/constants'
24
26
  require 'stockpile/configuration'
@@ -25,5 +25,5 @@ Gem::Specification.new do |spec|
25
25
  spec.add_dependency 'connection_pool'
26
26
  spec.add_dependency 'oj'
27
27
  spec.add_dependency 'rake'
28
- spec.add_dependency 'redis'
28
+ spec.add_dependency 'redis', '>= 4.2.0'
29
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stockpile_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ConvertKit, LLC
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-28 00:00:00.000000000 Z
11
+ date: 2021-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: connection_pool
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 4.2.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: 4.2.0
69
69
  description: Simple redis based cache with stampede protection
70
70
  email:
71
71
  - engineering@convertkit.com
@@ -123,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  requirements: []
126
- rubygems_version: 3.0.3
126
+ rubygems_version: 3.1.4
127
127
  signing_key:
128
128
  specification_version: 4
129
129
  summary: Redis based cache