super_queue 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/super_queue.rb +59 -33
- metadata +3 -3
data/lib/super_queue.rb
CHANGED
@@ -20,12 +20,13 @@ class SuperQueue
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def initialize(opts)
|
23
|
-
AWS.eager_autoload! # for thread safety
|
24
23
|
check_opts(opts)
|
25
24
|
@buffer_size = opts[:buffer_size] || 100
|
26
25
|
@queue_name = generate_queue_name(opts)
|
27
26
|
@bucket_name = opts[:bucket_name] || queue_name
|
28
|
-
@
|
27
|
+
@write_count = 0
|
28
|
+
@read_count = 0
|
29
|
+
@delete_count = 0
|
29
30
|
initialize_aws(opts)
|
30
31
|
|
31
32
|
@waiting = []
|
@@ -44,6 +45,8 @@ class SuperQueue
|
|
44
45
|
raise @gc_error
|
45
46
|
end
|
46
47
|
end
|
48
|
+
|
49
|
+
fill_out_buffer_from_sqs_queue
|
47
50
|
end
|
48
51
|
|
49
52
|
def push(p)
|
@@ -78,8 +81,7 @@ class SuperQueue
|
|
78
81
|
def length
|
79
82
|
check_for_errors
|
80
83
|
@mutex.synchronize {
|
81
|
-
|
82
|
-
return sqsl + @in_buffer.size + @out_buffer.size
|
84
|
+
return sqs_length + @in_buffer.size + @out_buffer.size
|
83
85
|
}
|
84
86
|
end
|
85
87
|
|
@@ -89,7 +91,9 @@ class SuperQueue
|
|
89
91
|
end
|
90
92
|
|
91
93
|
def empty?
|
92
|
-
|
94
|
+
len = 0
|
95
|
+
2.times { len += self.length; sleep(0.01) }
|
96
|
+
len == 0
|
93
97
|
end
|
94
98
|
|
95
99
|
def clear
|
@@ -116,7 +120,7 @@ class SuperQueue
|
|
116
120
|
|
117
121
|
def sqs_requests
|
118
122
|
check_for_errors
|
119
|
-
@
|
123
|
+
@write_count + @read_count + @delete_count
|
120
124
|
end
|
121
125
|
|
122
126
|
alias enq push
|
@@ -163,19 +167,27 @@ class SuperQueue
|
|
163
167
|
end
|
164
168
|
|
165
169
|
def open_s3_bucket
|
166
|
-
|
170
|
+
retryable(:tries => 3) do
|
171
|
+
@s3.buckets[@bucket_name].exists? ? @s3.buckets[@bucket_name] : @s3.buckets.create(@bucket_name)
|
172
|
+
end
|
167
173
|
end
|
168
174
|
|
169
175
|
def find_queue_by_name
|
176
|
+
retries = 0
|
170
177
|
begin
|
171
178
|
@sqs.queues.named(queue_name)
|
172
179
|
rescue AWS::SQS::Errors::NonExistentQueue
|
173
180
|
return nil
|
181
|
+
rescue NoMethodError => e
|
182
|
+
sleep 1
|
183
|
+
retries += 1
|
184
|
+
retry if retries < 5
|
185
|
+
raise e
|
174
186
|
end
|
175
187
|
end
|
176
188
|
|
177
189
|
def new_sqs_queue(opts)
|
178
|
-
@
|
190
|
+
@read_count += 1
|
179
191
|
if opts[:visibility_timeout]
|
180
192
|
@sqs.queues.create(queue_name, { :visibility_timeout => opts[:visibility_timeout] })
|
181
193
|
else
|
@@ -194,8 +206,10 @@ class SuperQueue
|
|
194
206
|
|
195
207
|
def send_messages_to_queue(batches)
|
196
208
|
batches.each do |b|
|
197
|
-
@
|
198
|
-
|
209
|
+
@write_count += 1
|
210
|
+
retryable(:tries => 5) do
|
211
|
+
@sqs_queue.batch_send(b)
|
212
|
+
end if b.any?
|
199
213
|
end
|
200
214
|
end
|
201
215
|
|
@@ -204,18 +218,17 @@ class SuperQueue
|
|
204
218
|
number_of_batches = number_of_messages_to_receive / 10
|
205
219
|
number_of_batches += 1 if number_of_messages_to_receive % 10
|
206
220
|
number_of_batches.times do
|
207
|
-
|
208
|
-
|
209
|
-
messages << message
|
210
|
-
end
|
211
|
-
@request_count += 1
|
221
|
+
retryable(:retries => 5) { messages += @sqs_queue.receive_messages(:limit => 10).compact }
|
222
|
+
@read_count += 1
|
212
223
|
end
|
213
|
-
messages
|
224
|
+
messages.compact
|
214
225
|
end
|
215
226
|
|
216
227
|
def send_payload_to_s3(encoded_message)
|
217
228
|
key = "#{queue_name}/#{Digest::MD5.hexdigest(encoded_message)}"
|
218
|
-
|
229
|
+
key_exists = false
|
230
|
+
retryable(:tries => 5) { key_exists = @bucket.objects[key].exists? }
|
231
|
+
return S3Pointer.new(key) if key_exists
|
219
232
|
retryable(:tries => 5) { @bucket.objects[key].write(encoded_message, :reduced_redundancy => true) }
|
220
233
|
S3Pointer.new(key)
|
221
234
|
end
|
@@ -239,24 +252,32 @@ class SuperQueue
|
|
239
252
|
end
|
240
253
|
|
241
254
|
def sqs_length
|
242
|
-
n =
|
255
|
+
n = 0
|
256
|
+
retryable(:retries => 5) { n = @sqs_queue.approximate_number_of_messages }
|
257
|
+
@read_count += 1
|
243
258
|
return n.is_a?(Integer) ? n : 0
|
244
259
|
end
|
245
260
|
|
246
261
|
def delete_aws_resources
|
247
|
-
@
|
262
|
+
@delete_count += 1
|
248
263
|
@sqs_queue.delete
|
249
|
-
|
264
|
+
begin
|
265
|
+
@bucket.clear!
|
266
|
+
sleep 1
|
267
|
+
end until @bucket.empty?
|
268
|
+
@bucket.delete
|
250
269
|
end
|
251
270
|
|
252
271
|
def clear_deletion_queue
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
272
|
+
retryable(:tries => 4) do
|
273
|
+
while !@deletion_queue.empty?
|
274
|
+
sqs_handles = @deletion_queue[0..9].map { |m| m[:sqs_handle].is_a?(AWS::SQS::ReceivedMessage) ? m[:sqs_handle] : nil }.compact
|
275
|
+
s3_keys = @deletion_queue[0..9].map { |m| m[:s3_key] }.compact
|
276
|
+
10.times { @deletion_queue.shift }
|
277
|
+
@sqs_queue.batch_delete(sqs_handles) if sqs_handles.any?
|
278
|
+
s3_keys.each { |key| @bucket.objects[key].delete }
|
279
|
+
@delete_count += 1
|
280
|
+
end
|
260
281
|
end
|
261
282
|
end
|
262
283
|
|
@@ -266,7 +287,7 @@ class SuperQueue
|
|
266
287
|
def fill_out_buffer_from_sqs_queue
|
267
288
|
return false if sqs_length == 0
|
268
289
|
nil_count = 0
|
269
|
-
while (@out_buffer.size < @buffer_size) && (nil_count <
|
290
|
+
while (@out_buffer.size < @buffer_size) && (nil_count < 5)
|
270
291
|
messages = get_messages_from_queue(@buffer_size - @out_buffer.size)
|
271
292
|
if messages.any?
|
272
293
|
messages.each do |message|
|
@@ -276,14 +297,18 @@ class SuperQueue
|
|
276
297
|
:payload => obj,
|
277
298
|
:sqs_handle => message)
|
278
299
|
else
|
279
|
-
p = fetch_payload_from_s3(obj)
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
300
|
+
if p = fetch_payload_from_s3(obj)
|
301
|
+
@out_buffer.push(
|
302
|
+
:payload => p,
|
303
|
+
:sqs_handle => message,
|
304
|
+
:s3_key => obj.s3_key)
|
305
|
+
else
|
306
|
+
@deletion_buffer.push(:sqs_handle => message, :s3_key => obj.s3_key)
|
307
|
+
end
|
284
308
|
end
|
285
309
|
end
|
286
310
|
nil_count = 0
|
311
|
+
sleep 0.01
|
287
312
|
else
|
288
313
|
nil_count += 1
|
289
314
|
end
|
@@ -414,6 +439,7 @@ class SuperQueue
|
|
414
439
|
@mutex.synchronize { fill_deletion_queue_from_buffer } if @deletion_buffer.any?
|
415
440
|
Thread.pass
|
416
441
|
@mutex.synchronize { clear_deletion_queue } if @deletion_queue.any?
|
442
|
+
sleep 1
|
417
443
|
end
|
418
444
|
end
|
419
445
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: super_queue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.3
|
5
4
|
prerelease:
|
5
|
+
version: 0.3.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jon Stokes
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-sdk
|
@@ -56,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
56
|
none: false
|
57
57
|
requirements: []
|
58
58
|
rubyforge_project:
|
59
|
-
rubygems_version: 1.8.
|
59
|
+
rubygems_version: 1.8.24
|
60
60
|
signing_key:
|
61
61
|
specification_version: 3
|
62
62
|
summary: A thread-safe, SQS- and S3-backed queue structure for ruby that works just like a normal queue, except it's essentially infinite and can use very little memory.
|