familia 0.7.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,25 +1,25 @@
1
1
 
2
2
  module Familia
3
-
3
+
4
4
  class RedisObject
5
5
  @registration = {}
6
6
  @classes = []
7
-
7
+
8
8
  # To be called inside every class that inherits RedisObject
9
9
  # +meth+ becomes the base for the class and instances methods
10
10
  # that are created for the given +klass+ (e.g. Obj.list)
11
11
  def RedisObject.register klass, meth
12
12
  registration[meth] = klass
13
13
  end
14
-
14
+
15
15
  def RedisObject.registration
16
16
  @registration
17
17
  end
18
-
18
+
19
19
  def RedisObject.classes
20
20
  @classes
21
21
  end
22
-
22
+
23
23
  @db, @ttl = nil, nil
24
24
  class << self
25
25
  attr_accessor :parent
@@ -45,49 +45,61 @@ module Familia
45
45
  super(obj)
46
46
  end
47
47
  end
48
-
48
+
49
49
  attr_reader :name, :parent
50
50
  attr_writer :redis
51
51
 
52
52
  # RedisObject instances are frozen. `cache` is a hash
53
53
  # for you to store values retreived from Redis. This is
54
54
  # not used anywhere by default, but you're encouraged
55
- # to use it in your specific scenarios.
55
+ # to use it in your specific scenarios.
56
56
  attr_reader :cache
57
-
58
- # +name+: If parent is set, this will be used as the suffix
57
+
58
+ # +name+: If parent is set, this will be used as the suffix
59
59
  # for rediskey. Otherwise this becomes the value of the key.
60
60
  # If this is an Array, the elements will be joined.
61
- #
61
+ #
62
62
  # Options:
63
63
  #
64
- # :class => A class that responds to Familia.load_method and
64
+ # :class => A class that responds to Familia.load_method and
65
65
  # Familia.dump_method. These will be used when loading and
66
- # saving data from/to redis to unmarshal/marshal the class.
66
+ # saving data from/to redis to unmarshal/marshal the class.
67
67
  #
68
68
  # :reference => When true the index of the given value will be
69
- # stored rather than the marshaled value. This assumes that
70
- # the marshaled object is stored at a separate key. When read,
71
- # from_redis looks for that separate key and returns the
72
- # unmarshaled object. :class must be specified. Default: false.
69
+ # stored rather than the marshaled value. This assumes that
70
+ # the marshaled object is stored at a separate key. When read,
71
+ # from_redis looks for that separate key and returns the
72
+ # unmarshaled object. :class must be specified. Default: false.
73
73
  #
74
- # :extend => Extend this instance with the functionality in an
74
+ # :extend => Extend this instance with the functionality in an
75
75
  # other module. Literally: "self.extend opts[:extend]".
76
76
  #
77
77
  # :parent => The Familia object that this redis object belongs
78
78
  # to. This can be a class that includes Familia or an instance.
79
- #
79
+ #
80
80
  # :ttl => the time to live in seconds. When not nil, this will
81
- # set the redis expire for this key whenever #save is called.
81
+ # set the redis expire for this key whenever #save is called.
82
82
  # You can also call it explicitly via #update_expiration.
83
83
  #
84
+ # :quantize => append a quantized timestamp to the rediskey.
85
+ # Takes one of the following:
86
+ # Boolean: include the default stamp (now % 10 minutes)
87
+ # Integer: the number of seconds to quantize to (e.g. 1.hour)
88
+ # Array: All arguments for qstamp (quantum, pattern, Time.now)
89
+ #
84
90
  # :default => the default value (String-only)
85
91
  #
92
+ # :dump_method => the instance method to call to serialize the
93
+ # object before sending it to Redis (default: Familia.dump_method).
94
+ #
95
+ # :load_method => the class method to call to deserialize the
96
+ # object after it's read from Redis (default: Familia.load_method).
97
+ #
86
98
  # :db => the redis database to use (ignored if :redis is used).
87
99
  #
88
100
  # :redis => an instance of Redis.
89
101
  #
90
- # Uses the redis connection of the parent or the value of
102
+ # Uses the redis connection of the parent or the value of
91
103
  # opts[:redis] or Familia.redis (in that order).
92
104
  def initialize name, opts={}
93
105
  @name, @opts = name, opts
@@ -96,78 +108,104 @@ module Familia
96
108
  self.extend @opts[:extend] if Module === @opts[:extend]
97
109
  @db = @opts.delete(:db)
98
110
  @parent = @opts.delete(:parent)
99
- @ttl ||= @opts.delete(:ttl)
111
+ @ttl ||= @opts.delete(:ttl)
100
112
  @redis ||= @opts.delete(:redis)
101
113
  @cache = {}
102
114
  init if respond_to? :init
103
115
  end
104
-
116
+
105
117
  def clear_cache
106
118
  @cache.clear
107
119
  end
108
-
120
+
109
121
  def echo meth, trace
110
122
  redis.echo "[#{self.class}\##{meth}] #{trace} (#{@opts[:class]}\#)"
111
123
  end
112
-
124
+
113
125
  def redis
114
126
  return @redis if @redis
115
127
  parent? ? parent.redis : Familia.redis(db)
116
128
  end
117
-
129
+
118
130
  # Returns the most likely value for db, checking (in this order):
119
131
  # * the value from :class if it's a Familia object
120
132
  # * the value from :parent
121
133
  # * the value self.class.db
122
134
  # * assumes the db is 0
123
- #
124
- # After this is called once, this method will always return the
135
+ #
136
+ # After this is called once, this method will always return the
125
137
  # same value.
126
- def db
138
+ def db
127
139
  # Note it's important that we select this value at the last
128
- # possible moment rather than in initialize b/c the value
129
- # could be modified after that but before this is called.
140
+ # possible moment rather than in initialize b/c the value
141
+ # could be modified after that but before this is called.
130
142
  if @opts[:class] && @opts[:class].ancestors.member?(Familia)
131
- @opts[:class].db
143
+ @opts[:class].db
132
144
  elsif parent?
133
145
  parent.db
134
146
  else
135
147
  self.class.db || @db || 0
136
148
  end
137
149
  end
138
-
150
+
139
151
  def ttl
140
- @ttl ||
141
- (parent.ttl if parent?) ||
142
- (@opts[:class].ttl if class?) ||
152
+ @ttl ||
153
+ (parent.ttl if parent?) ||
154
+ (@opts[:class].ttl if class?) ||
143
155
  (self.class.ttl if self.class.respond_to?(:ttl))
144
156
  end
145
-
146
- # returns a redis key based on the parent
157
+
158
+ # returns a redis key based on the parent
147
159
  # object so it will include the proper index.
148
160
  def rediskey
149
- parent? ? parent.rediskey(name, nil) : [name].flatten.compact.join(Familia.delim)
161
+ if parent?
162
+ # We need to check if the parent has a specific suffix
163
+ # for the case where we have specified one other than :object.
164
+ suffix = parent.kind_of?(Familia) && parent.class.suffix != :object ? parent.class.suffix : name
165
+ k = parent.rediskey(name, nil)
166
+ else
167
+ k = [name].flatten.compact.join(Familia.delim)
168
+ end
169
+ if @opts[:quantize]
170
+ args = case @opts[:quantize]
171
+ when Numeric
172
+ [@opts[:quantize]] # :quantize => 1.minute
173
+ when Array
174
+ @opts[:quantize] # :quantize => [1.day, '%m%D']
175
+ else
176
+ [] # :quantize => true
177
+ end
178
+ k = [k, qstamp(*args)].join(Familia.delim)
179
+ end
180
+ k
150
181
  end
151
-
182
+
152
183
  def class?
153
184
  !@opts[:class].to_s.empty? && @opts[:class].kind_of?(Familia)
154
185
  end
155
-
186
+
156
187
  def parent?
157
188
  Class === parent || Module === parent || parent.kind_of?(Familia)
158
189
  end
159
-
190
+
191
+ def qstamp quantum=nil, pattern=nil, now=Familia.now
192
+ quantum ||= ttl || 10.minutes
193
+ pattern ||= '%H%M'
194
+ rounded = now - (now % quantum)
195
+ Time.at(rounded).utc.strftime(pattern)
196
+ end
197
+
160
198
  def update_expiration(ttl=nil)
161
199
  ttl ||= self.ttl
162
200
  return if ttl.to_i.zero? # nil will be zero
163
201
  Familia.ld "#{rediskey} to #{ttl}"
164
202
  expire ttl.to_i
165
203
  end
166
-
204
+
167
205
  def move db
168
206
  redis.move rediskey, db
169
207
  end
170
-
208
+
171
209
  def rename newkey
172
210
  redis.rename rediskey, newkey
173
211
  end
@@ -175,50 +213,50 @@ module Familia
175
213
  def renamenx newkey
176
214
  redis.renamenx rediskey, newkey
177
215
  end
178
-
179
- def type
216
+
217
+ def type
180
218
  redis.type rediskey
181
219
  end
182
-
183
- def delete
220
+
221
+ def delete
184
222
  redis.del rediskey
185
223
  end
186
224
  alias_method :clear, :delete
187
225
  alias_method :del, :delete
188
-
189
- #def destroy!
226
+
227
+ #def destroy!
190
228
  # clear
191
229
  # # TODO: delete redis objects for this instance
192
230
  #end
193
-
231
+
194
232
  def exists?
195
233
  redis.exists(rediskey) && !size.zero?
196
234
  end
197
-
235
+
198
236
  def realttl
199
237
  redis.ttl rediskey
200
238
  end
201
-
239
+
202
240
  def expire sec
203
241
  redis.expire rediskey, sec.to_i
204
242
  end
205
-
243
+
206
244
  def expireat unixtime
207
245
  redis.expireat rediskey, unixtime
208
246
  end
209
-
247
+
210
248
  def persist
211
249
  redis.persist rediskey
212
250
  end
213
-
251
+
214
252
  def dump_method
215
253
  @opts[:dump_method] || Familia.dump_method
216
254
  end
217
-
255
+
218
256
  def load_method
219
257
  @opts[:load_method] || Familia.load_method
220
258
  end
221
-
259
+
222
260
  def to_redis v
223
261
  return v unless @opts[:class]
224
262
  ret = case @opts[:class]
@@ -227,7 +265,7 @@ module Familia
227
265
  else
228
266
  if ::String === v
229
267
  v
230
-
268
+
231
269
  elsif @opts[:reference] == true
232
270
  unless v.respond_to? :index
233
271
  raise Familia::Problem, "#{v.class} does not have an index method"
@@ -239,17 +277,17 @@ module Familia
239
277
 
240
278
  elsif v.respond_to? dump_method
241
279
  v.send dump_method
242
-
280
+
243
281
  else
244
282
  raise Familia::Problem, "No such method: #{v.class}.#{dump_method}"
245
283
  end
246
284
  end
247
285
  if ret.nil?
248
- Familia.ld "[#{self.class}\#to_redis] nil returned for #{@opts[:class]}\##{name}"
286
+ Familia.ld "[#{self.class}\#to_redis] nil returned for #{@opts[:class]}\##{name}"
249
287
  end
250
288
  ret
251
289
  end
252
-
290
+
253
291
  def multi_from_redis *values
254
292
  Familia.ld "multi_from_redis: (#{@opts}) #{values}"
255
293
  return [] if values.empty?
@@ -263,17 +301,17 @@ module Familia
263
301
  @opts[:class].induced_from v
264
302
  else
265
303
  objs = values
266
-
304
+
267
305
  if @opts[:reference] == true
268
306
  objs = @opts[:class].rawmultiget *values
269
307
  end
270
308
  objs.compact!
271
309
  if @opts[:class].respond_to? load_method
272
- objs.collect! { |obj|
310
+ objs.collect! { |obj|
273
311
  begin
274
312
  v = @opts[:class].send load_method, obj
275
313
  if v.nil?
276
- Familia.ld "[#{self.class}\#multi_from_redis] nil returned for #{@opts[:class]}\##{name}"
314
+ Familia.ld "[#{self.class}\#multi_from_redis] nil returned for #{@opts[:class]}\##{name}"
277
315
  end
278
316
  v
279
317
  rescue => ex
@@ -290,28 +328,28 @@ module Familia
290
328
  end
291
329
  ret
292
330
  end
293
-
331
+
294
332
  def from_redis v
295
333
  return @opts[:default] if v.nil?
296
334
  return v unless @opts[:class]
297
335
  ret = multi_from_redis v
298
336
  ret.first unless ret.nil? # return the object or nil
299
- end
300
-
337
+ end
338
+
301
339
  end
302
-
303
-
340
+
341
+
304
342
  class List < RedisObject
305
-
343
+
306
344
  def size
307
345
  redis.llen rediskey
308
346
  end
309
347
  alias_method :length, :size
310
-
348
+
311
349
  def empty?
312
350
  size == 0
313
351
  end
314
-
352
+
315
353
  def push *values
316
354
  echo :push, caller[0] if Familia.debug
317
355
  values.flatten.compact.each { |v| redis.rpush rediskey, to_redis(v) }
@@ -319,12 +357,12 @@ module Familia
319
357
  update_expiration
320
358
  self
321
359
  end
322
-
360
+
323
361
  def << v
324
362
  push v
325
363
  end
326
364
  alias_method :add, :<<
327
-
365
+
328
366
  def unshift *values
329
367
  values.flatten.compact.each { |v| redis.lpush rediskey, to_redis(v) }
330
368
  # TODO: test maxlength
@@ -332,15 +370,15 @@ module Familia
332
370
  update_expiration
333
371
  self
334
372
  end
335
-
373
+
336
374
  def pop
337
375
  from_redis redis.rpop(rediskey)
338
376
  end
339
-
377
+
340
378
  def shift
341
379
  from_redis redis.lpop(rediskey)
342
380
  end
343
-
381
+
344
382
  def [] idx, count=nil
345
383
  if idx.is_a? Range
346
384
  range idx.first, idx.last
@@ -355,23 +393,23 @@ module Familia
355
393
  end
356
394
  end
357
395
  alias_method :slice, :[]
358
-
396
+
359
397
  def delete v, count=0
360
398
  redis.lrem rediskey, count, to_redis(v)
361
399
  end
362
400
  alias_method :remove, :delete
363
401
  alias_method :rem, :delete
364
402
  alias_method :del, :delete
365
-
403
+
366
404
  def range sidx=0, eidx=-1
367
405
  el = rangeraw sidx, eidx
368
406
  multi_from_redis *el
369
407
  end
370
-
408
+
371
409
  def rangeraw sidx=0, eidx=-1
372
410
  redis.lrange(rediskey, sidx, eidx)
373
411
  end
374
-
412
+
375
413
  def members count=-1
376
414
  echo :members, caller[0] if Familia.debug
377
415
  count -= 1 if count > 0
@@ -379,36 +417,36 @@ module Familia
379
417
  end
380
418
  alias_method :all, :members
381
419
  alias_method :to_a, :members
382
-
420
+
383
421
  def membersraw count=-1
384
422
  count -= 1 if count > 0
385
423
  rangeraw 0, count
386
424
  end
387
-
425
+
388
426
  #def revmembers count=1 #TODO
389
427
  # range -count, 0
390
428
  #end
391
-
429
+
392
430
  def each &blk
393
431
  range.each &blk
394
432
  end
395
-
433
+
396
434
  def each_with_index &blk
397
435
  range.each_with_index &blk
398
436
  end
399
-
437
+
400
438
  def eachraw &blk
401
439
  rangeraw.each &blk
402
440
  end
403
-
441
+
404
442
  def eachraw_with_index &blk
405
443
  rangeraw.each_with_index &blk
406
444
  end
407
-
445
+
408
446
  def collect &blk
409
447
  range.collect &blk
410
448
  end
411
-
449
+
412
450
  def select &blk
413
451
  range.select &blk
414
452
  end
@@ -416,15 +454,15 @@ module Familia
416
454
  def collectraw &blk
417
455
  rangeraw.collect &blk
418
456
  end
419
-
457
+
420
458
  def selectraw &blk
421
459
  rangeraw.select &blk
422
460
  end
423
-
461
+
424
462
  def at idx
425
463
  from_redis redis.lindex(rediskey, idx)
426
464
  end
427
-
465
+
428
466
  def first
429
467
  at 0
430
468
  end
@@ -432,12 +470,12 @@ module Familia
432
470
  def last
433
471
  at -1
434
472
  end
435
-
473
+
436
474
  # TODO: def replace
437
475
  ## Make the value stored at KEY identical to the given list
438
476
  #define_method :"#{name}_sync" do |*latest|
439
477
  # latest = latest.flatten.compact
440
- # # Do nothing if we're given an empty Array.
478
+ # # Do nothing if we're given an empty Array.
441
479
  # # Otherwise this would clear all current values
442
480
  # if latest.empty?
443
481
  # false
@@ -454,31 +492,31 @@ module Familia
454
492
  # true
455
493
  # end
456
494
  #end
457
-
495
+
458
496
  Familia::RedisObject.register self, :list
459
497
  end
460
-
498
+
461
499
  class Set < RedisObject
462
-
500
+
463
501
  def size
464
502
  redis.scard rediskey
465
503
  end
466
504
  alias_method :length, :size
467
-
505
+
468
506
  def empty?
469
507
  size == 0
470
508
  end
471
-
509
+
472
510
  def add *values
473
511
  values.flatten.compact.each { |v| redis.sadd rediskey, to_redis(v) }
474
512
  update_expiration
475
513
  self
476
514
  end
477
-
515
+
478
516
  def << v
479
517
  add v
480
518
  end
481
-
519
+
482
520
  def members
483
521
  echo :members, caller[0] if Familia.debug
484
522
  el = membersraw
@@ -490,19 +528,19 @@ module Familia
490
528
  def membersraw
491
529
  redis.smembers(rediskey)
492
530
  end
493
-
531
+
494
532
  def each &blk
495
533
  members.each &blk
496
534
  end
497
-
535
+
498
536
  def each_with_index &blk
499
537
  members.each_with_index &blk
500
538
  end
501
-
539
+
502
540
  def collect &blk
503
541
  members.collect &blk
504
542
  end
505
-
543
+
506
544
  def select &blk
507
545
  members.select &blk
508
546
  end
@@ -510,43 +548,43 @@ module Familia
510
548
  def eachraw &blk
511
549
  membersraw.each &blk
512
550
  end
513
-
551
+
514
552
  def eachraw_with_index &blk
515
553
  membersraw.each_with_index &blk
516
554
  end
517
-
555
+
518
556
  def collectraw &blk
519
557
  membersraw.collect &blk
520
558
  end
521
-
559
+
522
560
  def selectraw &blk
523
561
  membersraw.select &blk
524
562
  end
525
-
563
+
526
564
  def member? v
527
565
  redis.sismember rediskey, to_redis(v)
528
566
  end
529
567
  alias_method :include?, :member?
530
-
568
+
531
569
  def delete v
532
570
  redis.srem rediskey, to_redis(v)
533
571
  end
534
572
  alias_method :remove, :delete
535
573
  alias_method :rem, :delete
536
574
  alias_method :del, :delete
537
-
575
+
538
576
  def intersection *setkeys
539
577
  # TODO
540
578
  end
541
-
579
+
542
580
  def pop
543
581
  redis.spop rediskey
544
582
  end
545
-
583
+
546
584
  def move dstkey, v
547
585
  redis.smove rediskey, dstkey, v
548
586
  end
549
-
587
+
550
588
  def random
551
589
  from_redis randomraw
552
590
  end
@@ -554,11 +592,11 @@ module Familia
554
592
  def randomraw
555
593
  redis.srandmember(rediskey)
556
594
  end
557
-
595
+
558
596
  ## Make the value stored at KEY identical to the given list
559
597
  #define_method :"#{name}_sync" do |*latest|
560
598
  # latest = latest.flatten.compact
561
- # # Do nothing if we're given an empty Array.
599
+ # # Do nothing if we're given an empty Array.
562
600
  # # Otherwise this would clear all current values
563
601
  # if latest.empty?
564
602
  # false
@@ -575,57 +613,57 @@ module Familia
575
613
  # true
576
614
  # end
577
615
  #end
578
-
616
+
579
617
  Familia::RedisObject.register self, :set
580
618
  end
581
-
619
+
582
620
  class SortedSet < RedisObject
583
-
621
+
584
622
  def size
585
623
  redis.zcard rediskey
586
624
  end
587
625
  alias_method :length, :size
588
-
626
+
589
627
  def empty?
590
628
  size == 0
591
629
  end
592
-
630
+
593
631
  # NOTE: The argument order is the reverse of #add
594
632
  # e.g. obj.metrics[VALUE] = SCORE
595
633
  def []= v, score
596
634
  add score, v
597
635
  end
598
-
636
+
599
637
  # NOTE: The argument order is the reverse of #[]=
600
638
  def add score, v
601
639
  ret = redis.zadd rediskey, score, to_redis(v)
602
640
  update_expiration
603
641
  ret
604
642
  end
605
-
643
+
606
644
  def score v
607
645
  ret = redis.zscore rediskey, to_redis(v)
608
646
  ret.nil? ? nil : ret.to_f
609
647
  end
610
648
  alias_method :[], :score
611
-
649
+
612
650
  def member? v
613
651
  !rank(v).nil?
614
652
  end
615
653
  alias_method :include?, :member?
616
-
654
+
617
655
  # rank of member +v+ when ordered lowest to highest (starts at 0)
618
656
  def rank v
619
657
  ret = redis.zrank rediskey, to_redis(v)
620
658
  ret.nil? ? nil : ret.to_i
621
659
  end
622
-
660
+
623
661
  # rank of member +v+ when ordered highest to lowest (starts at 0)
624
662
  def revrank v
625
663
  ret = redis.zrevrank rediskey, to_redis(v)
626
664
  ret.nil? ? nil : ret.to_i
627
665
  end
628
-
666
+
629
667
  def members count=-1, opts={}
630
668
  count -= 1 if count > 0
631
669
  el = membersraw count, opts
@@ -638,7 +676,7 @@ module Familia
638
676
  count -= 1 if count > 0
639
677
  rangeraw 0, count, opts
640
678
  end
641
-
679
+
642
680
  def revmembers count=-1, opts={}
643
681
  count -= 1 if count > 0
644
682
  el = revmembersraw count, opts
@@ -649,7 +687,7 @@ module Familia
649
687
  count -= 1 if count > 0
650
688
  revrangeraw 0, count, opts
651
689
  end
652
-
690
+
653
691
  def each &blk
654
692
  members.each &blk
655
693
  end
@@ -657,15 +695,15 @@ module Familia
657
695
  def each_with_index &blk
658
696
  members.each_with_index &blk
659
697
  end
660
-
698
+
661
699
  def collect &blk
662
700
  members.collect &blk
663
701
  end
664
-
702
+
665
703
  def select &blk
666
704
  members.select &blk
667
705
  end
668
-
706
+
669
707
  def eachraw &blk
670
708
  membersraw.each &blk
671
709
  end
@@ -673,50 +711,54 @@ module Familia
673
711
  def eachraw_with_index &blk
674
712
  membersraw.each_with_index &blk
675
713
  end
676
-
714
+
677
715
  def collectraw &blk
678
716
  membersraw.collect &blk
679
717
  end
680
-
718
+
681
719
  def selectraw &blk
682
720
  membersraw.select &blk
683
721
  end
684
-
722
+
685
723
  def range sidx, eidx, opts={}
686
724
  echo :range, caller[0] if Familia.debug
687
725
  el = rangeraw(sidx, eidx, opts)
688
726
  multi_from_redis *el
689
727
  end
690
-
728
+
691
729
  def rangeraw sidx, eidx, opts={}
692
- opts[:with_scores] = true if opts[:withscores]
693
- redis.zrange(rediskey, sidx, eidx, opts)
730
+ # NOTE: :withscores (no underscore) is the correct naming for the
731
+ # redis-4.x gem. We pass :withscores through explicitly b/c
732
+ # redis.zrange et al only accept that one optional argument.
733
+ # Passing `opts`` through leads to an ArgumentError:
734
+ #
735
+ # sorted_sets.rb:374:in `zrevrange': wrong number of arguments (given 4, expected 3) (ArgumentError)
736
+ #
737
+ redis.zrange(rediskey, sidx, eidx, :withscores => opts[:withscores])
694
738
  end
695
-
739
+
696
740
  def revrange sidx, eidx, opts={}
697
741
  echo :revrange, caller[0] if Familia.debug
698
742
  el = revrangeraw(sidx, eidx, opts)
699
743
  multi_from_redis *el
700
744
  end
701
-
745
+
702
746
  def revrangeraw sidx, eidx, opts={}
703
- opts[:with_scores] = true if opts[:withscores]
704
- redis.zrevrange(rediskey, sidx, eidx, opts)
747
+ redis.zrevrange(rediskey, sidx, eidx, :withscores => opts[:withscores])
705
748
  end
706
-
749
+
707
750
  # e.g. obj.metrics.rangebyscore (now-12.hours), now, :limit => [0, 10]
708
751
  def rangebyscore sscore, escore, opts={}
709
752
  echo :rangebyscore, caller[0] if Familia.debug
710
753
  el = rangebyscoreraw(sscore, escore, opts)
711
754
  multi_from_redis *el
712
755
  end
713
-
756
+
714
757
  def rangebyscoreraw sscore, escore, opts={}
715
758
  echo :rangebyscoreraw, caller[0] if Familia.debug
716
- opts[:with_scores] = true if opts[:withscores]
717
- redis.zrangebyscore(rediskey, sscore, escore, opts)
759
+ redis.zrangebyscore(rediskey, sscore, escore, :withscores => opts[:withscores])
718
760
  end
719
-
761
+
720
762
  def remrangebyrank srank, erank
721
763
  redis.zremrangebyrank rediskey, srank, erank
722
764
  end
@@ -724,7 +766,7 @@ module Familia
724
766
  def remrangebyscore sscore, escore
725
767
  redis.zremrangebyscore rediskey, sscore, escore
726
768
  end
727
-
769
+
728
770
  def increment v, by=1
729
771
  redis.zincrby(rediskey, by, v).to_i
730
772
  end
@@ -736,14 +778,14 @@ module Familia
736
778
  end
737
779
  alias_method :decr, :decrement
738
780
  alias_method :decrby, :decrement
739
-
781
+
740
782
  def delete v
741
783
  redis.zrem rediskey, to_redis(v)
742
784
  end
743
785
  alias_method :remove, :delete
744
786
  alias_method :rem, :delete
745
787
  alias_method :del, :delete
746
-
788
+
747
789
  def at idx
748
790
  range(idx, idx).first
749
791
  end
@@ -757,21 +799,21 @@ module Familia
757
799
  def last
758
800
  at(-1)
759
801
  end
760
-
802
+
761
803
  Familia::RedisObject.register self, :zset
762
804
  end
763
805
 
764
806
  class HashKey < RedisObject
765
-
807
+
766
808
  def size
767
809
  redis.hlen rediskey
768
810
  end
769
811
  alias_method :length, :size
770
-
812
+
771
813
  def empty?
772
814
  size == 0
773
815
  end
774
-
816
+
775
817
  def []= n, v
776
818
  ret = redis.hset rediskey, n, to_redis(v)
777
819
  update_expiration
@@ -779,63 +821,63 @@ module Familia
779
821
  end
780
822
  alias_method :put, :[]=
781
823
  alias_method :store, :[]=
782
-
824
+
783
825
  def [] n
784
826
  from_redis redis.hget(rediskey, n)
785
827
  end
786
828
  alias_method :get, :[]
787
-
829
+
788
830
  def fetch n, default=nil
789
831
  ret = self[n]
790
- if ret.nil?
832
+ if ret.nil?
791
833
  raise IndexError.new("No such index for: #{n}") if default.nil?
792
834
  default
793
835
  else
794
836
  ret
795
837
  end
796
838
  end
797
-
839
+
798
840
  def keys
799
841
  redis.hkeys rediskey
800
842
  end
801
-
843
+
802
844
  def values
803
845
  el = redis.hvals(rediskey)
804
846
  multi_from_redis *el
805
847
  end
806
-
848
+
807
849
  def all
808
850
  # TODO: from_redis
809
851
  redis.hgetall rediskey
810
852
  end
811
853
  alias_method :to_hash, :all
812
854
  alias_method :clone, :all
813
-
855
+
814
856
  def has_key? n
815
857
  redis.hexists rediskey, n
816
858
  end
817
859
  alias_method :include?, :has_key?
818
860
  alias_method :member?, :has_key?
819
-
861
+
820
862
  def delete n
821
863
  redis.hdel rediskey, n
822
864
  end
823
865
  alias_method :remove, :delete
824
866
  alias_method :rem, :delete
825
867
  alias_method :del, :delete
826
-
868
+
827
869
  def increment n, by=1
828
870
  redis.hincrby(rediskey, n, by).to_i
829
871
  end
830
872
  alias_method :incr, :increment
831
873
  alias_method :incrby, :increment
832
-
874
+
833
875
  def decrement n, by=1
834
876
  increment n, -by
835
877
  end
836
878
  alias_method :decr, :decrement
837
879
  alias_method :decrby, :decrement
838
-
880
+
839
881
  def update h={}
840
882
  raise ArgumentError, "Argument to bulk_set must be a hash" unless Hash === h
841
883
  data = h.inject([]){ |ret,pair| ret << [pair[0], to_redis(pair[1])] }.flatten
@@ -844,29 +886,29 @@ module Familia
844
886
  ret
845
887
  end
846
888
  alias_method :merge!, :update
847
-
889
+
848
890
  def values_at *names
849
891
  el = redis.hmget(rediskey, *names.flatten.compact)
850
892
  multi_from_redis *el
851
893
  end
852
-
894
+
853
895
  Familia::RedisObject.register self, :hash
854
896
  end
855
-
897
+
856
898
  class String < RedisObject
857
-
899
+
858
900
  def init
859
901
  end
860
-
902
+
861
903
  def size
862
904
  to_s.size
863
905
  end
864
906
  alias_method :length, :size
865
-
907
+
866
908
  def empty?
867
909
  size == 0
868
910
  end
869
-
911
+
870
912
  def value
871
913
  echo :value, caller[0..5] if Familia.debug
872
914
  redis.setnx rediskey, @opts[:default] if @opts[:default]
@@ -874,45 +916,61 @@ module Familia
874
916
  end
875
917
  alias_method :content, :value
876
918
  alias_method :get, :value
877
-
919
+
878
920
  def to_s
879
921
  value.to_s # value can return nil which to_s should not
880
922
  end
881
-
923
+
882
924
  def to_i
883
925
  value.to_i
884
926
  end
885
-
927
+
886
928
  def value= v
887
929
  ret = redis.set rediskey, to_redis(v)
888
930
  update_expiration
889
931
  ret
890
932
  end
891
933
  alias_method :replace, :value=
892
- alias_method :set, :value=
893
-
934
+ alias_method :set, :value=
935
+
936
+ def setnx v
937
+ ret = redis.setnx rediskey, to_redis(v)
938
+ update_expiration
939
+ ret
940
+ end
941
+
894
942
  def increment
895
- redis.incr rediskey
943
+ ret = redis.incr rediskey
944
+ update_expiration
945
+ ret
896
946
  end
897
947
  alias_method :incr, :increment
898
948
 
899
949
  def incrementby int
900
- redis.incrby rediskey, int.to_i
950
+ ret = redis.incrby rediskey, int.to_i
951
+ update_expiration
952
+ ret
901
953
  end
902
954
  alias_method :incrby, :incrementby
903
955
 
904
956
  def decrement
905
- redis.decr rediskey
957
+ ret = redis.decr rediskey
958
+ update_expiration
959
+ ret
906
960
  end
907
961
  alias_method :decr, :decrement
908
962
 
909
963
  def decrementby int
910
- redis.decrby rediskey, int.to_i
964
+ ret = redis.decrby rediskey, int.to_i
965
+ update_expiration
966
+ ret
911
967
  end
912
968
  alias_method :decrby, :decrementby
913
-
969
+
914
970
  def append v
915
- redis.append rediskey, v
971
+ ret = redis.append rediskey, v
972
+ update_expiration
973
+ ret
916
974
  end
917
975
  alias_method :<<, :append
918
976
 
@@ -921,7 +979,9 @@ module Familia
921
979
  end
922
980
 
923
981
  def setbit offset, v
924
- redis.setbit rediskey, offset, v
982
+ ret = redis.setbit rediskey, offset, v
983
+ update_expiration
984
+ ret
925
985
  end
926
986
 
927
987
  def getrange spoint, epoint
@@ -929,19 +989,22 @@ module Familia
929
989
  end
930
990
 
931
991
  def setrange offset, v
932
- redis.setrange rediskey, offset, v
992
+ ret = redis.setrange rediskey, offset, v
993
+ update_expiration
994
+ ret
933
995
  end
934
-
996
+
935
997
  def getset v
936
- redis.getset rediskey, v
998
+ ret = redis.getset rediskey, v
999
+ update_expiration
1000
+ ret
937
1001
  end
938
-
1002
+
939
1003
  def nil?
940
1004
  value.nil?
941
1005
  end
942
-
1006
+
943
1007
  Familia::RedisObject.register self, :string
944
1008
  end
945
-
946
- end
947
1009
 
1010
+ end