any_cache 0.2.0 → 0.3.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: fb955a7841f5f154dd3a18dcc911333edcf3f9ccc7564c84a8165022cb64e201
4
- data.tar.gz: 85ff1e78b433f11a8b870c49fd012b984491873923be153abf6117c57b757a49
3
+ metadata.gz: b4257f6b3fe2d927086723caf69eec54042cca687633f6737ee42f6604f434a8
4
+ data.tar.gz: dd574909f6c2668f13f19e97cafb948dd1f8c5b4a284705a221b486ccdf29872
5
5
  SHA512:
6
- metadata.gz: aaf92352c50ff3a15610214136f4c8b586786548ee384ec46c377b8f055318060417b0cf14ce9c4522e551b3891a2fe35546570f7ba7bef050faee921b4acbbe
7
- data.tar.gz: 14c37f9ab0c5319408e6366c4bcafacf3eb0f220b621fb7c68325ceac0bed3173953003e1ba052888788e875e98390d21e95588b9d82cddcef361a9b630e51ff
6
+ metadata.gz: 88934a670129cf8a67177471884cc8aa493868c4a0ebe6e73899939d2ffd86c5877341965aba82860752e22fe72fb04abbc51c3e071d6f90507367581cba830c
7
+ data.tar.gz: 676ed5568765a5916992333417503942cb545113aa30241c966b0723b7e521334991c56e008284e9f641db33e368509a8aa244a99658c07ca619ff67ce015c91
data/.travis.yml CHANGED
@@ -70,6 +70,18 @@ matrix:
70
70
  - rvm: ruby-head
71
71
  gemfile: gemfiles/redis_store.gemfile
72
72
  env: TEST_REDIS_STORE_CACHE=true
73
+ - rvm: 2.3.7
74
+ gemfile: gemfiles/active_support_with_dalli.gemfile
75
+ env: TEST_AS_DALLI_STORE=true
76
+ - rvm: 2.4.4
77
+ gemfile: gemfiles/active_support_with_dalli.gemfile
78
+ env: TEST_AS_DALLI_STORE=true
79
+ - rvm: 2.5.1
80
+ gemfile: gemfiles/active_support_with_dalli.gemfile
81
+ env: TEST_AS_DALLI_STORE=true
82
+ - rvm: ruby-head
83
+ gemfile: gemfiles/active_support_with_dalli.gemfile
84
+ env: TEST_AS_DALLI_STORE=true
73
85
  - rvm: 2.3.7
74
86
  gemfile: gemfiles/redis_store.gemfile
75
87
  env: TEST_REDIS_CACHE=true
@@ -94,3 +106,6 @@ matrix:
94
106
  - rvm: ruby-head
95
107
  gemfile: gemfiles/active_support_with_dalli.gemfile
96
108
  env: TEST_AS_MEM_CACHE_STORE_CACHE=true
109
+ notifications:
110
+ slack:
111
+ secure: CRYB00OjJTaAYDPM7VgzdU6kBu0WcgwxyzXR6UTrTklrz3jI8ZRKUxrIqNJXvvYbmQPmnRClCeb1/K865RaH+r6Lc+Fob9mBJrjX2eH8CRtBpn542MgKQcJrJR1rrZnxSq7hAfjzYddtbF/vlzkW5yIRLvtihzY9pP+o9XEJF4mhMZWZw8qeqfK16uDzInYpS7ocw7TjDobKPSpG7SXpm+tVMV+0Wmq/58GZDiHq/vEIPiEegnXEEA6lJao/isZtUGn0YFY+ibQA0MrjnBouIdm4MMkK62ybS8dV/EKT6z0ZuG81VhS8Jb6h8H5j9td8xzjYsHpb1FZE0Rwr8ClWmo2vPRekPxpwqJMBM9lBKJ4Ez7lNWsJP0YkleKfmDEN1KIaMMH4g2YXeTfDagVHc803ooNjCbS1EMA1fZgF77gdlG10sdbyexHkxYxw1rozSa1G6OdDBbKehdaCbqbiqx0unI6gQtENa6ouUiIndZjE/ehcHnP4Y8lFTIbwmvGqborkhsI/0/8X0/Xh6GDypOml3mvKT5u7m0UYBy5lSQpTpmZVz9TV3pId12DM1eObIeWxYRkz+L+7stQBfVAVy8mZFLxm2pmey/Vn5pwAnEwgOBZ5qFPrIEHrjgH91rpdvYVPYswYdGm7WrKPpta4pQhSqDMlKhW1zfk+AMmZ4Yz0=
data/CHANGELOG.md CHANGED
@@ -1,7 +1,22 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [0.3.0] - 2018-10-06
5
+ ### Added
6
+ - support for `ActiveSupport::Cache::DalliStore` client;
7
+ - multi-operations: `#read_multi`, `#write_multi`, `#fetch_multi`, `#delete_matched`;
8
+ - logging:
9
+ - configuration: `AnyCache.configure { |conf| conf.logger = your_logger_object }`;
10
+ - disable logging: `AnyCache.configure { |conf| conf.logger = nil }`;
11
+ - `::Logger.new(STDOUT)` with `::Logger::INFO` level is used by default (an instance of `AnyCache::Logging::Logger`);
12
+ - log message contains the following information:
13
+ - standard log data (level and time);
14
+ - cache class name;
15
+ - current cache operation (`read`, `write` and etc);
16
+ - cache operation arguments;
17
+
4
18
  ## [0.2.0] - 2018-09-03
19
+ ### Added
5
20
  - fetching operation `AnyCache#fetch(key, force:, expires_in:, &block)`
6
21
  - fetches data from the cache using the given key;
7
22
  - if a block has been passed and data with the given key does not exist -
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
- # AnyCache · [![Gem Version](https://badge.fury.io/rb/any_cache.svg)](https://badge.fury.io/rb/any_cache) [![Build Status](https://travis-ci.org/0exp/any_cache.svg?branch=master)](https://travis-ci.org/0exp/any_cache) [![Coverage Status](https://coveralls.io/repos/github/0exp/any_cache/badge.svg)](https://coveralls.io/github/0exp/any_cache)
1
+ # AnyCache · [![Gem Version](https://badge.fury.io/rb/any_cache.svg)](https://badge.fury.io/rb/any_cache) [![Build Status](https://travis-ci.org/0exp/any_cache.svg?branch=master)](https://travis-ci.org/0exp/any_cache) [![Coverage Status](https://coveralls.io/repos/github/0exp/any_cache/badge.svg?branch=master)](https://coveralls.io/github/0exp/any_cache?branch=master)
2
2
 
3
3
  AnyCache - a simplest cache wrapper that provides a minimalistic generic interface for all well-known cache storages and includes a minimal set of necessary operations:
4
- `fetch`, `read`, `write`, `delete`, `expire`, `persist`, `exist?`, `clear`, `increment`, `decrement`.
4
+ `fetch`, `read`, `write`, `delete`, `fetch_multi`, `read_multi`, `write_multi`, `delete_matched`, `expire`, `persist`, `exist?`, `clear`, `increment`, `decrement`.
5
5
 
6
6
  Supported clients:
7
7
 
@@ -9,6 +9,7 @@ Supported clients:
9
9
  - `Redis::Store` ([gem redis-store](https://github.com/redis-store/redis-store)) ([redis storage](https://redis.io/))
10
10
  - `Dalli::Client` ([gem dalli](https://github.com/petergoldstein/dalli)) ([memcached storage](https://memcached.org/))
11
11
  - `ActiveSupport::Cache::RedisCacheStore` ([gem activesupport](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/redis_cache_store.rb)) ([redis cache storage](https://api.rubyonrails.org/classes/ActiveSupport/Cache/RedisCacheStore.html))
12
+ - `ActiveSupport::Cache::DalliStore` ([gem dalli](https://github.com/petergoldstein/dalli)) ([dalli store](https://github.com/petergoldstein/dalli/blob/master/lib/active_support/cache/dalli_store.rb))
12
13
  - `ActiveSupport::Cache::MemCacheStore` ([gem activesupport](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/mem_cache_store.rb)) ([memcache storage](https://api.rubyonrails.org/classes/ActiveSupport/Cache/MemCacheStore.html))
13
14
  - `ActiveSupport::Cache::FileStore` ([gem activesupport](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/file_store.rb)) ([file storage](https://api.rubyonrails.org/classes/ActiveSupport/Cache/FileStore.html))
14
15
  - `ActiveSupport::Cache::MemoryStore` ([gem activesupport](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/memory_store.rb)) ([in memory storage](https://api.rubyonrails.org/classes/ActiveSupport/Cache/MemoryStore.html))
@@ -42,18 +43,19 @@ require 'any_cache'
42
43
  - [AnyCache with Redis::Store](#anycache-with-redisstore)
43
44
  - [AnyCache with Dalli::Client](#anycache-with-dalliclient)
44
45
  - [AnyCache with ActiveSupport::Cache::RedisCacheStore](#anycache-with-activesupportcacherediscachestore)
46
+ - [AnyCache with ActiveSupport::Cache::DalliStore](#anycache-with-activesupportcachedallistore)
45
47
  - [AnyCache with ActiveSupport::Cache::MemCacheStore](#anycache-with-activesupportcachememcachestore)
46
48
  - [AnyCache with ActiveSupport::Cache::FileStore](#anycache-with-activesupportcachefilestore)
47
49
  - [AnyCache with ActiveSupport::Cache::MemoryStore](#anycache-with-activesupportcachememorystore)
48
50
  - [Many cache storages](#many-cache-storages)
49
51
  - [Custom cache clients](#custom-cache-clients)
52
+ - [Logging](#logging)
50
53
  - [Operations](#operations)
51
- - [Fetch](#fetch)
52
- - [Read](#read)
53
- - [Write](#write)
54
- - [Delete](#delete)
55
- - [Increment](#increment)
56
- - [Decrement](#decrement)
54
+ - [Fetch](#fetch) / [Fetch Multi](#fetch-multi)
55
+ - [Read](#read) / [Read Multi](#read-multi)
56
+ - [Write](#write) / [Write Multi](#write-multi)
57
+ - [Delete](#delete) / [Delete Matched](#delete-matched)
58
+ - [Increment](#increment) / [Decrement](#decrement)
57
59
  - [Expire](#expire)
58
60
  - [Persist](#persist)
59
61
  - [Existence](#existence)
@@ -72,6 +74,7 @@ Supported clients:
72
74
  - `Redis::Store`
73
75
  - `Dalli::Client`
74
76
  - `ActiveSupport::Cache::RedisCacheStore`
77
+ - `ActiveSupport::Cache::DalliStore`
75
78
  - `ActiveSupport::Cache::MemCacheStore`
76
79
  - `ActiveSupport::Cache::FileStore`
77
80
  - `ActiveSupport::Cache::MemoryStore`
@@ -94,7 +97,9 @@ client = Redis::Store.new(...)
94
97
  client = Dalli::Client.new(...)
95
98
  # -- or --
96
99
  client = ActiveSupport::Cache::RedisCacheStore.new(...)
97
- # --- or ---
100
+ # -- or --
101
+ client = ActiveSupport::Cache::DalliStore.new(...)
102
+ # -- or --
98
103
  client = ActiveSupport::Cache::MemCacheStore.new(...)
99
104
  # -- or --
100
105
  client = ActiveSupport::Cache::FileStore.new(...)
@@ -102,7 +107,7 @@ client = ActiveSupport::Cache::FileStore.new(...)
102
107
  client = ActiveSupport::Cache::MemoryStore.new(...)
103
108
 
104
109
  # 2) build AnyCache instance
105
- any_cache = AnyCache.build(client) # => <AnyCache:0x00007f990527f268 ...>
110
+ cache_store = AnyCache.build(client) # => <AnyCache:0x00007f990527f268 ...>
106
111
  ```
107
112
 
108
113
  #### Config-based creation
@@ -117,9 +122,10 @@ storage instantiation works via `.build` method without explicit attributes.
117
122
  Supported drivers:
118
123
 
119
124
  - `:redis` - [Redis](#anycache-with-redis);
120
- - `:redis_tore` - [Redis::Client](#anycache-with-redisstore);
125
+ - `:redis_store` - [Redis::Client](#anycache-with-redisstore);
121
126
  - `:dalli` - [Dalli::Client](#anycache-with-dalliclient);
122
127
  - `:as_redis_cache_store` - [ActiveSupport::Cache::RedisCacheStore](#anycache-with-activesupportcacherediscachestore);
128
+ - `:as_dalli_store` - [ActiveSupport::Cache::DalliStore](#anycache-with-activesupportcachedallistore);
123
129
  - `:as_mem_cache_store` - [ActiveSupport::Cache::MemCacheStore](#anycache-with-activesupportcachememcachestore);
124
130
  - `:as_file_store` - [ActiveSupport::Cache::FileStore](#anycache-with-activesupportcachefilestore);
125
131
  - `:as_memory_store` - [ActiveSupport::Cache::MemoryStore](#anycache-with-activesupportcachememorystore);
@@ -135,7 +141,7 @@ AnyCache.configure do |conf|
135
141
  conf.redis.options = { ... } # Redis-related options
136
142
  end
137
143
 
138
- AnyCache.build
144
+ cache_store = AnyCache.build
139
145
  ```
140
146
 
141
147
  ##### `AnyCache` with `Redis::Store`:
@@ -149,7 +155,7 @@ AnyCache.configure do |conf|
149
155
  conf.redis_store.options = { ... } # Redis::Store-related options
150
156
  end
151
157
 
152
- AnyCache.build
158
+ cache_store = AnyCache.build
153
159
  ```
154
160
 
155
161
  ##### `AnyCache` with `Dalli::Client`:
@@ -164,12 +170,13 @@ AnyCache.configure do |conf|
164
170
  conf.dalli.options = { ... } # Dalli::Client-related options
165
171
  end
166
172
 
167
- AnyCache.build
173
+ cache_store = AnyCache.build
168
174
  ```
169
175
 
170
176
  ##### `AnyCache` with `ActiveSupport::Cache::RedisCacheStore`:
171
177
 
172
178
  ```ruby
179
+ require 'redis'
173
180
  require 'active_support'
174
181
  require 'any_cache'
175
182
 
@@ -178,7 +185,23 @@ AnyCache.configure do |conf|
178
185
  conf.as_redis_cache_store.options = { ... } # ActiveSupport::Cache::RedisCacheStore-related options
179
186
  end
180
187
 
181
- AnyCache.build
188
+ cache_store = AnyCache.build
189
+ ```
190
+
191
+ ##### `AnyCache` with `ActiveSupport::Cache::DalliStore`:
192
+
193
+ ```ruby
194
+ require 'dalli'
195
+ require 'active_support'
196
+ require 'any_cache'
197
+
198
+ AnyCache.configure do |conf|
199
+ conf.driver = :as_dalli_store
200
+ conf.as_dalli_store.servers = ... # string or array of strings
201
+ conf.as_dalli_store.options = { ... } # ActiveSupport::Cache::DalliStore-related options
202
+ end
203
+
204
+ cache_store = AnyCache.build
182
205
  ```
183
206
 
184
207
  ##### `AnyCache` with `ActiveSupport::Cache::MemCacheStore`:
@@ -189,11 +212,11 @@ require 'any_cache'
189
212
 
190
213
  AnyCache.configure do |conf|
191
214
  conf.driver = :as_mem_cache_store
192
- conf.as_memory_store.servers = ... # string or array of strings
193
- conf.as_memory_store.options = { ... } # ActiveSupport::Cache::MemCacheStore-related options
215
+ conf.as_mem_cache_store.servers = ... # string or array of strings
216
+ conf.as_mem_cache_store.options = { ... } # ActiveSupport::Cache::MemCacheStore-related options
194
217
  end
195
218
 
196
- AnyCache.build
219
+ cache_store = AnyCache.build
197
220
  ```
198
221
 
199
222
  ##### `AnyCache` with `ActiveSupport::Cache::FileStore`:
@@ -208,7 +231,7 @@ AnyCache.configure do |conf|
208
231
  conf.as_file_store.options = { ... } # ActiveSupport::Cache::FileStore-related options
209
232
  end
210
233
 
211
- AnyCache.build
234
+ cache_store = AnyCache.build
212
235
  ```
213
236
 
214
237
  ##### `AnyCache` with `ActiveSupport::Cache::MemoryStore`:
@@ -222,7 +245,7 @@ AnyCache.configure do |conf|
222
245
  conf.as_memory_store.options = { ... } # ActiveSupport::Cache::MemoryStore-related options
223
246
  end
224
247
 
225
- AnyCache.build
248
+ cache_store = AnyCache.build
226
249
  ```
227
250
 
228
251
  #### Many cache storages
@@ -250,10 +273,14 @@ dalli_cache = DalliCache.build
250
273
 
251
274
  If you want to use your own cache client implementation, you should provide an object that responds to:
252
275
 
253
- - `#fetch(*key, [**options])` ([doc](#fetch))
276
+ - `#fetch(key, [**options])` ([doc](#fetch))
277
+ - `#fetch_multi(*keys, [**options])` ([doc](#fetch-multi))
254
278
  - `#read(key, [**options])` ([doc](#read))
279
+ - `#read_multi(*keys, [**options])` ([doc](#read-multi))
255
280
  - `#write(key, value, [**options])` ([doc](#write))
281
+ - `#write_multi(entries, [**options])` ([doc](#write-multi))
256
282
  - `#delete(key, [**options])` ([doc](#delete))
283
+ - `#delete_matched(pattern, [**options])` ([doc](#delete-matched))
257
284
  - `#increment(key, amount, [**options])` ([doc](#increment))
258
285
  - `#decrement(key, amount, [**options])` ([doc](#decrement))
259
286
  - `#expire(key, [**options])` ([doc](#expire))
@@ -279,16 +306,63 @@ end
279
306
  AnyCache.build(MyCacheClient.new)
280
307
  ```
281
308
 
309
+ ---
310
+
311
+ ### Logging
312
+
313
+ AnyCache logs all its operations. By default, `AnyCache` uses a simple `STDOUT` logger with `Logger::INFO` level.
314
+ Logging is performed with level configured in logger object.
315
+
316
+ Logger configuration:
317
+
318
+ ```ruby
319
+ # --- use your own logger ---
320
+ AnyCache.configure do |conf|
321
+ conf.logger = MyLoggerObject.new
322
+ end
323
+
324
+ # --- disable logging ---
325
+ AnyCache.configure do |conf|
326
+ conf.logger = nil
327
+ end
328
+
329
+ # --- (used by default) ---
330
+ AnyCache.configure do |conf|
331
+ conf.logger = AnyCache::Logging::Logger.new(STDOUT)
332
+ end
333
+ ```
334
+
335
+ Log message format:
336
+
337
+ ```shell
338
+ [AnyCache<CACHER_NAME>/Activity<OPERATION_NAME>]: performed <OPERATION_NAME> operation with
339
+ params: INSPECTED_ARGUMENTS and options: INSPECTED_OPTIONS
340
+ ```
341
+
342
+ - progname
343
+ - `CACHER_NAME` - class name of your cache class;
344
+ - `OPERATION_NAME` - performed operation (`read`, `write`, `fetch` and etc);
345
+ - message
346
+ - `INSPECTED_ARGUMENTS` - a set of operation arguments;
347
+ - `INSPECTED_OPTIONS` - a set of operation options;
348
+
349
+ ```ruby
350
+ any_cache.write("data", 123, expires_in: 60)
351
+ # I, [2018-09-07T10:04:56.649960 #15761] INFO -- [AnyCache<AnyCache>/Activity<write>]: performed <write> operation with params: ["data", 123] and options: {:expires_in=>60}.
352
+
353
+ any_cache.clear
354
+ # I, [2018-09-07T10:05:26.999847 #15761] INFO -- [AnyCache<AnyCache>/Activity<clear>]: performed <clear> operation with params: [] and options: {}.
355
+ ```
356
+
282
357
  ## Operations
283
358
 
284
359
  `AnyCache` provides a following operation set:
285
360
 
286
- - [fetch](#fetch)
287
- - [read](#read)
288
- - [write](#write)
289
- - [delete](#delete)
290
- - [increment](#increment)
291
- - [decrement](#decrement)
361
+ - [fetch](#fetch) / [fetch_multi](#fetch-multi)
362
+ - [read](#read) / [read_multi](#read-multi)
363
+ - [write](#write) / [write_multi](#write-multi)
364
+ - [delete](#delete) / [delete_matched](#delete-matched)
365
+ - [increment](#increment) / [decrement](#decrement)
292
366
  - [expire](#expire)
293
367
  - [persist](#persist)
294
368
  - [clear](#clear)
@@ -298,37 +372,73 @@ AnyCache.build(MyCacheClient.new)
298
372
 
299
373
  ### Fetch
300
374
 
301
- - `AnyCache#fetch(key, [force:], [expires_in:], [&block])`
375
+ - `AnyCache#fetch(key, [force:], [expires_in:], [&fallback])`
302
376
  - works in `ActiveSupport::Cache::Store#fetch`-manner;
303
- - fetches data from the cache, using the given key;
304
- - if there is data in the cache with the given key, then that data is returned;
305
- - if there is no such data in the cache (a cache miss), then nil will be returned:
306
- - if a block has been passed, that block will be passed the key and executed in the event of a cache miss;
307
- - the return value of the block will be written to the cache under the given cache key, and that return value will be returned;
377
+ - fetches data from the cache using the given key;
378
+ - if a `fallback` block has been passed and data with the given key does not exist - that block
379
+ will be called with the given key and the return value will be written to the cache;
308
380
 
309
381
  ```ruby
310
382
  # --- entry exists ---
311
- any_cache.fetch("data") # => "some_data"
312
- any_cache.fetch("data") { "new_data" } # => "some_data"
383
+ cache_store.fetch("data") # => "some_data"
384
+ cache_store.fetch("data") { "new_data" } # => "some_data"
313
385
 
314
386
  # --- entry does not exist ---
315
- any_cache.fetch("data") # => nil
316
- any_cache.fetch("data") { "new_data" } # => "new_data"
317
- any_cache.fetch("data") # => "new_data"
387
+ cache_store.fetch("data") # => nil
388
+ cache_store.fetch("data") { |key| "new_data" } # => "new_data"
389
+ cache_store.fetch("data") # => "new_data"
318
390
 
319
391
  # --- new entry with expiration time ---
320
- any_cache.fetch("data") # => nil
321
- any_cache.fetch("data", expires_in: 8) { "new_data" } # => "new_data"
322
- any_cache.fetch("data") # => "new_data"
392
+ cache_store.fetch("data") # => nil
393
+ cache_store.fetch("data", expires_in: 8) { |key| "new_#{key}" } # => "new_data"
394
+ cache_store.fetch("data") # => "new_data"
323
395
  # ...sleep 8 seconds...
324
- any_cache.fetch("data") # => nil
396
+ cache_store.fetch("data") # => nil
325
397
 
326
398
  # --- force update/rewrite ---
327
- any_cache.fetch("data") # => "some_data"
328
- any_cache.fetch("data", expires_in: 8, force: true) { "new_data" } # => "new_data"
329
- any_cache.fetch("data") # => "new_data"
399
+ cache_store.fetch("data") # => "some_data"
400
+ cache_store.fetch("data", expires_in: 8, force: true) { |key| "new_#{key}" } # => "new_data"
401
+ cache_store.fetch("data") # => "new_data"
330
402
  # ...sleep 8 seconds...
331
- any_cache.fetch("data") # => nil
403
+ cache_store.fetch("data") # => nil
404
+ ```
405
+
406
+ ---
407
+
408
+ ### Fetch Multi
409
+
410
+ - `AnyCache#fetch_multi(*keys, [force:], [expires_in:], [&fallback])`
411
+ - get a set of entries in hash form from the cache storage using given keys;
412
+ - works in `#fetch` manner but with a series of entries;
413
+ - nonexistent entries will be fetched with `nil` values;
414
+
415
+ ```ruby
416
+ # --- fetch entries ---
417
+ cache_store.fetch_multi("data", "second_data", "last_data")
418
+ # => returns:
419
+ {
420
+ "data" => "data", # existing entry
421
+ "second_data" => nil, # nonexistent entry
422
+ "last_data" => nil # nonexistent entry
423
+ }
424
+
425
+ # --- fetch etnries and define non-existent entries ---
426
+ cache_store.fetch_multi("data", "second_data", "last_data") { |key| "new_#{key}" }
427
+ # => returns:
428
+ {
429
+ "data" => "data", # entry with OLD value
430
+ "second_data" => "new_second_data", # entry with NEW DEFINED value
431
+ "last_data" => "new_last_data" # entry with NEW DEFINED value
432
+ }
433
+
434
+ # --- force rewrite all entries ---
435
+ cache_store.fetch_multi("data", "second_data", "last_data", force: true) { |key| "force_#{key}" }
436
+ # => returns
437
+ {
438
+ "data" => "force_data", # entry with REDEFINED value
439
+ "second_data" => "force_second_data", # entry with REDEFINED value
440
+ "last_data" => "force_last_data" # entry with REDEFINED value
441
+ }
332
442
  ```
333
443
 
334
444
  ---
@@ -339,10 +449,29 @@ any_cache.fetch("data") # => nil
339
449
 
340
450
  ```ruby
341
451
  # --- entry exists ---
342
- any_cache.read("data") # => "some_data"
452
+ cache_store.read("data") # => "some_data"
343
453
 
344
454
  # --- entry doesnt exist ---
345
- any_cache.read("data") # => nil
455
+ cache_store.read("data") # => nil
456
+ ```
457
+
458
+ ---
459
+
460
+ ### Read Multi
461
+
462
+ - `AnyCache#read_multi(*keys)`
463
+ - get entries from the cache storage in hash form;
464
+ - nonexistent entries will be fetched with `nil` values;
465
+
466
+ ```ruby
467
+ cache_store.read_multi("data", "another_data", "last_data", "super_data")
468
+ # => returns
469
+ {
470
+ "data" => "test", # existing entry
471
+ "another_data" => nil, # nonexistent entry
472
+ "last_data" => "some_data", # exisitng enry
473
+ "super_data" => nil # existing entry
474
+ }
346
475
  ```
347
476
 
348
477
  ---
@@ -353,10 +482,20 @@ any_cache.read("data") # => nil
353
482
 
354
483
  ```ruby
355
484
  # --- permanent entry ---
356
- any_cache.write("data", 123)
485
+ cache_store.write("data", 123)
357
486
 
358
487
  # --- temporal entry (expires in 60 seconds) ---
359
- any_cache.write("data", 123, expires_in: 60)
488
+ cache_store.write("data", 123, expires_in: 60)
489
+ ```
490
+
491
+ ---
492
+
493
+ ### Write Multi
494
+
495
+ - `AnyCache#write_multi(**entries)` - write a set of permanent entries to the cache storage
496
+
497
+ ```ruby
498
+ cache_store.write_multi("data" => "test", "another_data" => 123)
360
499
  ```
361
500
 
362
501
  ---
@@ -366,7 +505,23 @@ any_cache.write("data", 123, expires_in: 60)
366
505
  - `AnyCache#delete(key)` - remove entry from the cache storage
367
506
 
368
507
  ```ruby
369
- any_cache.delete("data")
508
+ cache_store.delete("data")
509
+ ```
510
+
511
+ ---
512
+
513
+ ### Delete Matched
514
+
515
+ - `AnyCache#delete_matched(pattern)`
516
+ - removes all entries with keys matching the pattern;
517
+ - currently unsupported: `:dalli`, `:as_mem_cache_store`, `:as_dalli_Store`;
518
+
519
+ ```ruby
520
+ # --- using a regepx ---
521
+ cache_store.delete_matched(/\A*test*\z/i)
522
+
523
+ # --- using a string ---
524
+ cache_store.delete_matched("data")
370
525
  ```
371
526
 
372
527
  ---
@@ -378,19 +533,19 @@ any_cache.delete("data")
378
533
 
379
534
  ```ruby
380
535
  # --- increment existing entry ---
381
- any_cache.write("data", 1)
536
+ cache_store.write("data", 1)
382
537
 
383
538
  # --- increment by default value (1) ---
384
- any_cache.increment("data") # => 2
539
+ cache_store.increment("data") # => 2
385
540
 
386
541
  # --- increment by custom value ---
387
- any_cache.increment("data", 12) # => 14
542
+ cache_store.increment("data", 12) # => 14
388
543
 
389
544
  # --- increment and expire after 31 seconds
390
- any_cache.incrmeent("data", expires_in: 31) # => 15
545
+ cache_store.incrmeent("data", expires_in: 31) # => 15
391
546
 
392
547
  # --- increment nonexistent entry (create new entry) ---
393
- any_cache.increment("another_data", 5, expires_in: 5) # => 5
548
+ cache_store.increment("another_data", 5, expires_in: 5) # => 5
394
549
  ```
395
550
 
396
551
  ---
@@ -402,19 +557,19 @@ any_cache.increment("another_data", 5, expires_in: 5) # => 5
402
557
 
403
558
  ```ruby
404
559
  # --- decrement existing entry ---
405
- any_cache.write("data", 15)
560
+ cache_store.write("data", 15)
406
561
 
407
562
  # --- decrement by default value (1) ---
408
- any_cache.decrement("data") # => 14
563
+ cache_store.decrement("data") # => 14
409
564
 
410
565
  # --- decrement by custom value ---
411
- any_cache.decrement("data", 10) # => 4
566
+ cache_store.decrement("data", 10) # => 4
412
567
 
413
568
  # --- decrement and expire after 5 seconds
414
- any_cache.decrememnt("data", expirs_in: 5) # => 3
569
+ cache_store.decrememnt("data", expirs_in: 5) # => 3
415
570
 
416
571
  # --- decrement nonexistent entry (create new entry) ---
417
- any_cache.decrememnt("another_data", 2, expires_in: 10) # => -2 (or 0 for Dalli::Client)
572
+ cache_store.decrememnt("another_data", 2, expires_in: 10) # => -2 (or 0 for Dalli::Client)
418
573
  ```
419
574
 
420
575
  ---
@@ -425,10 +580,10 @@ any_cache.decrememnt("another_data", 2, expires_in: 10) # => -2 (or 0 for Dalli:
425
580
 
426
581
  ```ruby
427
582
  # --- expire immediately ---
428
- any_cache.expire("data")
583
+ cache_store.expire("data")
429
584
 
430
585
  # --- set new expiration time (in seconds) --
431
- any_cache.expire("data", expires_in: 36)
586
+ cache_store.expire("data", expires_in: 36)
432
587
  ```
433
588
 
434
589
  ---
@@ -439,10 +594,10 @@ any_cache.expire("data", expires_in: 36)
439
594
 
440
595
  ```ruby
441
596
  # --- create temporal entry (30 seconds) ---
442
- any_cache.write("data", { a: 1 }, expires_in: 30)
597
+ cache_store.write("data", { a: 1 }, expires_in: 30)
443
598
 
444
599
  # --- remove entry expiration (make it permanent) ---
445
- any_cache.persist("data")
600
+ cache_store.persist("data")
446
601
  ```
447
602
 
448
603
  ---
@@ -453,10 +608,10 @@ any_cache.persist("data")
453
608
 
454
609
  ```ruby
455
610
  # --- entry exists ---
456
- any_cache.exist?("data") # => true
611
+ cache_store.exist?("data") # => true
457
612
 
458
613
  # --- entry does not exist ---
459
- any_cache.exist?("another-data") # => false
614
+ cache_store.exist?("another-data") # => false
460
615
  ```
461
616
 
462
617
  ---
@@ -467,17 +622,17 @@ any_cache.exist?("another-data") # => false
467
622
 
468
623
  ```ruby
469
624
  # --- prepare cache data ---
470
- any_cache.write("data", { a: 1, b: 2 })
471
- any_cache.write("another_data", 123_456)
625
+ cache_store.write("data", { a: 1, b: 2 })
626
+ cache_store.write("another_data", 123_456)
472
627
 
473
- any_cache.read("data") # => { a: 1, b: 2 }
474
- any_cache.read("another_data") # => 123_456
628
+ cache_store.read("data") # => { a: 1, b: 2 }
629
+ cache_store.read("another_data") # => 123_456
475
630
 
476
631
  # --- clear cache ---
477
- any_cache.clear
632
+ cache_store.clear
478
633
 
479
- any_cache.read("data") # => nil
480
- any_cache.read("another_data") # => nil
634
+ cache_store.read("data") # => nil
635
+ cache_store.read("another_data") # => nil
481
636
  ```
482
637
 
483
638
  ---
@@ -490,14 +645,23 @@ any_cache.read("another_data") # => nil
490
645
  bin/rspec --test-redis # run specs with Redis
491
646
  bin/rspec --test-redis-store # run specs with Redis::Store
492
647
  bin/rspec --test-dalli # run specs with Dalli::Client
493
- bin/rspec --test-as-file-store # run specs with ActiveSupport::Cache::FileStore
494
- bin/rspec --test-as-memory-store # run specs with ActiveSupport::Cache::MemoryStore
495
648
  bin/rspec --test-as-redis-cache-store # run specs with ActiveSupport::Cache::RedisCacheStore
649
+ bin/rspec --test-as-dalli-store # run specs with ActiveSupport::Cache::DalliStore
496
650
  bin/rspec --test-as-mem-cache-store # run specs with ActiveSupport::Cache::MemCacheStore
651
+ bin/rspec --test-as-file-store # run specs with ActiveSupport::Cache::FileStore
652
+ bin/rspec --test-as-memory-store # run specs with ActiveSupport::Cache::MemoryStore
497
653
  ```
498
654
 
499
655
  ---
500
656
 
657
+ ## Roadmap
658
+
659
+ - instrumentation layer;
660
+ - global and configurable default expiration time;
661
+ - `#delete_matched` for memcached-based cache storages;
662
+
663
+ ---
664
+
501
665
  ## Contributing
502
666
 
503
667
  - Fork it (https://github.com/0exp/any_cache/fork)
data/any_cache.gemspec CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.add_development_dependency 'coveralls', '~> 0.8'
34
34
  spec.add_development_dependency 'simplecov', '~> 0.16'
35
- spec.add_development_dependency 'armitage-rubocop', '~> 0.7'
35
+ spec.add_development_dependency 'armitage-rubocop', '~> 0.9'
36
36
  spec.add_development_dependency 'rspec', '~> 3.8'
37
37
 
38
38
  spec.add_development_dependency 'bundler'
data/bin/rspec CHANGED
@@ -20,7 +20,7 @@ module AnyCacheSpecRunner
20
20
  active_support_with_dalli: expand_gemfile_path('active_support_with_dalli.gemfile')
21
21
  }.freeze
22
22
 
23
- # rubocop:disable Metrics/MethodLength, Metrics/BlockLength
23
+ # rubocop:disable Metrics/MethodLength, Metrics/BlockLength, Metrics/AbcSize
24
24
  def run!
25
25
  OptionParser.new do |opts|
26
26
  opts.banner = 'Usage: bin/rspec [options]'
@@ -60,13 +60,18 @@ module AnyCacheSpecRunner
60
60
  'Run specs with ActiveSupport::Cache::MemCacheStore cache storage'
61
61
  ) { run_as_mem_cache_store_cache_specs! }
62
62
 
63
+ opts.on(
64
+ '--test-as-dalli-store',
65
+ 'Run specs with ActiveSupport::Cache::DalliStore cache storage'
66
+ ) { run_as_dalli_store_specs! }
67
+
63
68
  opts.on(
64
69
  '-h', '--help',
65
70
  'Show this message'
66
71
  ) { puts opts }
67
72
  end.parse!
68
73
  end
69
- # rubocop:enable Metrics/MethodLength, Metrics/BlockLength
74
+ # rubocop:enable Metrics/MethodLength, Metrics/BlockLength, Metrics/AbcSize
70
75
 
71
76
  private
72
77
 
@@ -119,6 +124,13 @@ module AnyCacheSpecRunner
119
124
  run_tests!
120
125
  end
121
126
 
127
+ def run_as_dalli_store_specs!
128
+ ENV['TEST_AS_DALLI_STORE'] = 'true'
129
+ ENV['BUNDLE_GEMFILE'] = GEMFILES[:active_support_with_dalli]
130
+
131
+ run_tests!
132
+ end
133
+
122
134
  def run_tests!
123
135
  require 'rubygems'
124
136
  require 'bundler/setup'