redis-roc 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/redis-roc.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'roc/store'
2
+ require 'roc/objects'
@@ -0,0 +1,20 @@
1
+ class Redis
2
+
3
+ def zrevrangebyscore(key, max, min, options = {})
4
+ command = CommandOptions.new(options) do |c|
5
+ c.splat :limit
6
+ c.bool :with_scores
7
+ end
8
+
9
+ @client.call(:zrevrangebyscore, key, max, min, *command.to_a)
10
+ end
11
+
12
+ def del(*keys)
13
+ _bool @client.call(:del, *keys)
14
+ end
15
+
16
+ def hdel(key, field)
17
+ _bool @client.call(:hdel, key, field)
18
+ end
19
+
20
+ end
@@ -0,0 +1,81 @@
1
+ if RUBY_VERSION.match(/^1\.8/)
2
+ require 'rubygems'
3
+ end
4
+ require 'cim_attributes'
5
+
6
+ require 'roc/types/all_types'
7
+
8
+ module ROC
9
+ class Base
10
+ include ROC::Types::AllTypes
11
+ include CIMAttributes
12
+
13
+ attr_reader :key, :options
14
+
15
+ cim_attr_accessor :storage
16
+
17
+ # key, [storage], [seed_data], [opts]
18
+ def initialize(key, *args)
19
+ @key = key
20
+
21
+ if args.last.is_a?(Hash)
22
+ @options = args.pop
23
+ end
24
+
25
+ if args.first.is_a?(ROC::Store::ROCStore)
26
+ @storage = args.shift
27
+ end
28
+
29
+ if !self.storage
30
+ raise ArgumentError, 'no class-level storage set, so must initialize with a Store'
31
+ end
32
+
33
+ if args.size > 1
34
+ raise ArgumentError, 'new(key, [storage], [seed_data], [opts])'
35
+ end
36
+
37
+ if !(seed_data = args.pop).nil?
38
+ seed(seed_data)
39
+ end
40
+ end
41
+
42
+ def seed(data)
43
+ if self.exists?
44
+ raise "#{self.key} already exists -- can't seed it"
45
+ else
46
+ self.clobber(data)
47
+ end
48
+ end
49
+
50
+ def clobber(data)
51
+ raise "clobber must be overriden in subclasses"
52
+ end
53
+
54
+ def self.delegate_methods(options)
55
+ raise ":on and :to required to delegate methods" unless options.has_key?(:on) && options.has_key?(:to)
56
+ self.const_set('DELEGATE_OPTIONS', options)
57
+ end
58
+
59
+ def respond_to?(method_name)
60
+ self.methods.include?(method_name) || (self.class.const_get('DELEGATE_OPTIONS') && self.class.const_get('DELEGATE_OPTIONS')[:on].respond_to?(method_name))
61
+ end
62
+
63
+ def method_missing(method_name, *args, &block)
64
+ if self.class.const_get('DELEGATE_OPTIONS') &&
65
+ (delegate_type = self.class.const_get('DELEGATE_OPTIONS')[:on]) &&
66
+ delegate_type.respond_to?(method_name) &&
67
+ !['!', '='].include?(method_name.to_s[method_name.to_s.length - 1]) # we won't delegate modifying methods
68
+ self.send(self.class.const_get('DELEGATE_OPTIONS')[:to]).send(method_name, *args, &block)
69
+ else
70
+ super(method_name, *args, &block)
71
+ end
72
+ end
73
+
74
+ protected
75
+
76
+ def call(remote_method_name, *args)
77
+ self.storage.call(remote_method_name, self.key, *args)
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,32 @@
1
+ require 'roc/objects/base'
2
+ module ROC
3
+ class Float < Base
4
+ include ROC::Types::ScalarType
5
+
6
+ delegate_methods :on => 0.0, :to => :value
7
+
8
+ def to_float
9
+ self.value.to_f
10
+ end
11
+ alias to_f to_float
12
+
13
+ ## implementing scalar type required methods ##
14
+
15
+ def serialize(val)
16
+ val.to_s
17
+ end
18
+
19
+ def deserialize(val)
20
+ if val.nil?
21
+ nil
22
+ elsif 'Infinity' == val
23
+ 1.0 / 0
24
+ elsif '-Infinity' == val
25
+ -1.0 / 0
26
+ else
27
+ val.to_f
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,134 @@
1
+ require 'roc/objects/base'
2
+ module ROC
3
+ class Hash < Base
4
+ extend ROC::Types::MethodGenerators
5
+
6
+ delegate_methods :on => {}, :to => :to_hash
7
+
8
+ nonserializing_method :hdel
9
+
10
+ nonserializing_method :hexists
11
+ alias key? hexists
12
+ alias has_key? hexists
13
+ alias member? hexists
14
+ alias include? hexists
15
+
16
+ nonserializing_method :hget
17
+ alias get hget
18
+ alias [] hget
19
+
20
+ zero_arg_method :hgetall
21
+ alias getall hgetall
22
+
23
+ def hincrby(field, increment)
24
+ self.call :hincrby, field, increment
25
+ end
26
+ alias incrby hincrby
27
+
28
+ zero_arg_method :hkeys
29
+ alias keys hkeys
30
+
31
+ zero_arg_method :hlen
32
+ alias len hlen
33
+ alias length hlen
34
+ alias size hlen
35
+
36
+ def hmget(*fields)
37
+ self.call :hmget, *fields
38
+ end
39
+ alias mget hmget
40
+
41
+ def hmset(*pairs)
42
+ self.call :hmset, *pairs
43
+ end
44
+ alias mset hmset
45
+
46
+ def hset(field, val)
47
+ self.call :hset, field, val
48
+ end
49
+ alias set hset
50
+ alias []= hset
51
+ alias store hset
52
+
53
+ def hsetnx(field, val)
54
+ self.call :hsetnx, field, val
55
+ end
56
+ alias setnx hsetnx
57
+
58
+ zero_arg_method :hvals
59
+ alias vals hvals
60
+ alias values hvals
61
+
62
+ # shortcuts/helpers
63
+
64
+ alias values_at hmget
65
+
66
+ def has_value?(val)
67
+ self.values.include?(val)
68
+ end
69
+ alias value? has_value?
70
+
71
+ def empty?
72
+ 0 == self.hlen
73
+ end
74
+
75
+ def decrby(field, by)
76
+ self.hincrby field, -by
77
+ end
78
+
79
+ def increment(field, by=nil)
80
+ self.hincrby field, (by || 1)
81
+ end
82
+
83
+ def decrement(field, by=nil)
84
+ self.hincrby field, -(by || 1)
85
+ end
86
+
87
+ ## implement (if posible) destructive methods that would otherwise raise
88
+
89
+ def merge!(hsh)
90
+ raise ArgumentError, 'block version not supported' if block_given?
91
+ self.hmset(*hsh.to_a.flatten)
92
+ self
93
+ end
94
+ alias update merge!
95
+
96
+ def delete(field)
97
+ val = self.hget(field)
98
+ self.hdel(field)
99
+ val
100
+ end
101
+
102
+ def replace(hsh)
103
+ self.clobber(hsh)
104
+ self
105
+ end
106
+
107
+ def clear
108
+ self.replace({})
109
+ end
110
+
111
+ def delete_if
112
+ raise NotImplementedError
113
+ end
114
+
115
+ def shift
116
+ raise NotImplementedError
117
+ end
118
+
119
+ ## implementing for delegate
120
+
121
+ alias to_hash getall
122
+ alias to_h getall
123
+
124
+ def clobber(data)
125
+ self.storage.multi do
126
+ self.forget
127
+ if data.size > 0
128
+ self.merge!(data)
129
+ end
130
+ end
131
+ end
132
+
133
+ end
134
+ end
@@ -0,0 +1,51 @@
1
+ require 'roc/objects/base'
2
+ module ROC
3
+ class Integer < Base
4
+ include ROC::Types::ScalarType
5
+
6
+ delegate_methods :on => 0, :to => :value
7
+
8
+ def to_integer
9
+ self.value.to_i
10
+ end
11
+ alias to_int to_integer
12
+ alias to_i to_integer
13
+
14
+ ## implemeting redis methods ##
15
+
16
+ def increment(by=nil)
17
+ if by.nil?
18
+ self.call :incr
19
+ else
20
+ self.call :incrby, by
21
+ end
22
+ end
23
+ alias incr increment
24
+ alias incrby increment
25
+
26
+ def decrement(by=nil)
27
+ if by.nil?
28
+ self.call :decr
29
+ else
30
+ self.call :decrby, by
31
+ end
32
+ end
33
+ alias decr decrement
34
+ alias decrby decrement
35
+
36
+ ## implementing scalar type required methods ##
37
+
38
+ def serialize(val)
39
+ val.to_s
40
+ end
41
+
42
+ def deserialize(val)
43
+ if val.nil?
44
+ nil
45
+ else
46
+ val.to_i
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,204 @@
1
+ require 'roc/objects/base'
2
+ require 'roc/types/array_type'
3
+ require 'roc/types/sortable_type'
4
+
5
+ module ROC
6
+ class List < Base
7
+ include ROC::Types::ArrayType
8
+ include ROC::Types::SortableType
9
+ extend ROC::Types::MethodGenerators
10
+
11
+ def lrange(start_index, stop_index)
12
+ self.call :lrange, start_index, stop_index
13
+ end
14
+ alias range lrange
15
+
16
+ zero_arg_method :llen
17
+ alias len llen
18
+
19
+ nonserializing_method :rpush
20
+
21
+ nonserializing_method :rpushx
22
+ alias pushx rpushx
23
+
24
+ nonserializing_method :lpush
25
+
26
+ nonserializing_method :lpushx
27
+ alias unshiftx lpushx
28
+
29
+ zero_arg_method :rpop
30
+
31
+ zero_arg_method :lpop
32
+
33
+ def lset(index, val)
34
+ self.call :lset, index, val
35
+ end
36
+ alias set lset
37
+
38
+ nonserializing_method :lindex
39
+ alias index lindex
40
+
41
+ def lrem(count, val)
42
+ self.call :lrem, count, val
43
+ end
44
+ alias rem lrem
45
+
46
+ def ltrim(start_index, stop_index)
47
+ self.call :ltrim, start_index, stop_index
48
+ end
49
+ alias trim ltrim
50
+
51
+ def rpoplpush(other_list=self)
52
+ self.call :rpoplpush, other_list.key
53
+ end
54
+
55
+ def linsert(where, pivot, value)
56
+ self.call :linsert, where, pivot, value
57
+ end
58
+
59
+ def linsert_before(pivot, value)
60
+ self.linsert('before', pivot, value)
61
+ end
62
+ alias insert_before linsert_before
63
+
64
+ def linsert_after(pivot, value)
65
+ self.linsert('after', pivot, value)
66
+ end
67
+ alias insert_after linsert_after
68
+
69
+
70
+ ## shortcut methods
71
+
72
+ def [](range_or_num, num=nil)
73
+ if range_or_num.is_a?(::Integer)
74
+ if num.nil?
75
+ self.lindex(range_or_num)
76
+ elsif num >= 0
77
+ self.lrange(range_or_num, range_or_num + num - 1)
78
+ else
79
+ raise ArgumentError, 'second arg to [] must be a non-neg integer'
80
+ end
81
+ elsif range_or_num.is_a?(Range)
82
+ self.lrange(range_or_num.first, (range_or_num.exclude_end? ? range_or_num.last - 1 : range_or_num.last))
83
+ else
84
+ if num.nil?
85
+ self.values.slice(range_or_num)
86
+ else
87
+ self.values.slice(range_or_num, num)
88
+ end
89
+ end
90
+ end
91
+ alias slice []
92
+
93
+ def first
94
+ self.lindex(0)
95
+ end
96
+
97
+ def last
98
+ self.lindex(-1)
99
+ end
100
+
101
+ def []=(*args)
102
+ case args.size
103
+ when 1
104
+ raise ArgumentError, 'index required'
105
+ when 2
106
+ if args[0].is_a?(::Integer)
107
+ self.lset(*args)
108
+ else
109
+ raise ArgumentError, 'range assignment not supported in []='
110
+ end
111
+ when 3
112
+ raise ArgumentError, 'multiple index assignment not supported in []='
113
+ else
114
+ raise ArgumentError, 'wrong number of args'
115
+ end
116
+ end
117
+
118
+ ## implement (if posible) destructive methods that would otherwise raise
119
+
120
+ def delete(val)
121
+ count = self.lrem(0, val)
122
+ if count > 0
123
+ val
124
+ else
125
+ nil
126
+ end
127
+ end
128
+
129
+ def push(*objs)
130
+ if 1 == objs.size
131
+ self.rpush(objs[0])
132
+ elsif objs.size > 1
133
+ self.storage.multi do
134
+ objs.each do |obj|
135
+ self.rpush(obj)
136
+ end
137
+ end
138
+ end
139
+ self
140
+ end
141
+
142
+ def <<(obj)
143
+ self.push(obj)
144
+ end
145
+
146
+ def unshift(*objs)
147
+ if 1 == objs.size
148
+ self.lpush(objs[0])
149
+ elsif objs.size > 1
150
+ self.storage.multi do
151
+ objs.reverse.each do |obj|
152
+ self.lpush(obj)
153
+ end
154
+ end
155
+ end
156
+ self
157
+ end
158
+
159
+ def pop(*args)
160
+ if 0 == args.size
161
+ self.rpop
162
+ elsif 1 == args.size
163
+ (self.storage.multi do
164
+ args[0].times do
165
+ self.rpop
166
+ end
167
+ end).reverse
168
+ else
169
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 1)"
170
+ end
171
+ end
172
+
173
+ def shift(*args)
174
+ if 0 == args.size
175
+ self.lpop
176
+ elsif 1 == args.size
177
+ (self.storage.multi do
178
+ args[0].times do
179
+ self.lpop
180
+ end
181
+ end).reverse
182
+ else
183
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 1)"
184
+ end
185
+ end
186
+
187
+ ## implementing ArrayType ##
188
+
189
+ def clobber(vals)
190
+ self.storage.multi do
191
+ self.forget
192
+ vals.each{|v| self << v}
193
+ end
194
+ end
195
+
196
+ def values
197
+ self.lrange(0, -1)
198
+ end
199
+
200
+ alias size llen
201
+ alias length llen
202
+
203
+ end
204
+ end
@@ -0,0 +1,53 @@
1
+ module ROC
2
+ class Lock < Time
3
+
4
+ def lock(expires_time)
5
+ aquired_lock = false
6
+ if self.setnx(expires_time)
7
+ aquired_lock = true
8
+ else
9
+ locked_until = self.value
10
+ if locked_until.nil? || (locked_until < ::Time.now) ##ttl of 0 is not yet expired
11
+ # only say we got the lock if we manage to update it first
12
+ if self.getset(expires_time) == locked_until
13
+ aquired_lock = true
14
+ end
15
+ end
16
+ end
17
+ aquired_lock
18
+ end
19
+
20
+ def locked?
21
+ locked_until = self.value
22
+ !locked_until.nil? && (locked_until >= ::Time.now) ##ttl of 0 is not yet expired
23
+ end
24
+
25
+ def unlock
26
+ self.forget
27
+ end
28
+
29
+ def when_locked(expires_time, poll_ms=100)
30
+ until self.lock(expires_time)
31
+ sleep(poll_ms.to_f / 1000)
32
+ end
33
+ begin
34
+ yield
35
+ ensure
36
+ self.unlock
37
+ end
38
+ end
39
+
40
+ def locking_if_necessary(expires_time)
41
+ obtained_lock = self.lock(expires_time)
42
+ begin
43
+ yield
44
+ ensure
45
+ if obtained_lock
46
+ self.unlock
47
+ end
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+