1require 'active_support/cache/dalli_store' |
|
3module ActiveSupport |
|
4 module Cache |
|
5 class AtomicDalliStore < DalliStore |
|
6 def fetch(name, options = nil) |
|
7 if block_given? |
|
8 result = read(name, options)
|
|
10 if result.nil? |
|
11 result = instrument(:generate, name, options) do |payload| |
|
12 yield |
|
13 end |
|
15 write(name, result, options)
|
|
16 else |
|
17 instrument(:fetch_hit, name, options) { |payload| } |
|
18 end |
|
20 result
|
|
21 else |
|
22 read(name, options)
|
|
23 end |
|
24 end |
|
26 def read(name, options = nil) |
|
27 super.tap do |result| |
|
28 if result.present? |
|
29 return nil if lock!(name, options) |
|
30 end |
|
31 end |
|
32 end |
|
34 def write(name, value, options = nil) |
|
35 expiry = (options && options[:expires_in]) || 0 |
|
36 options[:expires_in] = expiry + 20 unless expiry.zero? |
|
37 ttl_set(ttl_key(name, options), expiry) && super |
|
38 end |
|
40 def delete(name, options = nil) |
|
41 ttl_delete(ttl_key(name, options)) && super |
|
42 end |
|
44 private
|
|
46 def lock!(name, options) |
|
47 key = ttl_key(name, options)
|
|
48 ttl_get(key) ? false : ttl_add(key) |
|
49 end |
|
51 def ttl_key(name, options) |
|
52 "#{namespaced_key(name, options)}.ttl" |
|
53 end |
|
55 def ttl_get(key) |
|
56 with { |c| c.get(key, raw: true) } |
|
57 rescue Dalli::DalliError => e |
|
58 logger.error("DalliError: #{e.message}") if logger |
|
59 raise if raise_errors? |
|
60 nil |
|
61 end |
|
63 def ttl_add(key) |
|
64 with { |c| c.add(key, "", 10, raw: true) } |
|
65 rescue Dalli::DalliError => e |
|
66 logger.error("DalliError: #{e.message}") if logger |
|
67 raise if raise_errors? |
|
68 false |
|
69 end |
|
71 def ttl_set(key, expiry) |
|
72 with { |c| c.set(key, "", expiry, raw: true) } |
|
73 rescue Dalli::DalliError => e |
|
74 logger.error("DalliError: #{e.message}") if logger |
|
75 raise if raise_errors? |
|
76 false |
|
77 end |
|
79 def ttl_delete(key) |
|
80 with { |c| c.delete(key) }
|
|
81 rescue Dalli::DalliError => e |
|
82 logger.error("DalliError: #{e.message}") if logger |
|
83 raise if raise_errors? |
|
84 false |
|
85 end |
|
86 end |
|
87 end |
|
88end |