double_write_cache_stores 0.3.0 → 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.
@@ -1,217 +1,209 @@
1
- class DoubleWriteCacheStores::Client
2
- def initialize(read_and_write_store_servers, write_only_store_servers = nil)
3
- @read_and_write_store = read_and_write_store_servers
4
- if write_only_store_servers
5
- if read_and_write_store_servers.class != write_only_store_servers.class
6
- fail "different cache store instance. #{read_and_write_store_servers.class} != #{write_only_store_servers.class}"
7
- end
8
- @write_only_store = write_only_store_servers
1
+ module DoubleWriteCacheStores
2
+ class Client # rubocop:disable Metrics/ClassLength
3
+ attr_accessor :read_and_write_store, :write_only_store
4
+
5
+ def initialize(read_and_write_store_servers, write_only_store_servers = nil)
6
+ @read_and_write_store = read_and_write_store_servers
7
+ if write_only_store_servers
8
+ if read_and_write_store_servers.class != write_only_store_servers.class
9
+ raise "different cache store instance. #{read_and_write_store_servers.class} != #{write_only_store_servers.class}"
10
+ end
11
+ @write_only_store = write_only_store_servers
12
+ end
9
13
  end
10
- end
11
-
12
- def [](key)
13
- get key
14
- end
15
14
 
16
- def get(key)
17
- get_or_read_method_call key
18
- end
19
-
20
- def get_multi(*keys)
21
- get_multi_or_read_multi_method_call *keys
22
- end
23
-
24
- def get_cas(key)
25
- if @read_and_write_store.respond_to? :get_cas
26
- @read_and_write_store.get_cas key
27
- elsif @read_and_write_store.respond_to? :read_cas
28
- @read_and_write_store.read_cas key
15
+ def [](key)
16
+ get key
29
17
  end
30
- end
31
18
 
32
- def set_cas(key, value, cas=0, options=nil)
33
- cas_unique = if @read_and_write_store.respond_to? :set_cas
34
- @read_and_write_store.set_cas key, value, cas, options
35
- elsif @read_and_write_store.respond_to? :read_cas
36
- options ||= {}
37
- options[:cas] = cas
38
- @read_and_write_store.write_cas key, value, options
39
- end
40
-
41
- if @write_only_store && cas_unique
42
- set_or_write_method_call @write_only_store, key, value, options
19
+ def get_cas(key)
20
+ if @read_and_write_store.respond_to? :get_cas
21
+ @read_and_write_store.get_cas key
22
+ elsif @read_and_write_store.respond_to? :read_cas
23
+ @read_and_write_store.read_cas key
24
+ elsif @read_and_write_store.respond_to? :dalli
25
+ @read_and_write_store.dalli.get_cas key
26
+ end
43
27
  end
44
28
 
45
- cas_unique
46
- end
47
-
48
- def read(key)
49
- get_or_read_method_call key
50
- end
51
-
52
- def read_multi(*keys)
53
- get_multi_or_read_multi_method_call *keys
54
- end
55
-
56
- def delete(key)
57
- @read_and_write_store.delete key
58
- @write_only_store.delete key if @write_only_store
59
- end
29
+ def set_cas(key, value, cas = 0, options = nil)
30
+ cas_unique = if @read_and_write_store.respond_to? :set_cas
31
+ @read_and_write_store.set_cas key, value, cas, options
32
+ elsif @read_and_write_store.respond_to? :read_cas
33
+ options ||= {}
34
+ options[:cas] = cas
35
+ @read_and_write_store.write_cas key, value, options
36
+ elsif @read_and_write_store.respond_to? :dalli
37
+ @read_and_write_store.dalli.set_cas key, value, cas, options
38
+ end
39
+
40
+ if @write_only_store && cas_unique
41
+ set_or_write_method_call @write_only_store, key, value, options
42
+ end
60
43
 
61
- def []=(key, value)
62
- set key, value
63
- end
44
+ cas_unique
45
+ end
64
46
 
65
- def set(key, value, options = nil)
66
- write_cache_store key, value, options
67
- end
47
+ def delete(key)
48
+ result = @read_and_write_store.delete key
49
+ @write_only_store.delete key if @write_only_store
50
+ result
51
+ end
68
52
 
69
- def write(key, value, options = nil)
70
- write_cache_store key, value, options
71
- end
53
+ def []=(key, value)
54
+ set key, value
55
+ end
72
56
 
73
- def touch(key, ttl=nil)
74
- result = false
75
- if defined?(Dalli) && @read_and_write_store.is_a?(Dalli::Client)
76
- result = @read_and_write_store.touch key, ttl
77
- else
78
- read_and_write_backend = @read_and_write_store.instance_variable_get('@backend') || @read_and_write_store.instance_variable_get('@data')
79
- if read_and_write_backend && read_and_write_backend.respond_to?(:touch)
80
- result = read_and_write_backend.touch key, ttl
81
- write_only_store_touch key, ttl
57
+ def touch(key, ttl = nil)
58
+ result = if @read_and_write_store.respond_to? :touch
59
+ @read_and_write_store.touch key, ttl
60
+ elsif @read_and_write_store.respond_to? :dalli
61
+ @read_and_write_store.dalli.touch key, ttl
62
+ end
63
+
64
+ if @write_only_store
65
+ if @write_only_store.respond_to? :touch
66
+ @write_only_store.touch key, ttl
67
+ elsif @write_only_store.respond_to? :dalli
68
+ @write_only_store.dalli.touch key, ttl
69
+ end
82
70
  end
83
- end
84
- result
85
- end
86
71
 
87
- def flush
88
- if flush_cache_store || flush_cache_store(:clear)
89
- true
90
- else
91
- false
72
+ result
92
73
  end
93
- end
94
74
 
95
- def fetch(name, options = nil)
96
- if @read_and_write_store.respond_to?(:fetch) ||
97
- (@write_only_store && @write_only_store.respond_to?(:fetch))
98
- if block_given?
99
- result = @read_and_write_store.fetch(name, options = nil) { yield }
100
- @write_only_store.fetch(name, options = nil) { yield } if @write_only_store
101
- result
75
+ def flush
76
+ if flush_cache_store || flush_cache_store(:clear)
77
+ true
102
78
  else
103
- result = @read_and_write_store.fetch(name, options = nil)
104
- @write_only_store.fetch(name, options = nil) if @write_only_store
105
- result
79
+ false
106
80
  end
107
- else
108
- raise UnSupportException.new "Unsupported #fetch from client object."
109
81
  end
110
- end
111
82
 
112
- def increment(key, amount = 1, options = {})
113
- increment_cache_store key, amount, options
114
- end
115
- alias_method :incr, :increment
83
+ def fetch(name, options = {}, &_block)
84
+ raise UnSupportException "Unsupported #fetch from client object." unless @read_and_write_store.respond_to?(:fetch)
116
85
 
117
- def decrement(key, amount = 1, options = {})
118
- decrement_cache_store key, amount, options
119
- end
120
- alias_method :decr, :decrement
121
-
122
- private
123
-
124
- def write_cache_store(key, value, options = nil)
125
- set_or_write_method_call @read_and_write_store, key, value, options
126
- set_or_write_method_call @write_only_store, key, value, options if @write_only_store
127
- end
86
+ delete name if options[:force]
128
87
 
129
- def set_or_write_method_call cache_store, key, value, options
130
- if cache_store.respond_to? :set
131
- if defined?(Dalli) && cache_store.is_a?(Dalli::Client)
132
- ttl = options[:expires_in] if options
133
- cache_store.set key, value, ttl, options
88
+ if options[:race_condition_ttl]
89
+ fetch_race_condition name, options { yield }
134
90
  else
135
- cache_store.set key, value, options
91
+ unless value = get_or_read_method_call(name)
92
+ value = yield
93
+ write_cache_store name, value, options
94
+ end
95
+ value
136
96
  end
137
- elsif cache_store.respond_to? :write
138
- cache_store.write key, value, options
139
97
  end
140
- end
141
98
 
142
- def get_or_read_method_call key
143
- if @read_and_write_store.respond_to? :get
144
- @read_and_write_store.get key
145
- elsif @read_and_write_store.respond_to? :read
146
- @read_and_write_store.read key
99
+ def increment(key, amount = 1, options = {})
100
+ increment_cache_store key, amount, options
147
101
  end
148
- end
102
+ alias_method :incr, :increment
149
103
 
150
- def get_multi_or_read_multi_method_call(*keys)
151
- if @read_and_write_store.respond_to? :get_multi
152
- @read_and_write_store.get_multi *keys
153
- elsif @read_and_write_store.respond_to? :read_multi
154
- @read_and_write_store.read_multi *keys
155
- else
156
- raise UnSupportException.new "Unsupported multi keys get or read from client object."
104
+ def decrement(key, amount = 1, options = {})
105
+ decrement_cache_store key, amount, options
157
106
  end
158
- end
107
+ alias_method :decr, :decrement
159
108
 
160
- def increment_cache_store(key, amount, options)
161
- rw_store_value = incr_or_increment_method_call @read_and_write_store, key, amount, options
162
- return rw_store_value unless @write_only_store
163
- incr_or_increment_method_call @write_only_store, key, amount, options
164
- end
109
+ def write_cache_store(key, value, options = nil)
110
+ set_or_write_method_call @read_and_write_store, key, value, options
111
+ set_or_write_method_call @write_only_store, key, value, options if @write_only_store
112
+ end
113
+ alias_method :set, :write_cache_store
114
+ alias_method :write, :write_cache_store
115
+
116
+ def get_or_read_method_call(key)
117
+ if @read_and_write_store.respond_to? :get
118
+ @read_and_write_store.get key
119
+ elsif @read_and_write_store.respond_to? :read
120
+ @read_and_write_store.read key
121
+ end
122
+ end
123
+ alias_method :get, :get_or_read_method_call
124
+ alias_method :read, :get_or_read_method_call
125
+
126
+ def get_multi_or_read_multi_method_call(*keys)
127
+ if @read_and_write_store.respond_to? :get_multi
128
+ @read_and_write_store.get_multi(*keys)
129
+ elsif @read_and_write_store.respond_to? :read_multi
130
+ @read_and_write_store.read_multi(*keys)
131
+ else
132
+ raise UnSupportException "Unsupported multi keys get or read from client object."
133
+ end
134
+ end
135
+ alias_method :get_multi, :get_multi_or_read_multi_method_call
136
+ alias_method :read_multi, :get_multi_or_read_multi_method_call
165
137
 
166
- def decrement_cache_store(key, amount, options)
167
- rw_store_value = decr_or_decrement_method_call @read_and_write_store, key, amount, options
168
- return rw_store_value unless @write_only_store
169
- decr_or_decrement_method_call @write_only_store, key, amount, options
170
- end
138
+ private
171
139
 
172
- def incr_or_increment_method_call(cache_store, key, amount, options)
173
- if defined?(Dalli) && cache_store.is_a?(Dalli::Client)
174
- ttl = options[:expires_in] if options
175
- default = options.has_key?(:initial) ? options[:initial] : amount
176
- cache_store.incr key, amount, ttl, default
177
- elsif cache_store.respond_to? :increment
178
- options[:initial] = amount unless options.has_key?(:initial)
179
- cache_store.increment key, amount, options
180
- end
181
- end
140
+ def fetch_race_condition(key, options, &_block)
141
+ result = fetch_to_cache_store(@read_and_write_store, key, options) { yield }
142
+ fetch_to_cache_store(@write_only_store, key, options) { result } if @write_only_store && @write_only_store.respond_to?(:fetch)
143
+ result
144
+ end
182
145
 
183
- def decr_or_decrement_method_call(cache_store, key, amount, options)
184
- if defined?(Dalli) && cache_store.is_a?(Dalli::Client)
185
- ttl = options[:expires_in] if options
186
- default = options.has_key?(:initial) ? options[:initial] : 0
187
- cache_store.decr key, amount, ttl, default
188
- elsif cache_store.respond_to? :decrement
189
- options[:initial] = 0 unless options.has_key?(:initial)
190
- cache_store.decrement key, amount, options
191
- end
192
- end
146
+ def fetch_to_cache_store(cache_store, key, options, &_block)
147
+ if cache_store.is_a? Dalli::Client
148
+ ttl = options[:expires_in]
149
+ cache_store.fetch key, ttl, options { yield }
150
+ else
151
+ cache_store.fetch key, options { yield }
152
+ end
153
+ end
193
154
 
194
- def flush_cache_store(method = :flush)
195
- if @read_and_write_store.respond_to? method
196
- if @write_only_store && @write_only_store.respond_to?(method)
197
- @write_only_store.send method
155
+ def set_or_write_method_call(cache_store, key, value, options)
156
+ if cache_store.respond_to? :set
157
+ ttl = options[:expires_in] if options
158
+ cache_store.set key, value, ttl, options
159
+ elsif cache_store.respond_to? :write
160
+ cache_store.write key, value, options
161
+ end
198
162
  end
199
- @read_and_write_store.send method
200
- else
201
- false
202
- end
203
- end
204
163
 
205
- def write_only_store_touch(key, ttl)
206
- if @write_only_store
207
- if defined?(Dalli) && @write_only_store.is_a?(Dalli::Client)
208
- @write_only_store.touch key, ttl
209
- else
210
- write_only_backend = @write_only_store.instance_variable_get('@backend') || @write_only_store.instance_variable_get('@data')
211
- if write_only_backend
212
- write_only_backend.touch(key, ttl) if write_only_backend.respond_to?(:touch)
164
+ def increment_cache_store(key, amount, options)
165
+ rw_store_value = incr_or_increment_method_call @read_and_write_store, key, amount, options
166
+ return rw_store_value unless @write_only_store
167
+ incr_or_increment_method_call @write_only_store, key, amount, options
168
+ end
169
+
170
+ def decrement_cache_store(key, amount, options)
171
+ rw_store_value = decr_or_decrement_method_call @read_and_write_store, key, amount, options
172
+ return rw_store_value unless @write_only_store
173
+ decr_or_decrement_method_call @write_only_store, key, amount, options
174
+ end
175
+
176
+ def incr_or_increment_method_call(cache_store, key, amount, options)
177
+ ttl = options[:expires_in] if options
178
+ default = options.key?(:initial) ? options[:initial] : amount
179
+ if cache_store.is_a? Dalli::Client
180
+ cache_store.incr key, amount, ttl, default
181
+ elsif cache_store.respond_to? :increment
182
+ options[:initial] = amount unless options.key?(:initial)
183
+ cache_store.increment key, amount, **options
184
+ end
185
+ end
186
+
187
+ def decr_or_decrement_method_call(cache_store, key, amount, options)
188
+ if cache_store.is_a?(Dalli::Client)
189
+ ttl = options[:expires_in] if options
190
+ default = options.key?(:initial) ? options[:initial] : 0
191
+ cache_store.decr key, amount, ttl, default
192
+ elsif cache_store.respond_to? :decrement
193
+ options[:initial] = 0 unless options.key?(:initial)
194
+ cache_store.decrement key, amount, **options
195
+ end
196
+ end
197
+
198
+ def flush_cache_store(method = :flush)
199
+ if @read_and_write_store.respond_to? method
200
+ if @write_only_store && @write_only_store.respond_to?(method)
201
+ @write_only_store.send method
202
+ end
203
+ @read_and_write_store.send method
204
+ else
205
+ false
213
206
  end
214
207
  end
215
- end
216
208
  end
217
209
  end
@@ -1,3 +1,3 @@
1
1
  module DoubleWriteCacheStores
2
- VERSION = "0.3.0"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -1,6 +1,25 @@
1
+ module DoubleWriteCacheStores
2
+ loaded_active_support = false
3
+
4
+ begin
5
+ require "active_support"
6
+ loaded_active_support = true
7
+ rescue LoadError # rubocop:disable Lint/SuppressedException
8
+ end
9
+
10
+ loaded_active_support.freeze
11
+
12
+ LOADED_ACTIVE_SUPPORT = loaded_active_support
13
+
14
+ def self.loaded_active_support?
15
+ LOADED_ACTIVE_SUPPORT
16
+ end
17
+ end
18
+
1
19
  require "double_write_cache_stores/version"
2
20
  require "double_write_cache_stores/client"
3
21
  require "double_write_cache_stores/base_exception"
4
- require "dalli_store_patch"
5
- module DoubleWriteCacheStores
6
- end
22
+
23
+ require "dalli"
24
+
25
+ require "mem_cache_store_patch" if DoubleWriteCacheStores.loaded_active_support?
@@ -0,0 +1,13 @@
1
+ # monky patch
2
+ module MemCacheStorePatch
3
+ def dalli
4
+ @data
5
+ end
6
+ end
7
+
8
+ begin
9
+ require "active_support/cache/mem_cache_store"
10
+
11
+ ActiveSupport::Cache::MemCacheStore.include MemCacheStorePatch
12
+ rescue LoadError # rubocop:disable Lint/SuppressedException
13
+ end