cachext 0.4.2 → 0.5.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: e419955af90b08b1ace8f3cf427e0405ae0bb3a3
4
- data.tar.gz: 5fd6b8a4944d03bc0250e758f51cba8cacab2e5b
3
+ metadata.gz: 5da982260e1706152de87d9c872a5afa37867ce1
4
+ data.tar.gz: 1d079cce845a3f8e0a2af95f86a8be384f8523f6
5
5
  SHA512:
6
- metadata.gz: a6d23554e9c0ae9a0dbf18c19658e9164f9d580cc40ade0c0e85e67bc69df5e6d5713b959f8c0a68c54812249b6538eef8c96472c56ef16a95ea21c1623961b9
7
- data.tar.gz: d34ca43dd664e490f4aae01d4c0e683185a632532445ce45c7495978922bd24fa5910f8d5e64454e2593865cd4d209dedd9e2177aff4d292e6a2ff10575e59c7
6
+ metadata.gz: de945e54a8b4d22408b645383b57b586122041e96c5d35bf29c7dd23402938474f2f85dec7bd43ce8f08034580de10d7f08c7944915a5d0b723a167a57766983
7
+ data.tar.gz: c96fcf677dfd5712994c451e5fb5677b195da74ed74d193e2eac59be93ce691db0e8b5e1b5edae46479930734867ae3353d558a2e1babc95aa01dac7e951a2b8
data/README.md CHANGED
@@ -8,6 +8,7 @@ Extensions to normal Rails caching:
8
8
 
9
9
  * Lock (inspired by https://github.com/seamusabshere/lock_and_cache)
10
10
  * Backup
11
+ * Circuit breaker
11
12
 
12
13
  ## Quickstart
13
14
 
@@ -119,6 +120,19 @@ Cachext.config.error_logger = nil
119
120
 
120
121
  If set to an object that responds to call, will `call` with any errors caught.
121
122
 
123
+ ```ruby
124
+ Cachext.config.failure_threshold = 3
125
+ ```
126
+
127
+ Number of tries before tripping circuit breaker.
128
+
129
+ ```ruby
130
+ Cachext.config.breaker_timeout = 60
131
+ ```
132
+
133
+ Time in seconds to wait before switching breaker to half-open.
134
+
135
+
122
136
  ## Usage
123
137
 
124
138
  ```ruby
@@ -129,11 +143,14 @@ Available options:
129
143
 
130
144
  * `expires_in`: override for the `default_expires_in`, in seconds
131
145
  * `default`: object or proc that will be used as the default if no backup is found
132
- * `errors`: override for the `default_errors` to be caught
133
- * `reraise_errors`: default `true`, if set to `false` NotFound errors will not
134
- be raised
135
- * `not_found_error`: override for `not_found_errors`
136
- * `heartbeat_expires`: override for `heartbeat_expires`
146
+ * `errors`: override for the `default_errors`: array of errors to catch and not reraise
147
+ * `reraise_errors`: default `true`, if set to `false` NotFound errors will not be raised
148
+ * `not_found_error`: (override) array of errors where we delete the backup and reraise
149
+ * `heartbeat_expires`: (override) time in seconds for process heardbeat to expire
150
+ * `failure_threshold`: (override) Number of tries before tripping circuit breaker
151
+ * `breaker_timeout`: (override) time in seconds to wait before switching breaker to half-open
152
+ * `cache`: use the first-level cache, defaults to true. If set to false, will always call the
153
+ fallback, but if an error is raised, will use the last known good value.
137
154
 
138
155
  ```ruby
139
156
  Cachext.multi key_base, ids, options, &block
@@ -15,17 +15,14 @@ Gem::Specification.new do |spec|
15
15
  spec.license = "MIT"
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
- spec.bindir = "exe"
19
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
18
  spec.require_paths = ["lib"]
21
19
 
22
- spec.add_dependency "activesupport", "~> 4.2"
20
+ spec.add_dependency "faraday"
23
21
  spec.add_dependency "redis"
24
- spec.add_dependency "redis-namespace"
25
22
  spec.add_dependency "redlock"
26
- spec.add_dependency "faraday"
27
23
  spec.add_dependency "dalli"
28
24
 
25
+ spec.add_development_dependency "activesupport"
29
26
  spec.add_development_dependency "bundler", "~> 1.10"
30
27
  spec.add_development_dependency "rake", "~> 10.0"
31
28
  spec.add_development_dependency "rspec"
@@ -1,5 +1,4 @@
1
1
  require "cachext/version"
2
- require "faraday/error"
3
2
 
4
3
  module Cachext
5
4
  autoload :Breaker, "cachext/breaker"
@@ -50,7 +49,12 @@ module Cachext
50
49
  end
51
50
 
52
51
  def self.configure &block
52
+ @config_block = block
53
53
  @config = Configuration.setup(&block)
54
54
  @client = Client.new @config
55
55
  end
56
+
57
+ def self.forked!
58
+ configure(&@config_block)
59
+ end
56
60
  end
@@ -21,9 +21,9 @@ module Cachext
21
21
  end
22
22
 
23
23
  def increment_failure
24
- redis.pipelined do
25
- redis.set key_str(:last_failure), Time.now.to_f
26
- redis.incr key_str(:monitor)
24
+ lock_redis.pipelined do
25
+ lock_redis.set key_str(:last_failure), Time.now.to_f
26
+ lock_redis.incr key_str(:monitor)
27
27
  end
28
28
  end
29
29
 
@@ -38,7 +38,7 @@ module Cachext
38
38
  end
39
39
 
40
40
  def reset!
41
- redis.del key_str(:monitor),
41
+ lock_redis.del key_str(:monitor),
42
42
  key_str(:health_check),
43
43
  key_str(:last_failure)
44
44
  end
@@ -62,27 +62,27 @@ module Cachext
62
62
  end
63
63
 
64
64
  def monitor
65
- redis.get(key_str(:monitor)).to_i
65
+ lock_redis.get(key_str(:monitor)).to_i
66
66
  end
67
67
 
68
68
  def last_failure
69
- lf = redis.get key_str(:last_failure)
69
+ lf = lock_redis.get key_str(:last_failure)
70
70
  lf.nil? ? nil : lf.to_f
71
71
  end
72
72
 
73
73
  def health_check
74
- redis.get(key_str(:health_check)).to_i
74
+ lock_redis.get(key_str(:health_check)).to_i
75
75
  end
76
76
 
77
77
  def increment_health_check
78
- redis.incr key_str(:health_check)
78
+ lock_redis.incr key_str(:health_check)
79
79
  end
80
80
 
81
81
  def key_str(name)
82
- "#{name}:#{key.raw.map(&:to_s).join(":")}"
82
+ "cachext:#{name}:#{key.raw.map(&:to_s).join(":")}"
83
83
  end
84
84
 
85
- def redis
85
+ def lock_redis
86
86
  config.lock_redis
87
87
  end
88
88
  end
@@ -50,7 +50,7 @@ module Cachext
50
50
  end
51
51
 
52
52
  def write key, fresh, options
53
- key.write fresh, expires_in: options.expires_in
53
+ key.write fresh, expires_in: options.expires_in if options.cache?
54
54
  end
55
55
  end
56
56
  end
@@ -1,6 +1,6 @@
1
1
  require "redlock"
2
- require "redis-namespace"
3
2
  require "thread"
3
+ require "faraday/error"
4
4
 
5
5
  module Cachext
6
6
  class Configuration
@@ -59,7 +59,7 @@ module Cachext
59
59
  end
60
60
 
61
61
  def lock_redis
62
- @lock_redis ||= Redis::Namespace.new :cachext, redis: redis
62
+ redis
63
63
  end
64
64
 
65
65
  def log_errors?
@@ -69,7 +69,7 @@ module Cachext
69
69
  def debug
70
70
  if block_given?
71
71
  if @debug
72
- @mutex.synchronize do
72
+ @debug_mutex.synchronize do
73
73
  yield
74
74
  end
75
75
  end
@@ -11,7 +11,9 @@ module Cachext
11
11
  def read key, options
12
12
  circuit = breaker.for(key)
13
13
  if circuit.open?
14
- key.read_backup
14
+ val = key.read_backup
15
+ debug_log { { m: :circuit_open, key: key, msg: "Circuit breaker open, reading from backup", val: val.inspect } }
16
+ val
15
17
  else
16
18
  circuit.check_health
17
19
  super
@@ -19,7 +19,7 @@ module Cachext
19
19
  end
20
20
 
21
21
  def call_block key, options, &block
22
- with_heartbeat_extender key.digest, options.heartbeat_expires do
22
+ with_heartbeat_extender key.lock_key, options.heartbeat_expires do
23
23
  super
24
24
  end
25
25
  end
@@ -46,9 +46,9 @@ module Cachext
46
46
  def obtain_lock key, options
47
47
  start_time = Time.now
48
48
 
49
- until lock_info ||= @config.lock_manager.lock(key.digest, (options.heartbeat_expires * 1000).ceil)
49
+ until lock_info ||= @config.lock_manager.lock(key.lock_key, (options.heartbeat_expires * 1000).ceil)
50
50
  if wait_for_lock(key, start_time) == :timeout
51
- lock_info = @config.lock_manager.lock(key.digest, (options.heartbeat_expires * 1000).ceil)
51
+ lock_info = @config.lock_manager.lock(key.lock_key, (options.heartbeat_expires * 1000).ceil)
52
52
  raise TimeoutWaitingForLock unless lock_info
53
53
  end
54
54
  end
@@ -19,8 +19,12 @@ module Cachext
19
19
  [:backup_cache] + raw
20
20
  end
21
21
 
22
+ def lock_key
23
+ "cachext:lock:#{digest}"
24
+ end
25
+
22
26
  def locked?
23
- lock_redis.exists digest
27
+ lock_redis.exists lock_key
24
28
  end
25
29
 
26
30
  def read
@@ -106,7 +106,7 @@ module Cachext
106
106
 
107
107
  def lock_key_from_ids(ids)
108
108
  key = Key.new multi.key_base + ids
109
- key.digest
109
+ key.lock_key
110
110
  end
111
111
 
112
112
  def write_cache records
@@ -1,3 +1,3 @@
1
1
  module Cachext
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,31 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cachext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Donald Plummer
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-19 00:00:00.000000000 Z
11
+ date: 2017-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activesupport
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '4.2'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '4.2'
27
- - !ruby/object:Gem::Dependency
28
- name: redis
14
+ name: faraday
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
17
  - - ">="
@@ -39,7 +25,7 @@ dependencies:
39
25
  - !ruby/object:Gem::Version
40
26
  version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
- name: redis-namespace
28
+ name: redis
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
31
  - - ">="
@@ -67,7 +53,7 @@ dependencies:
67
53
  - !ruby/object:Gem::Version
68
54
  version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
- name: faraday
56
+ name: dalli
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
59
  - - ">="
@@ -81,13 +67,13 @@ dependencies:
81
67
  - !ruby/object:Gem::Version
82
68
  version: '0'
83
69
  - !ruby/object:Gem::Dependency
84
- name: dalli
70
+ name: activesupport
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
73
  - - ">="
88
74
  - !ruby/object:Gem::Version
89
75
  version: '0'
90
- type: :runtime
76
+ type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
@@ -231,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
231
217
  version: '0'
232
218
  requirements: []
233
219
  rubyforge_project:
234
- rubygems_version: 2.4.8
220
+ rubygems_version: 2.5.1
235
221
  signing_key:
236
222
  specification_version: 4
237
223
  summary: Cache with lock and backup extensions