redis-roc 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,148 @@
1
+ require 'roc/objects/base'
2
+ require 'roc/types/array_type'
3
+ require 'roc/types/sortable_type'
4
+
5
+ module ROC
6
+ class Set < Base
7
+ include ROC::Types::ArrayType
8
+ include ROC::Types::SortableType
9
+ extend ROC::Types::MethodGenerators
10
+
11
+ nonserializing_method :sadd
12
+ alias add sadd
13
+
14
+ zero_arg_method :scard
15
+ alias card scard
16
+
17
+ nonserializing_method :sismember
18
+ alias ismember sismember
19
+ alias ismember? sismember
20
+ alias is_member? sismember
21
+ alias include? sismember
22
+
23
+ zero_arg_method :smembers
24
+ alias members smembers
25
+
26
+ zero_arg_method :spop
27
+
28
+ zero_arg_method :srandmember
29
+ alias randmmember srandmember
30
+ alias rand_member srandmember
31
+
32
+ nonserializing_method :srem
33
+ alias rem srem
34
+
35
+ def smove(other_set, val)
36
+ self.call :smove, other_set.key, val
37
+ end
38
+ alias move smove
39
+ alias move_into smove
40
+
41
+ def sinter(*other_sets)
42
+ self.call :sinter, *other_sets.map{|s| s.key}
43
+ end
44
+ alias inter sinter
45
+ alias intersect sinter
46
+ alias :& :sinter ## to make rdoc parser happy
47
+
48
+ def sunion(*other_sets)
49
+ self.call :sunion, *other_sets.map{|s| s.key}
50
+ end
51
+ alias union sunion
52
+ alias | sunion
53
+
54
+ def sdiff(*other_sets)
55
+ self.call :sdiff, *other_sets.map{|s| s.key}
56
+ end
57
+ alias diff sdiff
58
+ alias - sdiff
59
+
60
+ def sinterstore(*other_sets)
61
+ self.call :sinterstore, *other_sets.map{|s| s.key}
62
+ end
63
+ alias interstore sinterstore
64
+ alias inter_store sinterstore
65
+ alias set_as_intersect_of sinterstore
66
+
67
+ def sunionstore(*other_sets)
68
+ self.call :sunionstore, *other_sets.map{|s| s.key}
69
+ end
70
+ alias unionstore sunionstore
71
+ alias union_store sunionstore
72
+ alias set_as_union_of sunionstore
73
+
74
+ def sdiffstore(*other_sets)
75
+ self.call :sdiffstore, *other_sets.map{|s| s.key}
76
+ end
77
+ alias diffstore sdiffstore
78
+ alias diff_store sdiffstore
79
+ alias set_as_diff_of sdiffstore
80
+
81
+ ## helpers
82
+
83
+ def to_hash
84
+ hsh = {}
85
+ self.smembers.each do |val|
86
+ hsh[val] = true
87
+ end
88
+ hsh
89
+ end
90
+ alias to_h to_hash
91
+
92
+ ## implement (if posible) destructive methods that would otherwise raise
93
+
94
+ def delete(val)
95
+ if self.srem(val)
96
+ val
97
+ else
98
+ nil
99
+ end
100
+ end
101
+
102
+ def push(*objs)
103
+ if 1 == objs.size
104
+ self.sadd(objs[0])
105
+ elsif objs.size > 1
106
+ self.storage.multi do
107
+ objs.each do |obj|
108
+ self.sadd(obj)
109
+ end
110
+ end
111
+ end
112
+ self
113
+ end
114
+
115
+ def <<(obj)
116
+ self.push(obj)
117
+ end
118
+
119
+ def pop(*args)
120
+ if 0 == args.size
121
+ self.spop
122
+ elsif 1 == args.size
123
+ (self.storage.multi do
124
+ args[0].times do
125
+ self.spop
126
+ end
127
+ end).reverse
128
+ else
129
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 1)"
130
+ end
131
+ end
132
+
133
+ ## implementing ArrayType ##
134
+
135
+ def clobber(vals)
136
+ self.storage.multi do
137
+ self.forget
138
+ vals.each{|v| self << v}
139
+ end
140
+ end
141
+
142
+ alias values smembers
143
+
144
+ alias size scard
145
+ alias length scard
146
+
147
+ end
148
+ end
@@ -0,0 +1,217 @@
1
+ require 'roc/objects/base'
2
+ require 'roc/types/array_type'
3
+ require 'roc/types/sortable_type'
4
+
5
+ module ROC
6
+ class SortedSet < Base
7
+ include ROC::Types::ArrayType
8
+ include ROC::Types::SortableType
9
+ extend ROC::Types::MethodGenerators
10
+
11
+ def zadd(score, val)
12
+ self.call :zadd, score, val
13
+ end
14
+ alias add zadd
15
+
16
+ zero_arg_method :zcard
17
+ alias card zcard
18
+
19
+ def zrange(start_index, stop_index, opts={})
20
+ self.call :zrange, start_index, stop_index, opts
21
+ end
22
+ alias range zrange
23
+
24
+ def zrevrange(start_index, stop_index, opts={})
25
+ self.call :zrevrange, start_index, stop_index, opts
26
+ end
27
+ alias revrange zrevrange
28
+
29
+ def zrangebyscore(min, max, opts={})
30
+ self.call :zrangebyscore, min, max, opts
31
+ end
32
+ alias rangebyscore zrangebyscore
33
+
34
+ def zrevrangebyscore(max, min, opts={})
35
+ self.call :zrevrangebyscore, max, min, opts
36
+ end
37
+ alias revrangebyscore zrevrangebyscore
38
+
39
+ def zcount (min, max)
40
+ self.call :zcount, min, max
41
+ end
42
+ alias count zcount
43
+
44
+ nonserializing_method :zrank
45
+ alias rank zrank
46
+
47
+ nonserializing_method :zrevrank
48
+ alias revrank zrevrank
49
+
50
+ nonserializing_method :zscore
51
+ alias score zscore
52
+
53
+ def zincrby(by, val)
54
+ self.call :zincrby, by, val
55
+ end
56
+ alias incrby zincrby
57
+
58
+ nonserializing_method :zrem
59
+ alias rem zrem
60
+
61
+ def zremrangebyscore(min, max)
62
+ self.call :zremrangebyscore, min, max
63
+ end
64
+ alias remrangebyscore zremrangebyscore
65
+
66
+ def zremrangebyrank(start, stop)
67
+ self.call :zremrangebyrank, start, stop
68
+ end
69
+ alias remrangebyrank zremrangebyrank
70
+
71
+ def zinterstore(*other_sorted_sets)
72
+ opts = if other_sorted_sets.last.is_a?(::Hash)
73
+ other_sorted_sets.pop
74
+ else
75
+ {}
76
+ end
77
+
78
+ self.call :zinterstore, [*other_sorted_sets].map{|s| s.key}, opts
79
+ end
80
+ alias interstore zinterstore
81
+ alias inter_store zinterstore
82
+ alias set_as_intersect_of zinterstore
83
+
84
+ def zunionstore(*other_sorted_sets)
85
+ opts = if other_sorted_sets.last.is_a?(::Hash)
86
+ other_sorted_sets.pop
87
+ else
88
+ {}
89
+ end
90
+ self.call :zunionstore, [*other_sorted_sets].map{|s| s.key}, opts
91
+ end
92
+ alias unionstore zunionstore
93
+ alias union_store zunionstore
94
+ alias set_as_union_of zunionstore
95
+
96
+ ## shortcut methods
97
+
98
+ def [](range_or_num, num=nil)
99
+ if range_or_num.is_a?(::Integer)
100
+ if num.nil?
101
+ self.zrange(range_or_num, range_or_num)[0]
102
+ elsif num >= 0
103
+ self.zrange(range_or_num, range_or_num + num - 1)
104
+ else
105
+ raise ArgumentError, 'second arg to [] must be a non-neg integer'
106
+ end
107
+ elsif range_or_num.is_a?(Range)
108
+ self.zrange(range_or_num.first, (range_or_num.exclude_end? ? range_or_num.last - 1 : range_or_num.last))
109
+ else
110
+ if num.nil?
111
+ self.values.slice(range_or_num)
112
+ else
113
+ self.values.slice(range_or_num, num)
114
+ end
115
+ end
116
+ end
117
+ alias slice []
118
+
119
+ def first
120
+ self.zrange(0, 0)[0]
121
+ end
122
+
123
+ def last
124
+ self.zrange(-1, -1)[0]
125
+ end
126
+
127
+ def include?(val)
128
+ !self.zrank(val).nil?
129
+ end
130
+
131
+ def index(val)
132
+ self.zrank(val)
133
+ end
134
+
135
+ def reverse
136
+ self.zrevrange(0, -1)
137
+ end
138
+
139
+ # helpers
140
+
141
+ def decrby(by, val)
142
+ self.zincrby -by, val
143
+ end
144
+
145
+ def increment(val, by=nil)
146
+ self.zincrby( (by || 1), val )
147
+ end
148
+
149
+ def decrement(val, by=nil)
150
+ self.zincrby( -(by || 1), val )
151
+ end
152
+
153
+ def to_hash
154
+ hsh = {}
155
+ vals_with_scores = self.zrangebyscore('-inf', '+inf', :with_scores => true)
156
+ i = 0
157
+ l = vals_with_scores.size
158
+ while i < l
159
+ hsh[vals_with_scores[i]] = vals_with_scores[i+1]
160
+ i += 2
161
+ end
162
+ hsh
163
+ end
164
+ alias to_h to_hash
165
+
166
+ ## implement (if posible) destructive methods that would otherwise raise
167
+
168
+ def delete(val)
169
+ if self.zrem(val)
170
+ val
171
+ else
172
+ nil
173
+ end
174
+ end
175
+
176
+ def <<(val_and_score)
177
+ if val_and_score.is_a?(Array)
178
+ self.zadd *val_and_score
179
+ elsif val_and_score.is_a?(::Hash) && val_and_score.has_key?(:value) && val_and_score.has_key?(:score)
180
+ self.zadd(val_and_score[:score], val_and_score[:value])
181
+ else
182
+ raise ArgumentError, 'an Array or a Hash required'
183
+ end
184
+ self
185
+ end
186
+
187
+ def push(*objs)
188
+ if 1 == objs.size
189
+ self << objs[0]
190
+ elsif objs.size > 1
191
+ self.storage.multi do
192
+ objs.each do |obj|
193
+ self << obj
194
+ end
195
+ end
196
+ end
197
+ self
198
+ end
199
+
200
+ ## implementing ArrayType ##
201
+
202
+ def clobber(vals)
203
+ self.storage.multi do
204
+ self.forget
205
+ vals.each{|v| self << v}
206
+ end
207
+ end
208
+
209
+ def values(opts = {})
210
+ self.zrange(0, -1, opts)
211
+ end
212
+
213
+ alias size zcard
214
+ alias length zcard
215
+
216
+ end
217
+ end
@@ -0,0 +1,116 @@
1
+ require 'roc/objects/base'
2
+ require 'roc/types/scalar_type'
3
+
4
+ module ROC
5
+ class String < Base
6
+ include ROC::Types::ScalarType
7
+ extend ROC::Types::MethodGenerators
8
+
9
+ delegate_methods :on => '', :to => :value
10
+
11
+ attr_reader :encoding
12
+
13
+ def to_string
14
+ self.value.to_s
15
+ end
16
+ alias to_s to_string
17
+
18
+ ## redis methods ##
19
+
20
+ nonserializing_method :append
21
+ alias << append
22
+ alias concat append
23
+
24
+ def getrange(first_index, last_index)
25
+ self.call :getrange, first_index, last_index
26
+ end
27
+ alias substr getrange
28
+ alias substring getrange
29
+
30
+ nonserializing_method :getbit
31
+
32
+ def setbit(index, val)
33
+ self.call :setbit, index, val
34
+ end
35
+
36
+ def setrange(start_index, val)
37
+ self.call :setrange, start_index, val
38
+ end
39
+ alias splice setrange
40
+
41
+ zero_arg_method :strlen
42
+ alias bytesize strlen
43
+
44
+ ## shortcut methods
45
+
46
+ def getbyte(ind)
47
+ val = self.getrange(ind, ind)
48
+ if val.nil? || ('' == val)
49
+ nil
50
+ else
51
+ val.bytes.to_a[0]
52
+ end
53
+ end
54
+
55
+ def setbyte(ind, int)
56
+ self.setrange(ind, int.chr)
57
+ int
58
+ end
59
+
60
+ def empty?
61
+ 0 == self.strlen
62
+ end
63
+
64
+ def chr
65
+ self.getrange(0, 0)
66
+ end
67
+
68
+ ## implement (if posible) destructive methods that would otherwise raise
69
+
70
+ def replace(val)
71
+ self.set(val)
72
+ val
73
+ end
74
+
75
+ def clear
76
+ self.replace('')
77
+ end
78
+
79
+ def force_encoding(enc)
80
+ @encoding = enc
81
+ end
82
+
83
+ ## raise destructive methods if not implemted
84
+
85
+ def insert(ind, val)
86
+ raise NotImplementedError
87
+ end
88
+
89
+ ## implementing scalar type required methods ##
90
+
91
+ def serialize(val)
92
+ ## use the encoding of the first val were sent unless expicitly set
93
+ if @encoding.nil?
94
+ @encoding = if val.respond_to?(:encoding)
95
+ val.encoding
96
+ else
97
+ 'US-ASCII'
98
+ end
99
+ end
100
+ if val.respond_to?(:encode)
101
+ val.encode(@encoding)
102
+ else
103
+ val
104
+ end
105
+ end
106
+
107
+ def deserialize(val)
108
+ if @encoding.nil? || !val.respond_to?(:force_encoding)
109
+ val
110
+ else
111
+ val.force_encoding(@encoding)
112
+ end
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,62 @@
1
+ require 'roc/objects/base'
2
+ module ROC
3
+ class Time < Base
4
+ include ROC::Types::ScalarType
5
+
6
+ delegate_methods :on => ::Time.now, :to => :value
7
+
8
+ def to_time
9
+ v = self.value
10
+ if v.nil?
11
+ ::Time.at(0)
12
+ else
13
+ v
14
+ end
15
+ end
16
+
17
+ def to_s
18
+ self.to_time.to_s
19
+ end
20
+
21
+ ## implement (if posible) destructive methods that would otherwise raise
22
+
23
+ def localtime(offset=nil)
24
+ if (0 == ::Time.now.method(:localtime).arity) && !offset.nil?
25
+ raise ArgumentError, "1.8 Time#localtime doesn't take an arg"
26
+ else
27
+ @offset = offset
28
+ end
29
+ self
30
+ end
31
+
32
+ ## implementing scalar type required methods ##
33
+
34
+ def serialize(val)
35
+ if ::Time.now.respond_to?(:nsec)
36
+ val.to_i.to_s + '.' + val.nsec.to_s ##strait to_f loses precision
37
+ else
38
+ val.to_i.to_s + '.' + val.usec.to_s ##strait to_f loses precision
39
+ end
40
+ end
41
+
42
+ def deserialize(val)
43
+ if val.nil?
44
+ nil
45
+ else
46
+ parts = val.split('.')
47
+ t = if ::Time.now.respond_to?(:nsec)
48
+ ::Time.at(parts[0].to_i, (parts[1].to_i / 1000))
49
+ else
50
+ ::Time.at(parts[0].to_i, parts[1].to_i)
51
+ end
52
+ if defined?(@offset)
53
+ if ::Time.now.method(:localtime).arity > 0
54
+ t.localtime(@offset)
55
+ end
56
+ end
57
+ t
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,11 @@
1
+ require 'roc/objects/string'
2
+ require 'roc/objects/integer'
3
+ require 'roc/objects/float'
4
+ require 'roc/objects/time'
5
+ require 'roc/objects/lock'
6
+
7
+ require 'roc/objects/list'
8
+ require 'roc/objects/set'
9
+ require 'roc/objects/sorted_set'
10
+
11
+ require 'roc/objects/hash'
@@ -0,0 +1,74 @@
1
+ module ROC
2
+ module Store
3
+ module ObjectInitializers
4
+
5
+ def init(klass, key, *seed_data_and_options)
6
+ klass.new(key, self, *seed_data_and_options)
7
+ end
8
+
9
+ def find(key)
10
+ if klass = class_for_key(key)
11
+ init(klass, key)
12
+ else
13
+ nil
14
+ end
15
+ end
16
+
17
+ def class_for_key(key)
18
+ case t = self.call(:type, key)
19
+ when 'string'
20
+ ROC::String
21
+ when 'list'
22
+ ROC::List
23
+ when 'set'
24
+ ROC::Set
25
+ when 'zset'
26
+ ROC::SortedSet
27
+ when 'hash'
28
+ ROC::Hash
29
+ when 'none'
30
+ nil
31
+ else
32
+ raise "unknown type: #{t}"
33
+ end
34
+ end
35
+
36
+ def init_string(key, *seed_data_and_options)
37
+ init(ROC::String, key, *seed_data_and_options)
38
+ end
39
+
40
+ def init_integer(key, *seed_data_and_options)
41
+ init(ROC::Integer, key, *seed_data_and_options)
42
+ end
43
+
44
+ def init_float(key, *seed_data_and_options)
45
+ init(ROC::Float, key, *seed_data_and_options)
46
+ end
47
+
48
+ def init_time(key, *seed_data_and_options)
49
+ init(ROC::Time, key, *seed_data_and_options)
50
+ end
51
+
52
+ def init_lock(key, *seed_data_and_options)
53
+ init(ROC::Lock, key, *seed_data_and_options)
54
+ end
55
+
56
+ def init_list(key, *seed_data_and_options)
57
+ init(ROC::List, key, *seed_data_and_options)
58
+ end
59
+
60
+ def init_set(key, *seed_data_and_options)
61
+ init(ROC::Set, key, *seed_data_and_options)
62
+ end
63
+
64
+ def init_sorted_set(key, *seed_data_and_options)
65
+ init(ROC::SortedSet, key, *seed_data_and_options)
66
+ end
67
+
68
+ def init_hash(key, *seed_data_and_options)
69
+ init(ROC::Hash, key, *seed_data_and_options)
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,7 @@
1
+ class Redis
2
+
3
+ def eval(script, num_key_args, *args)
4
+ @client.call(:eval, script, num_key_args, *args)
5
+ end
6
+
7
+ end
@@ -0,0 +1,76 @@
1
+ if RUBY_VERSION.match(/^1\.8/)
2
+ require 'rubygems'
3
+ end
4
+ require 'redis'
5
+ require 'roc/ext/redis_ext'
6
+ require 'roc/store/roc_store'
7
+ require 'roc/store/object_initializers'
8
+
9
+ require 'forwardable'
10
+
11
+ module ROC
12
+ module Store
13
+ class RedisStore < ROCStore
14
+ include ObjectInitializers
15
+ extend Forwardable
16
+
17
+ attr_reader :connection
18
+
19
+ def initialize(connection)
20
+ if connection.is_a?(Redis)
21
+ @connection = connection
22
+ else
23
+ @connection = Redis.connect(connection)
24
+ end
25
+ end
26
+
27
+ def call(method_name, *args)
28
+ self.connection.send method_name, *args
29
+ end
30
+
31
+ def_delegators :connection, :watch, :unwatch, :flushdb
32
+
33
+ def multi
34
+ @in_multi = true
35
+ if block_given?
36
+ ret = self.connection.multi do
37
+ yield
38
+ end
39
+ @in_multi = false
40
+ else
41
+ ret = self.connection.multi
42
+ end
43
+ ret
44
+ end
45
+
46
+ def exec
47
+ ret = self.connection.exec
48
+ if @in_multi
49
+ @in_multi = false
50
+ end
51
+ ret
52
+ end
53
+
54
+ def discard
55
+ ret = self.connection.discard
56
+ if @in_multi
57
+ @in_multi = false
58
+ end
59
+ ret
60
+ end
61
+
62
+ def in_multi?
63
+ !!@in_multi
64
+ end
65
+
66
+ def inspect
67
+ "<#{self.class} @connection=#{self.connection.inspect}>"
68
+ end
69
+
70
+ def enable_eval
71
+ require 'roc/store/redis_eval'
72
+ end
73
+
74
+ end
75
+ end
76
+ end