ohm 0.1.0.rc4 → 0.1.0.rc5
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +7 -3
- data/lib/ohm/key.rb +24 -8
- data/lib/ohm/pattern.rb +37 -0
- data/lib/ohm/utils/upgrade.rb +2 -2
- data/lib/ohm/version.rb +1 -1
- data/lib/ohm.rb +183 -121
- data/test/connection_test.rb +1 -9
- data/test/indices_test.rb +3 -1
- data/test/model_test.rb +158 -98
- data/test/mutex_test.rb +4 -4
- data/test/pattern_test.rb +8 -0
- data/test/test_helper.rb +43 -2
- data/test/upgrade_script_test.rb +1 -1
- metadata +6 -7
- data/lib/ohm/collection.rb +0 -186
- data/test/model_module_test.rb +0 -951
data/Rakefile
CHANGED
@@ -25,13 +25,17 @@ task :stop do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
task :test do
|
28
|
-
|
28
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "test", "test_helper"))
|
29
|
+
|
30
|
+
Dir["test/**/*_test.rb"].each_with_index do |file, index|
|
31
|
+
ENV["REDIS_URL"] = "redis://127.0.0.1:6379/#{index}"
|
32
|
+
|
29
33
|
fork do
|
30
34
|
load file
|
31
35
|
end
|
32
36
|
|
33
|
-
Process.wait
|
34
|
-
|
35
37
|
exit $?.exitstatus unless $?.success?
|
36
38
|
end
|
39
|
+
|
40
|
+
Process.waitall
|
37
41
|
end
|
data/lib/ohm/key.rb
CHANGED
@@ -2,27 +2,43 @@ module Ohm
|
|
2
2
|
|
3
3
|
# Represents a key in Redis.
|
4
4
|
class Key < String
|
5
|
-
|
5
|
+
attr :redis
|
6
6
|
|
7
|
-
def
|
8
|
-
|
7
|
+
def initialize(name, redis = nil)
|
8
|
+
@redis = redis
|
9
|
+
super(name.to_s)
|
9
10
|
end
|
10
11
|
|
11
12
|
def [](key)
|
12
|
-
self.class
|
13
|
+
self.class.new("#{self}:#{key}", @redis)
|
13
14
|
end
|
14
15
|
|
15
16
|
def volatile
|
16
|
-
self.index(
|
17
|
+
self.index("~") == 0 ? self : self.class.new("~", @redis)[self]
|
17
18
|
end
|
18
19
|
|
19
20
|
def +(other)
|
20
|
-
self.class.new("#{self}+#{other}")
|
21
|
+
self.class.new("#{self}+#{other}", @redis)
|
21
22
|
end
|
22
23
|
|
23
24
|
def -(other)
|
24
|
-
self.class.new("#{self}-#{other}")
|
25
|
+
self.class.new("#{self}-#{other}", @redis)
|
25
26
|
end
|
26
|
-
end
|
27
27
|
|
28
|
+
[:append, :blpop, :brpop, :decr, :decrby, :del, :exists, :expire,
|
29
|
+
:expireat, :get, :getset, :hdel, :hexists, :hget, :hgetall,
|
30
|
+
:hincrby, :hkeys, :hlen, :hmget, :hmset, :hset, :hvals, :incr,
|
31
|
+
:incrby, :lindex, :llen, :lpop, :lpush, :lrange, :lrem, :lset,
|
32
|
+
:ltrim, :move, :rename, :renamenx, :rpop, :rpoplpush, :rpush,
|
33
|
+
:sadd, :scard, :sdiff, :sdiffstore, :set, :setex, :setnx, :sinter,
|
34
|
+
:sinterstore, :sismember, :smembers, :smove, :sort, :spop,
|
35
|
+
:srandmember, :srem, :substr, :sunion, :sunionstore, :ttl, :type,
|
36
|
+
:zadd, :zcard, :zincrby, :zinterstore, :zrange, :zrangebyscore,
|
37
|
+
:zrank, :zrem, :zremrangebyrank, :zremrangebyscore, :zrevrange,
|
38
|
+
:zrevrank, :zscore, :zunionstore].each do |meth|
|
39
|
+
define_method(meth) do |*args|
|
40
|
+
redis.send(meth, self, *args)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
28
44
|
end
|
data/lib/ohm/pattern.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Pattern extends Array with case equality to provide meaningful semantics in
|
2
|
+
# case statements.
|
3
|
+
#
|
4
|
+
# After this change, pattern matching-like behavior is possible with
|
5
|
+
# Arrays:
|
6
|
+
#
|
7
|
+
# Pattern[Fixnum, String] === [1, "foo"]
|
8
|
+
# Pattern[Symbol, Array] === [:foo, [1, 2]]
|
9
|
+
#
|
10
|
+
# When used in a case statement, it provides a functionality close to that of
|
11
|
+
# languages with proper pattern matching. It becomes useful when implementing
|
12
|
+
# a polymorphic method:
|
13
|
+
#
|
14
|
+
# def [](index, limit = nil)
|
15
|
+
# case [index, limit]
|
16
|
+
# when Pattern[Fixnum, Fixnum] then
|
17
|
+
# key.lrange(index, limit).collect { |id| model[id] }
|
18
|
+
# when Pattern[Range, nil] then
|
19
|
+
# key.lrange(index.first, index.last).collect { |id| model[id] }
|
20
|
+
# when Pattern[Fixnum, nil] then
|
21
|
+
# model[key.lindex(index)]
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
module Ohm
|
26
|
+
class Pattern < Array
|
27
|
+
def ===(other)
|
28
|
+
return false if size != other.size
|
29
|
+
|
30
|
+
each_with_index do |item, index|
|
31
|
+
return false unless item === other[index]
|
32
|
+
end
|
33
|
+
|
34
|
+
true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/ohm/utils/upgrade.rb
CHANGED
@@ -21,11 +21,11 @@ module Ohm
|
|
21
21
|
|
22
22
|
def run
|
23
23
|
models.each do |model|
|
24
|
-
ns = Ohm::Key
|
24
|
+
ns = Ohm::Key.new(model, redis)
|
25
25
|
|
26
26
|
puts "Upgrading #{model}..."
|
27
27
|
|
28
|
-
Batch.each(
|
28
|
+
Batch.each(ns[:all].smembers) do |id|
|
29
29
|
instance = ns[id]
|
30
30
|
|
31
31
|
attrs = []
|
data/lib/ohm/version.rb
CHANGED
data/lib/ohm.rb
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
require "base64"
|
4
4
|
require "redis"
|
5
5
|
|
6
|
+
require File.join(File.dirname(__FILE__), "ohm", "pattern")
|
6
7
|
require File.join(File.dirname(__FILE__), "ohm", "validations")
|
7
8
|
require File.join(File.dirname(__FILE__), "ohm", "compat-1.8.6")
|
8
9
|
require File.join(File.dirname(__FILE__), "ohm", "key")
|
9
|
-
require File.join(File.dirname(__FILE__), "ohm", "collection")
|
10
10
|
|
11
11
|
module Ohm
|
12
12
|
|
@@ -45,7 +45,8 @@ module Ohm
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def options
|
48
|
-
@options
|
48
|
+
@options = [] unless defined? @options
|
49
|
+
@options
|
49
50
|
end
|
50
51
|
|
51
52
|
# Clear the database.
|
@@ -53,11 +54,7 @@ module Ohm
|
|
53
54
|
redis.flushdb
|
54
55
|
end
|
55
56
|
|
56
|
-
|
57
|
-
Key[*args]
|
58
|
-
end
|
59
|
-
|
60
|
-
module_function :key, :connect, :connection, :flush, :redis, :redis=, :options, :threaded
|
57
|
+
module_function :connect, :connection, :flush, :redis, :redis=, :options, :threaded
|
61
58
|
|
62
59
|
Error = Class.new(StandardError)
|
63
60
|
|
@@ -97,44 +94,32 @@ module Ohm
|
|
97
94
|
class Collection
|
98
95
|
include Enumerable
|
99
96
|
|
100
|
-
attr :
|
97
|
+
attr :key
|
101
98
|
attr :model
|
102
99
|
|
103
|
-
def initialize(key, model
|
100
|
+
def initialize(key, model)
|
101
|
+
@key = key
|
104
102
|
@model = model.unwrap
|
105
|
-
@raw = self.class::Raw.new(key, db || @model.db)
|
106
103
|
end
|
107
104
|
|
108
|
-
def
|
109
|
-
|
110
|
-
end
|
111
|
-
|
112
|
-
alias add <<
|
113
|
-
|
114
|
-
def each(&block)
|
115
|
-
raw.each do |id|
|
116
|
-
block.call(model[id])
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def key
|
121
|
-
raw.key
|
105
|
+
def add(model)
|
106
|
+
self << model
|
122
107
|
end
|
123
108
|
|
124
109
|
def first(options = {})
|
125
110
|
if options[:by]
|
126
111
|
sort_by(options.delete(:by), options.merge(:limit => 1)).first
|
127
112
|
else
|
128
|
-
model[
|
113
|
+
model[key.first(options)]
|
129
114
|
end
|
130
115
|
end
|
131
116
|
|
132
117
|
def [](index)
|
133
|
-
model[
|
118
|
+
model[key[index]]
|
134
119
|
end
|
135
120
|
|
136
121
|
def sort(*args)
|
137
|
-
|
122
|
+
key.sort(*args).map(&model)
|
138
123
|
end
|
139
124
|
|
140
125
|
# Sort the model instances by the given attribute.
|
@@ -151,84 +136,127 @@ module Ohm
|
|
151
136
|
options.merge!(:by => model.key("*->#{att}"))
|
152
137
|
|
153
138
|
if options[:get]
|
154
|
-
|
139
|
+
key.sort(options.merge(:get => model.key("*->#{options[:get]}")))
|
155
140
|
else
|
156
141
|
sort(options)
|
157
142
|
end
|
158
143
|
end
|
159
144
|
|
160
|
-
def delete(model)
|
161
|
-
raw.delete(model.id)
|
162
|
-
model
|
163
|
-
end
|
164
|
-
|
165
145
|
def clear
|
166
|
-
|
146
|
+
key.del
|
167
147
|
end
|
168
148
|
|
169
149
|
def concat(models)
|
170
|
-
|
150
|
+
models.each { |model| add(model) }
|
171
151
|
self
|
172
152
|
end
|
173
153
|
|
174
154
|
def replace(models)
|
175
|
-
|
176
|
-
|
155
|
+
clear
|
156
|
+
concat(models)
|
177
157
|
end
|
178
158
|
|
179
|
-
def
|
180
|
-
|
159
|
+
def empty?
|
160
|
+
!key.exists
|
181
161
|
end
|
182
162
|
|
183
|
-
def
|
184
|
-
|
163
|
+
def to_a
|
164
|
+
all
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
class Set < Collection
|
169
|
+
def each(&block)
|
170
|
+
key.smembers.each { |id| block.call(model[id]) }
|
171
|
+
end
|
172
|
+
|
173
|
+
def [](id)
|
174
|
+
model[id] if key.sismember(id)
|
175
|
+
end
|
176
|
+
|
177
|
+
def << model
|
178
|
+
key.sadd(model.id)
|
185
179
|
end
|
186
180
|
|
181
|
+
alias add <<
|
182
|
+
|
187
183
|
def size
|
188
|
-
|
184
|
+
key.scard
|
185
|
+
end
|
186
|
+
|
187
|
+
def delete(member)
|
188
|
+
key.srem(member.id)
|
189
189
|
end
|
190
190
|
|
191
191
|
def all
|
192
|
-
|
192
|
+
key.smembers.map(&model)
|
193
193
|
end
|
194
194
|
|
195
|
-
|
196
|
-
|
195
|
+
def find(options)
|
196
|
+
source = keys(options)
|
197
|
+
target = source.inject(key.volatile) { |chain, other| chain + other }
|
198
|
+
apply(:sinterstore, key, source, target)
|
199
|
+
end
|
197
200
|
|
198
|
-
|
199
|
-
|
201
|
+
def except(options)
|
202
|
+
source = keys(options)
|
203
|
+
target = source.inject(key.volatile) { |chain, other| chain - other }
|
204
|
+
apply(:sdiffstore, key, source, target)
|
205
|
+
end
|
200
206
|
|
201
|
-
def
|
202
|
-
|
207
|
+
def sort(options = {})
|
208
|
+
return [] unless key.exists
|
209
|
+
|
210
|
+
options[:start] ||= 0
|
211
|
+
options[:limit] = [options[:start], options[:limit]] if options[:limit]
|
212
|
+
|
213
|
+
key.sort(options).map(&model)
|
203
214
|
end
|
204
215
|
|
205
|
-
#
|
216
|
+
# Sort the model instances by the given attribute.
|
206
217
|
#
|
207
|
-
# @
|
208
|
-
#
|
209
|
-
#
|
218
|
+
# @example Sorting elements by name:
|
219
|
+
#
|
220
|
+
# User.create :name => "B"
|
221
|
+
# User.create :name => "A"
|
210
222
|
#
|
211
|
-
#
|
212
|
-
#
|
213
|
-
|
214
|
-
|
223
|
+
# user = User.all.sort_by(:name, :order => "ALPHA").first
|
224
|
+
# user.name == "A"
|
225
|
+
# # => true
|
226
|
+
def sort_by(att, options = {})
|
227
|
+
return [] unless key.exists
|
228
|
+
|
229
|
+
options.merge!(:by => model.key["*->#{att}"])
|
230
|
+
|
231
|
+
if options[:get]
|
232
|
+
key.sort(options.merge(:get => model.key["*->#{options[:get]}"]))
|
233
|
+
else
|
234
|
+
sort(options)
|
235
|
+
end
|
215
236
|
end
|
216
237
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
238
|
+
def first(options = {})
|
239
|
+
options.merge!(:limit => 1)
|
240
|
+
|
241
|
+
if options[:by]
|
242
|
+
sort_by(options.delete(:by), options).first
|
243
|
+
else
|
244
|
+
sort(options).first
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def include?(model)
|
249
|
+
key.sismember(model.id)
|
223
250
|
end
|
224
251
|
|
225
|
-
|
252
|
+
def inspect
|
253
|
+
"#<Set (#{model}): #{key.smembers.inspect}>"
|
254
|
+
end
|
226
255
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
target
|
231
|
-
model.db.send(operation, target, key, *keys)
|
256
|
+
protected
|
257
|
+
|
258
|
+
def apply(operation, key, source, target)
|
259
|
+
target.send(operation, key, *source)
|
232
260
|
Set.new(target, Wrapper.wrap(model))
|
233
261
|
end
|
234
262
|
|
@@ -245,37 +273,74 @@ module Ohm
|
|
245
273
|
end
|
246
274
|
end
|
247
275
|
|
276
|
+
class Index < Set
|
277
|
+
def find(options)
|
278
|
+
keys = keys(options)
|
279
|
+
return super(options) if keys.size > 1
|
280
|
+
|
281
|
+
Set.new(keys.first, Wrapper.wrap(model))
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
248
285
|
class List < Collection
|
249
|
-
|
286
|
+
def each(&block)
|
287
|
+
key.lrange(0, -1).each { |id| block.call(model[id]) }
|
288
|
+
end
|
250
289
|
|
251
|
-
def
|
252
|
-
|
253
|
-
|
290
|
+
def <<(model)
|
291
|
+
key.rpush(model.id)
|
292
|
+
end
|
293
|
+
|
294
|
+
alias push <<
|
295
|
+
|
296
|
+
# Returns the element at index, or returns a subarray starting at
|
297
|
+
# start and continuing for length elements, or returns a subarray
|
298
|
+
# specified by range. Negative indices count backward from the end
|
299
|
+
# of the array (-1 is the last element). Returns nil if the index
|
300
|
+
# (or starting index) are out of range.
|
301
|
+
def [](index, limit = nil)
|
302
|
+
case [index, limit]
|
303
|
+
when Pattern[Fixnum, Fixnum] then
|
304
|
+
key.lrange(index, limit).collect { |id| model[id] }
|
305
|
+
when Pattern[Range, nil] then
|
306
|
+
key.lrange(index.first, index.last).collect { |id| model[id] }
|
307
|
+
when Pattern[Fixnum, nil] then
|
308
|
+
model[key.lindex(index)]
|
254
309
|
end
|
255
310
|
end
|
256
311
|
|
312
|
+
def first
|
313
|
+
self[0]
|
314
|
+
end
|
315
|
+
|
257
316
|
def pop
|
258
|
-
|
259
|
-
|
260
|
-
|
317
|
+
id = key.rpop
|
318
|
+
model[id] if id
|
319
|
+
end
|
320
|
+
|
321
|
+
def shift
|
322
|
+
id = key.lpop
|
323
|
+
model[id] if id
|
261
324
|
end
|
262
325
|
|
263
326
|
def unshift(model)
|
264
|
-
|
327
|
+
key.lpush(model.id)
|
265
328
|
end
|
266
329
|
|
267
|
-
def
|
268
|
-
|
330
|
+
def all
|
331
|
+
key.lrange(0, -1).map(&model)
|
269
332
|
end
|
270
|
-
end
|
271
333
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
334
|
+
def size
|
335
|
+
key.llen
|
336
|
+
end
|
337
|
+
|
338
|
+
def include?(model)
|
339
|
+
key.lrange(0, -1).include?(model.id)
|
340
|
+
end
|
341
|
+
|
342
|
+
def inspect
|
343
|
+
"#<List (#{model}): #{key.lrange(0, -1).inspect}>"
|
279
344
|
end
|
280
345
|
end
|
281
346
|
|
@@ -356,8 +421,8 @@ module Ohm
|
|
356
421
|
# is created.
|
357
422
|
#
|
358
423
|
# @param name [Symbol] Name of the list.
|
359
|
-
def self.list(name, model
|
360
|
-
|
424
|
+
def self.list(name, model)
|
425
|
+
define_memoized_method(name) { List.new(key[name], Wrapper.wrap(model)) }
|
361
426
|
collections << name unless collections.include?(name)
|
362
427
|
end
|
363
428
|
|
@@ -366,8 +431,8 @@ module Ohm
|
|
366
431
|
# operations like union, join, and membership checks are important.
|
367
432
|
#
|
368
433
|
# @param name [Symbol] Name of the set.
|
369
|
-
def self.set(name, model
|
370
|
-
|
434
|
+
def self.set(name, model)
|
435
|
+
define_memoized_method(name) { Set.new(key[name], Wrapper.wrap(model)) }
|
371
436
|
collections << name unless collections.include?(name)
|
372
437
|
end
|
373
438
|
|
@@ -427,7 +492,8 @@ module Ohm
|
|
427
492
|
reader = :"#{name}_id"
|
428
493
|
writer = :"#{name}_id="
|
429
494
|
|
430
|
-
|
495
|
+
attributes << reader unless attributes.include?(reader)
|
496
|
+
|
431
497
|
index reader
|
432
498
|
|
433
499
|
define_memoized_method(name) do
|
@@ -435,12 +501,16 @@ module Ohm
|
|
435
501
|
end
|
436
502
|
|
437
503
|
define_method(:"#{name}=") do |value|
|
438
|
-
|
504
|
+
@_memo.delete(name)
|
439
505
|
send(writer, value ? value.id : nil)
|
440
506
|
end
|
441
507
|
|
508
|
+
define_method(reader) do
|
509
|
+
read_local(reader)
|
510
|
+
end
|
511
|
+
|
442
512
|
define_method(writer) do |value|
|
443
|
-
|
513
|
+
@_memo.delete(name)
|
444
514
|
write_local(reader, value)
|
445
515
|
end
|
446
516
|
end
|
@@ -493,19 +563,9 @@ module Ohm
|
|
493
563
|
name.to_s.match(/^(?:.*::)*(.*)$/)[1].gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase.to_sym
|
494
564
|
end
|
495
565
|
|
496
|
-
def self.attr_collection_reader(name, type, model)
|
497
|
-
if model
|
498
|
-
model = Wrapper.wrap(model)
|
499
|
-
define_memoized_method(name) { Ohm::Model::const_get(type).new(key(name), model, db) }
|
500
|
-
else
|
501
|
-
define_memoized_method(name) { Ohm::const_get(type).new(key(name), db) }
|
502
|
-
end
|
503
|
-
end
|
504
|
-
|
505
566
|
def self.define_memoized_method(name, &block)
|
506
567
|
define_method(name) do
|
507
|
-
|
508
|
-
instance_variable_set("@#{name}", instance_eval(&block))
|
568
|
+
@_memo[name] ||= instance_eval(&block)
|
509
569
|
end
|
510
570
|
end
|
511
571
|
|
@@ -518,7 +578,7 @@ module Ohm
|
|
518
578
|
end
|
519
579
|
|
520
580
|
def self.all
|
521
|
-
Ohm::Model::Index.new(key
|
581
|
+
Ohm::Model::Index.new(key[:all], Wrapper.wrap(self))
|
522
582
|
end
|
523
583
|
|
524
584
|
def self.attributes
|
@@ -561,6 +621,8 @@ module Ohm
|
|
561
621
|
end
|
562
622
|
|
563
623
|
def initialize(attrs = {})
|
624
|
+
@id = nil
|
625
|
+
@_memo = {}
|
564
626
|
@_attributes = Hash.new { |hash, key| hash[key] = read_remote(key) }
|
565
627
|
update_attributes(attrs)
|
566
628
|
end
|
@@ -736,8 +798,8 @@ module Ohm
|
|
736
798
|
|
737
799
|
protected
|
738
800
|
|
739
|
-
def key
|
740
|
-
self.class.key
|
801
|
+
def key
|
802
|
+
self.class.key[id]
|
741
803
|
end
|
742
804
|
|
743
805
|
def write
|
@@ -789,16 +851,16 @@ module Ohm
|
|
789
851
|
Ohm.threaded[self] = connection
|
790
852
|
end
|
791
853
|
|
792
|
-
def self.key
|
793
|
-
|
854
|
+
def self.key
|
855
|
+
Key.new(self, db)
|
794
856
|
end
|
795
857
|
|
796
858
|
def self.exists?(id)
|
797
|
-
db.sismember(key
|
859
|
+
db.sismember(key[:all], id)
|
798
860
|
end
|
799
861
|
|
800
862
|
def initialize_id
|
801
|
-
self.id = db.incr(self.class.key
|
863
|
+
self.id = db.incr(self.class.key[:id]).to_s
|
802
864
|
end
|
803
865
|
|
804
866
|
def db
|
@@ -806,7 +868,7 @@ module Ohm
|
|
806
868
|
end
|
807
869
|
|
808
870
|
def delete_attributes(atts)
|
809
|
-
db.del(*atts.map { |att| key
|
871
|
+
db.del(*atts.map { |att| key[att] })
|
810
872
|
end
|
811
873
|
|
812
874
|
def create_model_membership
|
@@ -842,15 +904,15 @@ module Ohm
|
|
842
904
|
def add_to_index(att, value = send(att))
|
843
905
|
index = index_key_for(att, value)
|
844
906
|
db.sadd(index, id)
|
845
|
-
db.sadd(key
|
907
|
+
db.sadd(key[:_indices], index)
|
846
908
|
end
|
847
909
|
|
848
910
|
def delete_from_indices
|
849
|
-
db.smembers(key
|
911
|
+
db.smembers(key[:_indices]).each do |index|
|
850
912
|
db.srem(index, id)
|
851
913
|
end
|
852
914
|
|
853
|
-
db.del(key
|
915
|
+
db.del(key[:_indices])
|
854
916
|
end
|
855
917
|
|
856
918
|
def read_local(att)
|
@@ -884,7 +946,7 @@ module Ohm
|
|
884
946
|
|
885
947
|
def self.index_key_for(att, value)
|
886
948
|
raise IndexNotFound, att unless indices.include?(att)
|
887
|
-
key
|
949
|
+
key[att][encode(value)]
|
888
950
|
end
|
889
951
|
|
890
952
|
def index_key_for(att, value)
|
@@ -897,11 +959,11 @@ module Ohm
|
|
897
959
|
#
|
898
960
|
# @see Model#mutex
|
899
961
|
def lock!
|
900
|
-
until db.setnx(key
|
901
|
-
next unless lock = db.get(key
|
962
|
+
until db.setnx(key[:_lock], lock_timeout)
|
963
|
+
next unless lock = db.get(key[:_lock])
|
902
964
|
sleep(0.5) and next unless lock_expired?(lock)
|
903
965
|
|
904
|
-
break unless lock = db.getset(key
|
966
|
+
break unless lock = db.getset(key[:_lock], lock_timeout)
|
905
967
|
break if lock_expired?(lock)
|
906
968
|
end
|
907
969
|
end
|
@@ -909,7 +971,7 @@ module Ohm
|
|
909
971
|
# Release the lock.
|
910
972
|
# @see Model#mutex
|
911
973
|
def unlock!
|
912
|
-
db.del(key
|
974
|
+
db.del(key[:_lock])
|
913
975
|
end
|
914
976
|
|
915
977
|
def lock_timeout
|
data/test/connection_test.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
|
3
3
|
class ConnectionTest < Test::Unit::TestCase
|
4
|
-
setup do
|
5
|
-
@options = Ohm.options
|
6
|
-
end
|
7
|
-
|
8
4
|
test "connects lazily" do
|
9
5
|
assert_nothing_raised do
|
10
6
|
Ohm.connect(:port => 9876)
|
@@ -32,10 +28,6 @@ class ConnectionTest < Test::Unit::TestCase
|
|
32
28
|
|
33
29
|
threads.each { |t| t.join }
|
34
30
|
|
35
|
-
assert
|
36
|
-
end
|
37
|
-
|
38
|
-
teardown do
|
39
|
-
Ohm.connect(*@options)
|
31
|
+
assert(conn1 != conn2)
|
40
32
|
end
|
41
33
|
end
|