redis-roc 0.5.0

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.
@@ -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