rufus-sqs 0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.txt +89 -0
  2. data/lib/rufus/sqs.rb +569 -0
  3. data/test/test.rb +87 -0
  4. metadata +64 -0
@@ -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
+
@@ -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
+
@@ -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