ohm 0.1.0.rc4 → 0.1.0.rc5
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.
- 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
|