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