readthis 0.5.0 → 0.5.1

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
  SHA1:
3
- metadata.gz: d1763594017ac9b87a099ca476d01c9f3823a0b0
4
- data.tar.gz: 23e9363a5cc0c997c70f923f0ea21c50477843ff
3
+ metadata.gz: 39c546b2720bf3e983c15c8fe9d7a60fea06cf75
4
+ data.tar.gz: 0a41d522ce9f5a096bf967a344d3e71ab1c01b56
5
5
  SHA512:
6
- metadata.gz: 0c3868ec4afab92154c4a9bc542de628224086760a6c8c5275d9ba83ede290b4800f209eb3c3b5349d11cd2f2f63e0aa5858e587308ac9d2988ecc6a35989511
7
- data.tar.gz: 3ffd2cc9546da805453a27d5ca33a4a35525582eb7905973a45293e4093ed47c70ebe37b4e3fb8f16035074cb558de08e271b2de712b8f52e237a8f386db9ca3
6
+ metadata.gz: 669ad6115ac86b13bb8ff8108a839d6c9890fbf4ca456ee8bd5f06dfe53578532559a8507a9cdd8a7ed7458341def6acee7e7e051b479fef2828c3312b0f32b8
7
+ data.tar.gz: 15ebfbe02678355846db403aa48b800212aeb5115c05b3b14107ba603db2e74445403ad24988b2161eaff7c5d8e0662b8c7fa1bab2a0927f290ccbf943fa5648
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## v0.5.1 2014-12-30
2
+
3
+ - Fixed: The `clear` method now accepts an argument for compatibility with other
4
+ caches. The argument is not actually used for anything.
5
+ - Changed: The `delete` method will always return a boolean value rather than an
6
+ integer.
7
+ - Changed: Avoid multiple instrumentation calls and pool checkouts within
8
+ `fetch_multi` calls.
9
+
1
10
  ## v0.5.0 2014-12-12
2
11
 
3
12
  - Added: All read and write operations are marshalled to and from storage. This
data/PERFORMANCE.md CHANGED
@@ -1,4 +1,4 @@
1
- Results from the various benchmarks in `./bencharks`. Hardware doesnt't matter
1
+ Results from the various benchmarks in `./bencharks`. Hardware doesn't matter
2
2
  much, as we're simply looking for a comparison against other libraries and prior
3
3
  verions.
4
4
 
data/README.md CHANGED
@@ -7,10 +7,14 @@
7
7
 
8
8
  Readthis is a drop in replacement for any ActiveSupport compliant cache, but
9
9
  emphasizes performance and simplicity. It takes some cues from Dalli (connection
10
- pooling), the popular Memcache client. Below are some performance comparisons
11
- against the only other notable redis cache implementation, `redis-activesupport`,
12
- which has been abandoned and doesn't actually comply to Rails 4.2 cache store
13
- behavior for `fetch_multi`.
10
+ pooling), the popular Memcache client.
11
+
12
+ For any new projects there isn't any reason to stick with Memcached. Redis is
13
+ as fast, if not faster in many scenarios, and is far more likely to be used
14
+ elsewhere in the stack. See [this Stack Overflow post][stackoverflow] for more
15
+ details.
16
+
17
+ [stackoverflow]: http://stackoverflow.com/questions/10558465/memcache-vs-redis
14
18
 
15
19
  ## Footprint & Performance
16
20
 
@@ -52,6 +56,8 @@ redis database, which defaults to 0. For example, using database 2:
52
56
  REDIS_URL=redis://localhost:6379/2
53
57
  ```
54
58
 
59
+ [store]: http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html
60
+
55
61
  ### Compression
56
62
 
57
63
  Compression can be enabled for all actions by passing the `compress` flag. By
@@ -72,7 +78,7 @@ config.cache_store = :readthis_store, ENV.fetch('REDIS_URL'), {
72
78
 
73
79
  Readthis uses Ruby's `Marshal` module for dumping and loading all values by
74
80
  default. This isn't always the fastest option, depending on your use case it may
75
- be desirable to use a faster but more flexible marshaller.
81
+ be desirable to use a faster but less flexible marshaller.
76
82
 
77
83
  Use Oj for JSON marshalling, extremely fast, limited types:
78
84
 
@@ -93,5 +99,3 @@ Readthis supports all of standard cache methods except for the following:
93
99
  * `cleanup` - redis does this with ttl for us already
94
100
  * `delete_matched` - you really don't want to perform key matching operations
95
101
  in redis. They are linear time and only support basic globbing.
96
-
97
- [store]: http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html
data/benchmarks/multi.rb CHANGED
@@ -5,10 +5,12 @@ Bundler.setup
5
5
  require 'benchmark/ips'
6
6
  require 'dalli'
7
7
  require 'redis-activesupport'
8
+ require 'active_support/cache/memory_store'
8
9
  require 'active_support/cache/dalli_store'
9
10
  require 'readthis'
10
11
 
11
12
  REDIS_URL = 'redis://localhost:6379/11'
13
+ memory = ActiveSupport::Cache::MemoryStore.new(expires_in: 60, namespace: 'mm')
12
14
  dalli = ActiveSupport::Cache::DalliStore.new('localhost', namespace: 'da', pool_size: 5, expires_in: 60)
13
15
  redisas = ActiveSupport::Cache::RedisStore.new(REDIS_URL + '/ra', expires_in: 60)
14
16
  readthis = Readthis::Cache.new(REDIS_URL, namespace: 'rd', expires_in: 60)
@@ -16,12 +18,17 @@ readthis = Readthis::Cache.new(REDIS_URL, namespace: 'rd', expires_in: 60)
16
18
  ('a'..'z').each do |key|
17
19
  value = key * 1024
18
20
 
21
+ memory.write(key, value)
19
22
  dalli.write(key, value)
20
23
  readthis.write(key, value)
21
24
  redisas.write(key, value)
22
25
  end
23
26
 
24
27
  Benchmark.ips do |x|
28
+ x.report 'memory:read-multi' do
29
+ memory.read_multi(*('a'..'z'))
30
+ end
31
+
25
32
  x.report 'readthis:read-multi' do
26
33
  readthis.read_multi(*('a'..'z'))
27
34
  end
@@ -38,6 +45,10 @@ Benchmark.ips do |x|
38
45
  end
39
46
 
40
47
  Benchmark.ips do |x|
48
+ x.report 'memory:fetch-multi' do
49
+ memory.fetch_multi(*('a'..'z')) { |_| 'missing' }
50
+ end
51
+
41
52
  x.report 'readthis:fetch-multi' do
42
53
  readthis.fetch_multi(*('a'..'z')) { |_| 'missing' }
43
54
  end
@@ -75,22 +75,41 @@ module Readthis
75
75
  end
76
76
  end
77
77
 
78
+ # Writes data to the cache using the given key. Will overwrite whatever
79
+ # value is already stored at that key.
80
+ #
81
+ # @param [String] Key for lookup
82
+ # @param [Hash] Optional overrides
83
+ #
84
+ # @example
85
+ #
86
+ # cache.write('some-key', 'a bunch of text') # => 'OK'
87
+ # cache.write('some-key', 'short lived', expires_in: 60) # => 'OK'
88
+ # cache.write('some-key', 'lives elsehwere', namespace: 'cache') # => 'OK'
89
+ #
78
90
  def write(key, value, options = {})
79
- options = merged_options(options)
80
- namespaced = namespaced_key(key, options)
91
+ options = merged_options(options)
81
92
 
82
93
  invoke(:write, key) do |store|
83
- if expiration = options[:expires_in]
84
- store.setex(namespaced, expiration, entity.dump(value))
85
- else
86
- store.set(namespaced, entity.dump(value))
87
- end
94
+ write_entity(key, value, store, options)
88
95
  end
89
96
  end
90
97
 
98
+ # Delete the value stored at the specified key. Returns `true` if
99
+ # anything was deleted, `false` otherwise.
100
+ #
101
+ # @params [String] The key for lookup
102
+ # @params [Hash] Optional overrides
103
+ #
104
+ # @example
105
+ #
106
+ # cache.delete('existing-key') # => true
107
+ # cache.delete('random-key') # => false
91
108
  def delete(key, options = {})
109
+ namespaced = namespaced_key(key, merged_options(options))
110
+
92
111
  invoke(:delete, key) do |store|
93
- store.del(namespaced_key(key, merged_options(options)))
112
+ store.del(namespaced) > 0
94
113
  end
95
114
  end
96
115
 
@@ -162,9 +181,20 @@ module Readthis
162
181
  # and filling in any cache misses. All read and write operations are
163
182
  # executed atomically.
164
183
  #
184
+ # @overload fetch_multi(keys)
185
+ # Return all values fro the given keys, applying the block to the key
186
+ # when a value is missing.
187
+ # @param [String] One or more keys to fetch
188
+ #
189
+ # @example
190
+ #
165
191
  # cache.fetch_multi('alpha', 'beta') do |key|
166
192
  # "#{key}-was-missing"
167
193
  # end
194
+ #
195
+ # cache.fetch_multi('a', 'b', expires_in: 60) do |key|
196
+ # key * 2
197
+ # end
168
198
  def fetch_multi(*keys)
169
199
  results = read_multi(*keys)
170
200
  options = merged_options(extract_options!(keys))
@@ -173,8 +203,8 @@ module Readthis
173
203
  store.pipelined do
174
204
  results.each do |key, value|
175
205
  if value.nil?
176
- value = yield key
177
- write(key, value, options)
206
+ value = yield(key)
207
+ write_entity(key, value, store, options)
178
208
  results[key] = value
179
209
  end
180
210
  end
@@ -184,16 +214,46 @@ module Readthis
184
214
  end
185
215
  end
186
216
 
217
+ # Returns `true` if the cache contains an entry for the given key.
218
+ #
219
+ # @param [String] Key for lookup
220
+ # @param [Hash] Optional overrides
221
+ #
222
+ # @example
223
+ #
224
+ # cache.exist?('some-key') # => false
225
+ # cache.exist?('some-key', namespace: 'cache') # => true
226
+ #
187
227
  def exist?(key, options = {})
188
228
  invoke(:exist?, key) do |store|
189
229
  store.exists(namespaced_key(key, merged_options(options)))
190
230
  end
191
231
  end
192
232
 
193
- def clear
233
+ # Clear the entire cache. This flushes the current database, no
234
+ # globbing is applied.
235
+ #
236
+ # @param [Hash] Options, only present for compatibility.
237
+ #
238
+ # @example
239
+ #
240
+ # cache.clear #=> 'OK'
241
+ def clear(options = {})
194
242
  invoke(:clear, '*', &:flushdb)
195
243
  end
196
244
 
245
+ protected
246
+
247
+ def write_entity(key, value, store, options)
248
+ namespaced = namespaced_key(key, options)
249
+
250
+ if expiration = options[:expires_in]
251
+ store.setex(namespaced, expiration, entity.dump(value))
252
+ else
253
+ store.set(namespaced, entity.dump(value))
254
+ end
255
+ end
256
+
197
257
  private
198
258
 
199
259
  def alter(key, amount, options)
@@ -1,3 +1,3 @@
1
1
  module Readthis
2
- VERSION = '0.5.0'
2
+ VERSION = '0.5.1'
3
3
  end
@@ -158,6 +158,22 @@ RSpec.describe Readthis::Cache do
158
158
  'b' => 'bb',
159
159
  'c' => 3,
160
160
  )
161
+
162
+ expect(cache.read('b')).to eq('bb')
163
+ end
164
+
165
+ it 'uses passed options' do
166
+ cache.write('a', 1, namespace: 'alph')
167
+
168
+ results = cache.fetch_multi('a', 'b', namespace: 'alph') { |key| key }
169
+
170
+ expect(results).to eq(
171
+ 'a' => 1,
172
+ 'b' => 'b'
173
+ )
174
+
175
+ expect(cache.read('b')).to be_nil
176
+ expect(cache.read('b', namespace: 'alph')).not_to be_nil
161
177
  end
162
178
  end
163
179
 
@@ -175,10 +191,14 @@ RSpec.describe Readthis::Cache do
175
191
  describe '#delete' do
176
192
  it 'deletes an existing key' do
177
193
  cache.write('not-long', 'for this world')
178
- cache.delete('not-long')
179
194
 
195
+ expect(cache.delete('not-long')).to be_truthy
180
196
  expect(cache.read('not-long')).to be_nil
181
197
  end
198
+
199
+ it 'safely returns false if nothing is deleted' do
200
+ expect(cache.delete('no-such-key')).to be_falsy
201
+ end
182
202
  end
183
203
 
184
204
  describe '#increment' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: readthis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Parker Selbert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-12 00:00:00.000000000 Z
11
+ date: 2014-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis