ngmoco-cache-money 0.2.9 → 0.2.10
Sign up to get free protection for your applications and to get access to all the features.
- data/UNSUPPORTED_FEATURES +0 -1
- data/lib/cash/lock.rb +9 -4
- data/lib/cash/query/abstract.rb +9 -1
- data/lib/memcached_wrapper.rb +34 -5
- data/spec/cash/finders_spec.rb +8 -0
- data/spec/spec_helper.rb +3 -2
- metadata +3 -2
data/UNSUPPORTED_FEATURES
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
* attr_readonly - no technical obstacle, just not yet supported
|
8
8
|
* attributes before typecast behave unpredictably - hard to support
|
9
9
|
* ActiveRecord::Rollback is unsupported - the exception gets swallowed so there isn't an opportunity to rollback the cache transaction - not hard to support
|
10
|
-
* Named bind variables :conditions => ["name = :name", { :name => "37signals!" }] - not hard to support
|
11
10
|
* printf style binds: :conditions => ["name = '%s'", "37signals!"] - not too hard to support
|
12
11
|
* objects as attributes that are serialized. story.title = {:foo => :bar}; customer.balance = Money.new(...) - these could be coerced using Column#type_cast?
|
13
12
|
|
data/lib/cash/lock.rb
CHANGED
@@ -2,8 +2,8 @@ module Cash
|
|
2
2
|
class Lock
|
3
3
|
class Error < RuntimeError; end
|
4
4
|
|
5
|
-
INITIAL_WAIT =
|
6
|
-
DEFAULT_RETRY =
|
5
|
+
INITIAL_WAIT = 2
|
6
|
+
DEFAULT_RETRY = 8
|
7
7
|
DEFAULT_EXPIRY = 30
|
8
8
|
|
9
9
|
def initialize(cache)
|
@@ -27,10 +27,10 @@ module Cash
|
|
27
27
|
retries.times do |count|
|
28
28
|
response = @cache.add("lock/#{key}", Process.pid, lock_expiry)
|
29
29
|
return if response == "STORED\r\n"
|
30
|
-
raise Error if count == retries - 1
|
31
30
|
exponential_sleep(count, initial_wait) unless count == retries - 1
|
32
31
|
end
|
33
|
-
|
32
|
+
debug_lock(key)
|
33
|
+
raise Error, "Couldn't acquire memcache lock for: #{key} server: #{@cache.get_server_for_key(key)}"
|
34
34
|
end
|
35
35
|
|
36
36
|
def release_lock(key)
|
@@ -47,5 +47,10 @@ module Cash
|
|
47
47
|
@cache.get("lock/#{key}") == Process.pid
|
48
48
|
end
|
49
49
|
|
50
|
+
def debug_lock(key)
|
51
|
+
@cache.logger.warn("#{@cache.get("lock/#{key}")}") if @cache.respond_to?(:logger) && @cache.logger.respond_to?(:warn)
|
52
|
+
rescue
|
53
|
+
@cache.logger.warn("#{$!}") if @cache.respond_to?(:logger) && @cache.logger.respond_to?(:warn)
|
54
|
+
end
|
50
55
|
end
|
51
56
|
end
|
data/lib/cash/query/abstract.rb
CHANGED
@@ -119,7 +119,15 @@ module Cash
|
|
119
119
|
conditions.split(AND).inject([]) do |indices, condition|
|
120
120
|
matched, table_name, column_name, sql_value = *(KEY_EQ_VALUE.match(condition))
|
121
121
|
if matched
|
122
|
-
value = sql_value == '?' ? values.shift : columns_hash[column_name].type_cast(sql_value)
|
122
|
+
# value = sql_value == '?' ? values.shift : columns_hash[column_name].type_cast(sql_value)
|
123
|
+
if sql_value == '?'
|
124
|
+
value = values.shift
|
125
|
+
elsif sql_value[0..0] == ':' && values && values.count > 0 && values[0].is_a?(Hash)
|
126
|
+
symb = sql_value[1..-1].to_sym
|
127
|
+
value = columns_hash[column_name].type_cast(values[0][symb])
|
128
|
+
else
|
129
|
+
value = columns_hash[column_name].type_cast(sql_value)
|
130
|
+
end
|
123
131
|
indices << [column_name, value]
|
124
132
|
else
|
125
133
|
return nil
|
data/lib/memcached_wrapper.rb
CHANGED
@@ -10,14 +10,14 @@
|
|
10
10
|
####### they have MemCache installed (don't need the wrapper)
|
11
11
|
if defined? MemCache
|
12
12
|
|
13
|
-
Rails.logger.info("cache-money: MemCache installed")
|
13
|
+
Rails.logger.info("cache-money: MemCache installed") if defined? Rails
|
14
14
|
#TODO add logging?
|
15
15
|
class MemcachedWrapper < ::MemCache
|
16
16
|
end
|
17
17
|
|
18
18
|
########## they have Memcached installed (do need the wrapper)
|
19
19
|
elsif defined? Memcached
|
20
|
-
Rails.logger.info("cache-money: Memcached installed")
|
20
|
+
Rails.logger.info("cache-money: Memcached installed") if defined? Rails
|
21
21
|
|
22
22
|
class Memcached
|
23
23
|
alias :get_multi :get #:nodoc:
|
@@ -69,20 +69,25 @@ class MemcachedWrapper < ::Memcached
|
|
69
69
|
|
70
70
|
# Wraps Memcached::Rails#add to return a text string - for cache money
|
71
71
|
def add(key, value, ttl=@default_ttl, raw=false)
|
72
|
+
logger.debug("Memcached add: #{key.inspect}") if logger && @debug
|
72
73
|
super(key, value, ttl, !raw)
|
74
|
+
logger.debug("Memcached hit: #{key.inspect}") if logger && @debug
|
73
75
|
stored
|
74
76
|
rescue Memcached::NotStored
|
77
|
+
logger.debug("Memcached miss: #{key.inspect}") if logger && @debug
|
75
78
|
not_stored
|
76
79
|
rescue Memcached::Error
|
77
|
-
log_error($!)
|
78
80
|
log_error($!) if logger
|
79
81
|
not_stored
|
80
82
|
end
|
81
83
|
|
82
84
|
def replace(key, value, ttl = @default_ttl, raw = false)
|
85
|
+
logger.debug("Memcached replace: #{key.inspect}") if logger && @debug
|
83
86
|
super(key, value, ttl, !raw)
|
87
|
+
logger.debug("Memcached hit: #{key.inspect}") if logger && @debug
|
84
88
|
stored
|
85
89
|
rescue Memcached::NotStored
|
90
|
+
logger.debug("Memcached miss: #{key.inspect}") if logger && @debug
|
86
91
|
not_stored
|
87
92
|
rescue Memcached::Error
|
88
93
|
log_error($!) if logger
|
@@ -122,9 +127,12 @@ class MemcachedWrapper < ::Memcached
|
|
122
127
|
|
123
128
|
# Wraps Memcached#cas so that it doesn't raise. Doesn't set anything if no value is present.
|
124
129
|
def cas(key, ttl=@default_ttl, raw=false, &block)
|
130
|
+
logger.debug("Memcached cas: #{key.inspect}") if logger && @debug
|
125
131
|
super(key, ttl, !raw, &block)
|
132
|
+
logger.debug("Memcached hit: #{key.inspect}") if logger && @debug
|
126
133
|
stored
|
127
134
|
rescue Memcached::NotFound
|
135
|
+
logger.debug("Memcached miss: #{key.inspect}") if logger && @debug
|
128
136
|
rescue TypeError
|
129
137
|
log_error($!) if logger
|
130
138
|
delete(key)
|
@@ -138,7 +146,13 @@ class MemcachedWrapper < ::Memcached
|
|
138
146
|
|
139
147
|
def get_multi(*keys)
|
140
148
|
keys.flatten!
|
141
|
-
|
149
|
+
logger.debug("Memcached get_multi: #{keys.inspect}") if logger && @debug
|
150
|
+
values = super(keys, true)
|
151
|
+
logger.debug("Memcached hit: #{keys.inspect}") if logger && @debug
|
152
|
+
values
|
153
|
+
rescue Memcached::NotFound
|
154
|
+
logger.debug("Memcached miss: #{keys.inspect}") if logger && @debug
|
155
|
+
{}
|
142
156
|
rescue TypeError
|
143
157
|
log_error($!) if logger
|
144
158
|
keys.each { |key| delete(key) }
|
@@ -150,7 +164,9 @@ class MemcachedWrapper < ::Memcached
|
|
150
164
|
end
|
151
165
|
|
152
166
|
def set(key, value, ttl=@default_ttl, raw=false)
|
167
|
+
logger.debug("Memcached set: #{key.inspect}") if logger && @debug
|
153
168
|
super(key, value, ttl, !raw)
|
169
|
+
logger.debug("Memcached hit: #{key.inspect}") if logger && @debug
|
154
170
|
stored
|
155
171
|
rescue Memcached::Error
|
156
172
|
log_error($!) if logger
|
@@ -158,27 +174,36 @@ class MemcachedWrapper < ::Memcached
|
|
158
174
|
end
|
159
175
|
|
160
176
|
def append(key, value)
|
177
|
+
logger.debug("Memcached append: #{key.inspect}") if logger && @debug
|
161
178
|
super(key, value)
|
179
|
+
logger.debug("Memcached hit: #{key.inspect}") if logger && @debug
|
162
180
|
stored
|
163
181
|
rescue Memcached::NotStored
|
182
|
+
logger.debug("Memcached miss: #{key.inspect}") if logger && @debug
|
164
183
|
not_stored
|
165
184
|
rescue Memcached::Error
|
166
185
|
log_error($!) if logger
|
167
186
|
end
|
168
187
|
|
169
188
|
def prepend(key, value)
|
189
|
+
logger.debug("Memcached prepend: #{key.inspect}") if logger && @debug
|
170
190
|
super(key, value)
|
191
|
+
logger.debug("Memcached hit: #{key.inspect}") if logger && @debug
|
171
192
|
stored
|
172
193
|
rescue Memcached::NotStored
|
194
|
+
logger.debug("Memcached miss: #{key.inspect}") if logger && @debug
|
173
195
|
not_stored
|
174
196
|
rescue Memcached::Error
|
175
197
|
log_error($!) if logger
|
176
198
|
end
|
177
199
|
|
178
200
|
def delete(key)
|
201
|
+
logger.debug("Memcached delete: #{key.inspect}") if logger && @debug
|
179
202
|
super(key)
|
203
|
+
logger.debug("Memcached hit: #{key.inspect}") if logger && @debug
|
180
204
|
deleted
|
181
205
|
rescue Memcached::NotFound
|
206
|
+
logger.debug("Memcached miss: #{key.inspect}") if logger && @debug
|
182
207
|
not_found
|
183
208
|
rescue Memcached::Error
|
184
209
|
log_error($!) if logger
|
@@ -198,6 +223,10 @@ class MemcachedWrapper < ::Memcached
|
|
198
223
|
log_error($!) if logger
|
199
224
|
end
|
200
225
|
|
226
|
+
def get_server_for_key(key, options = {})
|
227
|
+
server_by_key(key)
|
228
|
+
end
|
229
|
+
|
201
230
|
alias :reset :quit
|
202
231
|
alias :close :quit #nodoc
|
203
232
|
alias :flush_all :flush
|
@@ -229,5 +258,5 @@ private
|
|
229
258
|
|
230
259
|
end
|
231
260
|
else
|
232
|
-
Rails.logger.warn 'unable to determine memcache implementation'
|
261
|
+
Rails.logger.warn 'unable to determine memcache implementation' if defined? Rails
|
233
262
|
end #include the wraper
|
data/spec/cash/finders_spec.rb
CHANGED
@@ -30,6 +30,14 @@ module Cash
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
describe '#find(:first, :conditions => [ "id = :id", { :id => story.id } ])' do
|
34
|
+
it "does not use the database" do
|
35
|
+
story = Story.create!
|
36
|
+
mock(Story.connection).execute.never
|
37
|
+
Story.find(:first, :conditions => [ "id = :id", { :id => story.id } ]).should == story
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
33
41
|
describe "#find(:first, :conditions => 'id = ?')" do
|
34
42
|
it "does not use the database" do
|
35
43
|
story = Story.create!
|
data/spec/spec_helper.rb
CHANGED
@@ -6,7 +6,8 @@ require 'spec'
|
|
6
6
|
require 'pp'
|
7
7
|
require 'cache_money'
|
8
8
|
#require 'memcache'
|
9
|
-
|
9
|
+
require 'memcached'
|
10
|
+
require 'memcached_wrapper'
|
10
11
|
|
11
12
|
require File.join(dir, '../config/environment')
|
12
13
|
|
@@ -16,7 +17,7 @@ Spec::Runner.configure do |config|
|
|
16
17
|
load File.join(dir, "../db/schema.rb")
|
17
18
|
|
18
19
|
config = YAML.load(IO.read((File.expand_path(File.dirname(__FILE__) + "/../config/memcached.yml"))))['test']
|
19
|
-
$memcache = MemcachedWrapper.new(config[
|
20
|
+
$memcache = MemcachedWrapper.new(config["servers"].gsub(' ', '').split(','), config)
|
20
21
|
$lock = Cash::Lock.new($memcache)
|
21
22
|
end
|
22
23
|
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ngmoco-cache-money
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Kallen
|
8
|
+
- Ashley Martens
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date:
|
13
|
+
date: 2010-01-08 00:00:00 -08:00
|
13
14
|
default_executable:
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|