rufus-sqs 0.8
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.
- data/README.txt +89 -0
- data/lib/rufus/sqs.rb +569 -0
- data/test/test.rb +87 -0
- metadata +64 -0
data/README.txt
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
|
2
|
+
= rufus-sqs
|
3
|
+
|
4
|
+
|
5
|
+
== getting it
|
6
|
+
|
7
|
+
sudo gem install -y rufus-sqs
|
8
|
+
|
9
|
+
or at
|
10
|
+
|
11
|
+
http://rubyforge.org/frs/?group_id=4812
|
12
|
+
|
13
|
+
|
14
|
+
== usage
|
15
|
+
|
16
|
+
At first, 'rufus-sqs' expects to find the Amazon WebServices keys in four environment variables : AMAZON_KEY_ID, AMAZON_ACCESS_KEY_ID, AMAZON_ACCESS_KEY and AMAZON_SECRET_ACCESS_KEY
|
17
|
+
|
18
|
+
(Like the gem "aws-s3" http://amazon.rubyforge.org/ does).
|
19
|
+
|
20
|
+
|
21
|
+
For example, I store them in a file named .amazon that gets loaded when necessary :
|
22
|
+
|
23
|
+
export AMAZON_KEY_ID=171A375Y3DY838652G2
|
24
|
+
export AMAZON_ACCESS_KEY_ID=17r37R45YZDY252G2
|
25
|
+
|
26
|
+
export AMAZON_ACCESS_KEY=iOML8QLPy5DB5sCUoS0LbJcA2/OChUUNky
|
27
|
+
export AMAZON_SECRET_ACCESS_KEY=ibMU8QfPDB5sCUgS0NLbScA2/OChUHNy
|
28
|
+
|
29
|
+
|
30
|
+
Some example code :
|
31
|
+
|
32
|
+
qs = Rufus::SQS::QueueService.new
|
33
|
+
|
34
|
+
qs.create_queue "mytestqueue"
|
35
|
+
|
36
|
+
msg = "hello SQS world !"
|
37
|
+
|
38
|
+
msg_id = qs.put_message "mytestqueue", msg
|
39
|
+
|
40
|
+
put msg_id
|
41
|
+
# will print something like
|
42
|
+
# 0MQFS772Z73BG5R9QD6V|A717CAQHX0CS7N69WY71|M57DGQ7TB7T3MFY3J1X0
|
43
|
+
|
44
|
+
sleep 1
|
45
|
+
|
46
|
+
msgs = qs.get_messages "mytestqueue"
|
47
|
+
|
48
|
+
puts msgs[0].message_body
|
49
|
+
# => 'hello SQS world !"
|
50
|
+
|
51
|
+
qs.delete_queue "mytestqueue"
|
52
|
+
|
53
|
+
more at Rufus::SQS::QueueService
|
54
|
+
|
55
|
+
|
56
|
+
= dependencies
|
57
|
+
|
58
|
+
The gem 'rufus-verbs' (http://rufus.rubyforge.org/rufus-verbs) and its dependencies.
|
59
|
+
|
60
|
+
|
61
|
+
== mailing list
|
62
|
+
|
63
|
+
On the rufus-ruby list[http://groups.google.com/group/rufus-ruby] :
|
64
|
+
|
65
|
+
http://groups.google.com/group/rufus-ruby
|
66
|
+
|
67
|
+
|
68
|
+
== issue tracker
|
69
|
+
|
70
|
+
http://rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse
|
71
|
+
|
72
|
+
|
73
|
+
== source
|
74
|
+
|
75
|
+
http://rufus.rubyforge.org/svn/trunk/sqs
|
76
|
+
|
77
|
+
svn checkout http://rufus.rubyforge.org/svn/trunk/sqs
|
78
|
+
|
79
|
+
|
80
|
+
== author
|
81
|
+
|
82
|
+
John Mettraux, jmettraux@gmail.com
|
83
|
+
http://jmettraux.wordpress.com
|
84
|
+
|
85
|
+
|
86
|
+
== license
|
87
|
+
|
88
|
+
MIT
|
89
|
+
|
data/lib/rufus/sqs.rb
ADDED
@@ -0,0 +1,569 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2007-2008, John Mettraux, jmettraux@gmail.com
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
#
|
24
|
+
|
25
|
+
#
|
26
|
+
# Made in Japan
|
27
|
+
#
|
28
|
+
# John dot Mettraux at OpenWFE dot org
|
29
|
+
#
|
30
|
+
|
31
|
+
require 'base64'
|
32
|
+
require 'cgi'
|
33
|
+
require 'net/https'
|
34
|
+
require 'rexml/document'
|
35
|
+
require 'time'
|
36
|
+
require 'pp'
|
37
|
+
|
38
|
+
require 'rubygems'
|
39
|
+
require 'rufus/verbs'
|
40
|
+
|
41
|
+
|
42
|
+
module Rufus
|
43
|
+
module SQS
|
44
|
+
|
45
|
+
#
|
46
|
+
# An SQS message (after its creation).
|
47
|
+
#
|
48
|
+
class Message
|
49
|
+
|
50
|
+
attr_reader :queue, :message_id, :message_body
|
51
|
+
|
52
|
+
def initialize (queue, xml_element)
|
53
|
+
|
54
|
+
@queue = queue
|
55
|
+
@message_id = SQS::get_element_text(xml_element, "MessageId")
|
56
|
+
@message_body = SQS::get_element_text(xml_element, "MessageBody")
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Connects to the queue service and deletes this message in its queue.
|
61
|
+
#
|
62
|
+
def delete
|
63
|
+
|
64
|
+
@queue.queue_service.delete_message(@queue, @message_id)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# An SQS queue (gathering all the necessary info about it
|
70
|
+
# in a single class).
|
71
|
+
#
|
72
|
+
class Queue
|
73
|
+
|
74
|
+
attr_reader :queue_service, :host, :path, :name
|
75
|
+
|
76
|
+
def initialize (queue_service, xml_element)
|
77
|
+
|
78
|
+
@queue_service = queue_service
|
79
|
+
|
80
|
+
s = xml_element.text.to_s
|
81
|
+
m = Regexp.compile('^http://(.*)(/.*)(/.*$)').match(s)
|
82
|
+
@host = m[1]
|
83
|
+
@name = m[3][1..-1]
|
84
|
+
@path = m[2] + m[3]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# As the name implies.
|
90
|
+
#
|
91
|
+
class QueueService
|
92
|
+
|
93
|
+
AWS_VERSION = "2006-04-01"
|
94
|
+
DEFAULT_QUEUE_HOST = "queue.amazonaws.com"
|
95
|
+
|
96
|
+
def initialize (queue_host=nil)
|
97
|
+
|
98
|
+
@queue_host = queue_host || DEFAULT_QUEUE_HOST
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Lists the queues for the active AWS account.
|
103
|
+
# If 'prefix' is given, only queues whose name begin with that
|
104
|
+
# prefix will be returned.
|
105
|
+
#
|
106
|
+
def list_queues (prefix=nil)
|
107
|
+
|
108
|
+
queues = []
|
109
|
+
|
110
|
+
path = "/"
|
111
|
+
path = "#{path}?QueueNamePrefix=#{prefix}" if prefix
|
112
|
+
|
113
|
+
doc = do_action :get, @queue_host, path
|
114
|
+
|
115
|
+
doc.elements.each("//QueueUrl") do |e|
|
116
|
+
queues << Queue.new(self, e)
|
117
|
+
end
|
118
|
+
|
119
|
+
return queues
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# Creates a queue.
|
124
|
+
#
|
125
|
+
# If the queue name doesn't comply with SQS requirements for it,
|
126
|
+
# an error will be raised.
|
127
|
+
#
|
128
|
+
def create_queue (queue_name)
|
129
|
+
|
130
|
+
doc = do_action :post, @queue_host, "/?QueueName=#{queue_name}"
|
131
|
+
|
132
|
+
doc.elements.each("//QueueUrl") do |e|
|
133
|
+
return e.text.to_s
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
#
|
138
|
+
# Given some content ('text/plain' content), send it as a message to
|
139
|
+
# a queue.
|
140
|
+
# Returns the SQS message id (a String).
|
141
|
+
#
|
142
|
+
# The queue might be a queue name (String) or a Queue instance.
|
143
|
+
#
|
144
|
+
def put_message (queue, content)
|
145
|
+
|
146
|
+
queue = resolve_queue(queue)
|
147
|
+
|
148
|
+
doc = do_action :put, queue.host, "#{queue.path}/back", content
|
149
|
+
|
150
|
+
#puts doc.to_s
|
151
|
+
|
152
|
+
#status_code = SQS::get_element_text(doc, '//StatusCode')
|
153
|
+
#message_id = SQS::get_element_text(doc, '//MessageId')
|
154
|
+
#request_id = SQS::get_element_text(doc, '//RequestId')
|
155
|
+
#{ :status_code => status_code,
|
156
|
+
# :message_id => message_id,
|
157
|
+
# :request_id => request_id }
|
158
|
+
|
159
|
+
SQS::get_element_text(doc, '//MessageId')
|
160
|
+
end
|
161
|
+
|
162
|
+
alias :send_message :put_message
|
163
|
+
|
164
|
+
#
|
165
|
+
# Retrieves a bunch of messages from a queue. Returns a list of
|
166
|
+
# Message instances.
|
167
|
+
#
|
168
|
+
# There are actually two optional params that this method understands :
|
169
|
+
#
|
170
|
+
# - :timeout the duration in seconds of the message visibility in the
|
171
|
+
# queue
|
172
|
+
# - :count the max number of message to be returned by this call
|
173
|
+
#
|
174
|
+
# The queue might be a queue name (String) or a Queue instance.
|
175
|
+
#
|
176
|
+
def get_messages (queue, params={})
|
177
|
+
|
178
|
+
queue = resolve_queue(queue)
|
179
|
+
|
180
|
+
path = "#{queue.path}/front"
|
181
|
+
|
182
|
+
path += "?" if params.size > 0
|
183
|
+
|
184
|
+
timeout = params[:timeout]
|
185
|
+
count = params[:count]
|
186
|
+
|
187
|
+
path += "VisibilityTimeout=#{timeout}" if timeout
|
188
|
+
path += "&" if timeout and count
|
189
|
+
path += "NumberOfMessages=#{count}" if count
|
190
|
+
|
191
|
+
doc = do_action :get, queue.host, path
|
192
|
+
|
193
|
+
messages = []
|
194
|
+
|
195
|
+
doc.elements.each("//Message") do |me|
|
196
|
+
messages << Message.new(queue, me)
|
197
|
+
end
|
198
|
+
|
199
|
+
messages
|
200
|
+
end
|
201
|
+
|
202
|
+
#
|
203
|
+
# Retrieves a single message from a queue. Returns an instance of
|
204
|
+
# Message.
|
205
|
+
#
|
206
|
+
# The queue might be a queue name (String) or a Queue instance.
|
207
|
+
#
|
208
|
+
def get_message (queue, message_id)
|
209
|
+
|
210
|
+
queue = resolve_queue(queue)
|
211
|
+
|
212
|
+
path = "#{queue.path}/#{message_id}"
|
213
|
+
|
214
|
+
begin
|
215
|
+
doc = do_action :get, queue.host, path
|
216
|
+
Message.new(queue, doc.root.elements[1])
|
217
|
+
rescue Exception => e
|
218
|
+
#puts e.message
|
219
|
+
return nil if e.message.match "^404 .*$"
|
220
|
+
raise e
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
#
|
225
|
+
# Deletes a given message.
|
226
|
+
#
|
227
|
+
# The queue might be a queue name (String) or a Queue instance.
|
228
|
+
#
|
229
|
+
def delete_message (queue, message_id)
|
230
|
+
|
231
|
+
queue = resolve_queue(queue)
|
232
|
+
|
233
|
+
path = "#{queue.path}/#{message_id}"
|
234
|
+
#path = "#{queue.path}/#{CGI::escape(message_id)}"
|
235
|
+
|
236
|
+
doc = do_action :delete, queue.host, path
|
237
|
+
|
238
|
+
SQS::get_element_text(doc, "//StatusCode") == "Success"
|
239
|
+
end
|
240
|
+
|
241
|
+
#
|
242
|
+
# Use with care !
|
243
|
+
#
|
244
|
+
# Attempts at deleting all the messages in a queue.
|
245
|
+
# Returns the total count of messages deleted.
|
246
|
+
#
|
247
|
+
# A call on this method might take a certain time, as it has
|
248
|
+
# to delete each message individually. AWS will perhaps
|
249
|
+
# add a proper 'flush_queue' method later.
|
250
|
+
#
|
251
|
+
# The queue might be a queue name (String) or a Queue instance.
|
252
|
+
#
|
253
|
+
def flush_queue (queue)
|
254
|
+
|
255
|
+
count = 0
|
256
|
+
|
257
|
+
loop do
|
258
|
+
|
259
|
+
l = get_messages queue, :timeout => 0, :count => 255
|
260
|
+
|
261
|
+
break if l.length < 1
|
262
|
+
|
263
|
+
l.each do |m|
|
264
|
+
m.delete
|
265
|
+
count += 1
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
count
|
270
|
+
end
|
271
|
+
|
272
|
+
#
|
273
|
+
# Deletes the queue. Returns true if the delete was successful.
|
274
|
+
# You can empty a queue by called the method #flush_queue
|
275
|
+
#
|
276
|
+
# If 'force' is set to true, a flush will be performed on the
|
277
|
+
# queue before the actual delete operation. It should ensure
|
278
|
+
# a successful removal of the queue.
|
279
|
+
#
|
280
|
+
def delete_queue (queue, force=false)
|
281
|
+
|
282
|
+
queue = resolve_queue(queue)
|
283
|
+
|
284
|
+
flush_queue(queue) if force
|
285
|
+
|
286
|
+
begin
|
287
|
+
|
288
|
+
doc = do_action :delete, @queue_host, queue.path
|
289
|
+
|
290
|
+
rescue Exception => e
|
291
|
+
|
292
|
+
return false if e.message.match "^400 .*$"
|
293
|
+
end
|
294
|
+
|
295
|
+
SQS::get_element_text(doc, "//StatusCode") == "Success"
|
296
|
+
end
|
297
|
+
|
298
|
+
#
|
299
|
+
# Given a queue name, a Queue instance is returned.
|
300
|
+
#
|
301
|
+
def get_queue (queue_name)
|
302
|
+
|
303
|
+
l = list_queues(queue_name)
|
304
|
+
|
305
|
+
l.each do |q|
|
306
|
+
return q if q.name == queue_name
|
307
|
+
end
|
308
|
+
|
309
|
+
#return nil
|
310
|
+
raise "found no queue named '#{queue_name}'"
|
311
|
+
end
|
312
|
+
|
313
|
+
protected
|
314
|
+
|
315
|
+
#
|
316
|
+
# 'queue' might be a Queue instance or a queue name.
|
317
|
+
# If it's a Queue instance, it is immediately returned,
|
318
|
+
# else the Queue instance is looked up and returned.
|
319
|
+
#
|
320
|
+
def resolve_queue (queue)
|
321
|
+
|
322
|
+
return queue if queue.kind_of?(Queue)
|
323
|
+
get_queue queue.to_s
|
324
|
+
end
|
325
|
+
|
326
|
+
def do_action (action, host, path, content=nil)
|
327
|
+
|
328
|
+
date = Time.now.httpdate
|
329
|
+
|
330
|
+
h = {}
|
331
|
+
|
332
|
+
h['AWS-Version'] = AWS_VERSION
|
333
|
+
h['Date'] = date
|
334
|
+
h['Content-type'] = 'text/plain'
|
335
|
+
|
336
|
+
h['Content-length'] = content.length.to_s if content
|
337
|
+
|
338
|
+
h['Authorization'] = generate_auth_header(
|
339
|
+
action, path, date, "text/plain")
|
340
|
+
|
341
|
+
res = Rufus::Verbs::EndPoint.request(
|
342
|
+
action,
|
343
|
+
:host => host,
|
344
|
+
:path => path,
|
345
|
+
:d => content,
|
346
|
+
:headers => h)
|
347
|
+
|
348
|
+
#case res
|
349
|
+
#when Net::HTTPSuccess, Net::HTTPRedirection
|
350
|
+
# doc = REXML::Document.new(res.read_body)
|
351
|
+
#else
|
352
|
+
# doc = res.error!
|
353
|
+
#end
|
354
|
+
doc = if res.is_a?(Net::HTTPSuccess)
|
355
|
+
REXML::Document.new(res.read_body)
|
356
|
+
else
|
357
|
+
res.error!
|
358
|
+
end
|
359
|
+
|
360
|
+
raise_errors doc
|
361
|
+
|
362
|
+
doc
|
363
|
+
end
|
364
|
+
|
365
|
+
#
|
366
|
+
# Scans the SQS XML reply for potential errors and raises an
|
367
|
+
# error if he encounters one.
|
368
|
+
#
|
369
|
+
def raise_errors (doc)
|
370
|
+
|
371
|
+
doc.elements.each("//Error") do |e|
|
372
|
+
|
373
|
+
code = get_element_text(e, "Code")
|
374
|
+
return unless code
|
375
|
+
|
376
|
+
message = get_element_text(e, "Message")
|
377
|
+
raise "Rufus::SQS::#{code} : #{m.text.to_s}"
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
#
|
382
|
+
# Generates the 'AWS x:y" authorization header value.
|
383
|
+
#
|
384
|
+
def generate_auth_header (action, path, date, content_type)
|
385
|
+
|
386
|
+
s = ""
|
387
|
+
s << action.to_s.upcase
|
388
|
+
s << "\n"
|
389
|
+
|
390
|
+
#s << Base64.encode64(Digest::MD5.digest(content)).strip \
|
391
|
+
# if content
|
392
|
+
#
|
393
|
+
# documented but not necessary (not working)
|
394
|
+
s << "\n"
|
395
|
+
|
396
|
+
s << content_type
|
397
|
+
s << "\n"
|
398
|
+
|
399
|
+
s << date
|
400
|
+
s << "\n"
|
401
|
+
|
402
|
+
i = path.index '?'
|
403
|
+
path = path[0..i-1] if i
|
404
|
+
s << path
|
405
|
+
|
406
|
+
#puts ">>>#{s}<<<"
|
407
|
+
|
408
|
+
digest = OpenSSL::Digest::Digest.new 'sha1'
|
409
|
+
|
410
|
+
key = ENV['AMAZON_SECRET_ACCESS_KEY']
|
411
|
+
|
412
|
+
raise "No $AMAZON_SECRET_ACCESS_KEY env variable found" \
|
413
|
+
unless key
|
414
|
+
|
415
|
+
sig = OpenSSL::HMAC.digest(digest, key, s)
|
416
|
+
sig = Base64.encode64(sig).strip
|
417
|
+
|
418
|
+
"AWS #{ENV['AMAZON_ACCESS_KEY_ID']}:#{sig}"
|
419
|
+
end
|
420
|
+
|
421
|
+
end
|
422
|
+
|
423
|
+
#
|
424
|
+
# A convenience method for returning the text of a sub element,
|
425
|
+
# maybe there is something better in REXML, but I haven't found out
|
426
|
+
# yet.
|
427
|
+
#
|
428
|
+
def SQS.get_element_text (parent_elt, elt_name)
|
429
|
+
|
430
|
+
e = parent_elt.elements[elt_name]
|
431
|
+
return nil unless e
|
432
|
+
e.text.to_s
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
|
437
|
+
#
|
438
|
+
# running directly...
|
439
|
+
|
440
|
+
if $0 == __FILE__
|
441
|
+
|
442
|
+
if ENV['AMAZON_ACCESS_KEY_ID'] == nil or
|
443
|
+
ENV['AMAZON_SECRET_ACCESS_KEY'] == nil
|
444
|
+
|
445
|
+
puts
|
446
|
+
puts "env variables $AMAZON_ACCESS_KEY_ID and $AMAZON_SECRET_ACCESS_KEY are not set"
|
447
|
+
puts
|
448
|
+
exit 1
|
449
|
+
end
|
450
|
+
|
451
|
+
ACTIONS = {
|
452
|
+
:list_queues => :list_queues,
|
453
|
+
:lq => :list_queues,
|
454
|
+
:create_queue => :create_queue,
|
455
|
+
:cq => :create_queue,
|
456
|
+
:delete_queue => :delete_queue,
|
457
|
+
:dq => :delete_queue,
|
458
|
+
:flush_queue => :flush_queue,
|
459
|
+
:fq => :flush_queue,
|
460
|
+
:get_message => :get_message,
|
461
|
+
:gm => :get_message,
|
462
|
+
:delete_message => :delete_message,
|
463
|
+
:dm => :delete_message,
|
464
|
+
:puts_message => :put_message,
|
465
|
+
:pm => :put_message
|
466
|
+
}
|
467
|
+
|
468
|
+
b64 = false
|
469
|
+
queue_host = nil
|
470
|
+
|
471
|
+
require 'optparse'
|
472
|
+
|
473
|
+
opts = OptionParser.new
|
474
|
+
|
475
|
+
opts.banner = "Usage: sqs.rb [options] {action} [queue_name] [message_id]"
|
476
|
+
opts.separator("")
|
477
|
+
opts.separator(" known actions are :")
|
478
|
+
opts.separator("")
|
479
|
+
|
480
|
+
keys = ACTIONS.keys.collect { |k| k.to_s }.sort
|
481
|
+
keys.each { |k| opts.separator(" - '#{k}' (#{ACTIONS[k.intern]})") }
|
482
|
+
|
483
|
+
opts.separator("")
|
484
|
+
opts.separator(" options are :")
|
485
|
+
opts.separator("")
|
486
|
+
|
487
|
+
opts.on("-H", "--host", "AWS queue host") do |host|
|
488
|
+
queue_host = host
|
489
|
+
end
|
490
|
+
|
491
|
+
opts.on("-h", "--help", "displays this help / usage") do
|
492
|
+
STDERR.puts "\n#{opts.to_s}\n"
|
493
|
+
exit 0
|
494
|
+
end
|
495
|
+
|
496
|
+
opts.on("-b", "--base64", "encode/decode messages with base64") do
|
497
|
+
b64 = true
|
498
|
+
end
|
499
|
+
|
500
|
+
argv = opts.parse(ARGV)
|
501
|
+
|
502
|
+
if argv.length < 1
|
503
|
+
STDERR.puts "\n#{opts.to_s}\n"
|
504
|
+
exit 0
|
505
|
+
end
|
506
|
+
|
507
|
+
a = argv[0]
|
508
|
+
queue_name = argv[1]
|
509
|
+
message_id = argv[2]
|
510
|
+
|
511
|
+
action = ACTIONS[a.intern]
|
512
|
+
|
513
|
+
unless action
|
514
|
+
STDERR.puts "unknown action '#{a}'"
|
515
|
+
exit 1
|
516
|
+
end
|
517
|
+
|
518
|
+
qs = SQS::QueueService.new
|
519
|
+
|
520
|
+
STDERR.puts "#{action.to_s}..."
|
521
|
+
|
522
|
+
#
|
523
|
+
# just do it
|
524
|
+
|
525
|
+
case action
|
526
|
+
when :list_queues, :create_queue, :delete_queue, :flush_queue
|
527
|
+
|
528
|
+
pp qs.send(action, queue_name)
|
529
|
+
|
530
|
+
when :get_message
|
531
|
+
|
532
|
+
if message_id
|
533
|
+
m = qs.get_message(queue_name, message_id)
|
534
|
+
body = m.message_body
|
535
|
+
body = Base64.decode64(body) if b64
|
536
|
+
puts body
|
537
|
+
else
|
538
|
+
pp qs.get_messages(queue_name, :timeout => 0, :count => 255)
|
539
|
+
end
|
540
|
+
|
541
|
+
when :delete_message
|
542
|
+
|
543
|
+
raise "argument 'message_id' is missing" unless message_id
|
544
|
+
pp qs.delete_message(queue_name, message_id)
|
545
|
+
|
546
|
+
when :put_message
|
547
|
+
|
548
|
+
message = argv[2]
|
549
|
+
|
550
|
+
unless message
|
551
|
+
message = ""
|
552
|
+
while true
|
553
|
+
s = STDIN.gets()
|
554
|
+
break if s == nil
|
555
|
+
message += s[0..-2]
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
message = Base64.encode64(message).strip if b64
|
560
|
+
|
561
|
+
pp qs.put_message(queue_name, message)
|
562
|
+
else
|
563
|
+
|
564
|
+
STDERR.puts "not yet implemented..."
|
565
|
+
end
|
566
|
+
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
data/test/test.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# testing the sqs with yaml messages
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
require 'yaml'
|
9
|
+
require 'base64'
|
10
|
+
|
11
|
+
require 'rufus/sqs'
|
12
|
+
|
13
|
+
|
14
|
+
class SqsTest < Test::Unit::TestCase
|
15
|
+
|
16
|
+
#def setup
|
17
|
+
#end
|
18
|
+
|
19
|
+
#def teardown
|
20
|
+
#end
|
21
|
+
|
22
|
+
def test_usage
|
23
|
+
|
24
|
+
qs = Rufus::SQS::QueueService.new
|
25
|
+
|
26
|
+
qs.create_queue "mytestqueue"
|
27
|
+
|
28
|
+
msg = "hello SQS world !"
|
29
|
+
|
30
|
+
msg_id = qs.put_message "mytestqueue", msg
|
31
|
+
|
32
|
+
sleep 1
|
33
|
+
|
34
|
+
msgs = qs.get_messages "mytestqueue"
|
35
|
+
|
36
|
+
assert_equal 1, msgs.size
|
37
|
+
assert_equal msg, msgs[0].message_body
|
38
|
+
|
39
|
+
qs.delete_queue "mytestqueue"
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_0
|
43
|
+
|
44
|
+
hash = {
|
45
|
+
:red => :color,
|
46
|
+
:count => "twelve",
|
47
|
+
"fish" => "sakana",
|
48
|
+
:llen => 4,
|
49
|
+
:list => [ 0, 1, 2, 3, 4, :fizz ]
|
50
|
+
}
|
51
|
+
|
52
|
+
qs = Rufus::SQS::QueueService.new
|
53
|
+
|
54
|
+
qs.create_queue(:yamltest)
|
55
|
+
|
56
|
+
puts "created queue 'yamltest'"
|
57
|
+
|
58
|
+
msg = YAML.dump(hash)
|
59
|
+
msg = Base64.encode64(msg)
|
60
|
+
|
61
|
+
puts "message size is #{msg.size.to_f / 1024.0} K"
|
62
|
+
|
63
|
+
msg_id = qs.put_message(:yamltest, msg)
|
64
|
+
|
65
|
+
puts "sent hash as message, msg_id is #{msg_id}"
|
66
|
+
|
67
|
+
sleep 1
|
68
|
+
|
69
|
+
msg = qs.get_message(:yamltest, msg_id)
|
70
|
+
|
71
|
+
puts "got message back"
|
72
|
+
|
73
|
+
msg = Base64.decode64(msg.message_body)
|
74
|
+
msg = YAML.load(msg)
|
75
|
+
|
76
|
+
pp msg
|
77
|
+
|
78
|
+
assert_equal msg, hash
|
79
|
+
|
80
|
+
count = qs.flush_queue(:yamltest)
|
81
|
+
|
82
|
+
puts "flushed #{count} messages from queue 'yamltest'"
|
83
|
+
|
84
|
+
qs.delete_queue(:yamltest)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rufus-sqs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.8"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Mettraux
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-02-03 00:00:00 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rufus-verbs
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
description:
|
25
|
+
email: jmettraux@gmail.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- README.txt
|
32
|
+
files:
|
33
|
+
- lib/rufus
|
34
|
+
- lib/rufus/sqs.rb
|
35
|
+
- test/test.rb
|
36
|
+
- README.txt
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://rufus.rubyforge.org/rufus-sqs
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements:
|
57
|
+
- rufus-verbs
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 0.9.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 2
|
62
|
+
summary: A Ruby library for Amazon SQS (gem previously known as 'openwferu-sqs'
|
63
|
+
test_files:
|
64
|
+
- test/test.rb
|