right_aws 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -110,3 +110,25 @@ Initial release.
110
110
  * SDB support added.
111
111
  * RightAws::S3::bucket and RightAws::S3::Bucket.create methods behaviour
112
112
  changed: param +create+ is set to +false+ by default.
113
+
114
+ == 1.6.0
115
+
116
+ r2780 | todd | 2008-02-11 11:41:07 -0800 (Mon, 11 Feb 2008) | 4 lines
117
+ Some doc updates & tweaks: we now support ultra-large PUTs to S3, small SDB
118
+ cleanups, add SDB to the list of interfaces in RightAws, update some copyrights,
119
+ warn about loading attachment_fu AFTER right_aws (big no-no).
120
+
121
+ r2784 | todd | 2008-02-11 13:46:47 -0800 (Mon, 11 Feb 2008) | 2 lines
122
+ One final clarification: you may get a Net::HTTP bad monkey patch exception
123
+
124
+ r2880 | todd | 2008-02-25 18:06:22 -0800 (Mon, 25 Feb 2008) | 2 lines
125
+ Add SQS 'Gen 2' interface implementation
126
+
127
+ r2913 | todd | 2008-02-29 16:57:07 -0800 (Fri, 29 Feb 2008) | 3 lines
128
+ SqsGen2 (object interface), unit tests for both interfaces, documentation
129
+ updates.
130
+
131
+ r2922 | todd | 2008-03-03 15:26:42 -0800 (Mon, 03 Mar 2008) | 2 lines
132
+ couple of documentation tweaks in prep for 1.6.0
133
+
134
+
data/Manifest.txt CHANGED
@@ -12,6 +12,8 @@ lib/s3/right_s3_interface.rb
12
12
  lib/sdb/right_sdb_interface.rb
13
13
  lib/sqs/right_sqs.rb
14
14
  lib/sqs/right_sqs_interface.rb
15
+ lib/sqs/right_sqs_gen2.rb
16
+ lib/sqs/right_sqs_gen2_interface.rb
15
17
  test/ec2/test_helper.rb
16
18
  test/ec2/test_right_ec2.rb
17
19
  test/s3/test_helper.rb
@@ -21,6 +23,7 @@ test/sdb/test_right_sdb.rb
21
23
  test/sdb/test_helper.rb
22
24
  test/sqs/test_helper.rb
23
25
  test/sqs/test_right_sqs.rb
26
+ test/sqs/test_right_sqs_gen2.rb
24
27
  test/ts_right_aws.rb
25
28
  test/test_credentials.rb
26
29
  test/http_connection.rb
data/README.txt CHANGED
@@ -9,7 +9,8 @@ The RightScale AWS gems have been designed to provide a robust, fast, and secure
9
9
 
10
10
  - RightAws::Ec2 -- interface to Amazon EC2 (Elastic Compute Cloud)
11
11
  - RightAws::S3 and RightAws::S3Interface -- interface to Amazon S3 (Simple Storage Service)
12
- - RightAws::Sqs and RightAws::SqsInterface -- interface to Amazon SQS (Simple Queue Service)
12
+ - RightAws::Sqs and RightAws::SqsInterface -- interface to first-generation Amazon SQS (Simple Queue Service) (API version 2007-05-01)
13
+ - RightAws::SqsGen2 and RightAws::SqsGen2Interface -- interface to second-generation Amazon SQS (Simple Queue Service) (API version 2008-01-01)
13
14
  - RightAws::SdbInterface -- interface to Amazon SDB (SimpleDB)
14
15
 
15
16
  == FEATURES:
@@ -31,6 +32,8 @@ The RightScale AWS gems have been designed to provide a robust, fast, and secure
31
32
  - Support for streaming GETs from S3, and streaming PUTs to S3 if the data source is a file.
32
33
  - Support for single-threaded usage, multithreaded usage, as well as usage with multiple
33
34
  AWS accounts.
35
+ - Support for both first- and second-generation SQS (API versions 2007-05-01
36
+ and 2008-01-01). These versions of SQS are not compatible.
34
37
  - Test suite (requires AWS account to do "live" testing).
35
38
 
36
39
  == THREADING:
@@ -66,8 +69,14 @@ multithreaded mode.
66
69
  http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=87
67
70
  * For S3 read RightAws::S3 and consult the Amazon S3 API documentation at
68
71
  http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=48
69
- * For SQS read RightAws::Sqs and consult the Amazon SQS API documentation at
72
+ * For first generation SQS read RightAws::Sqs and consult the Amazon SQS API documentation at
70
73
  http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=31
74
+ * For second generation SQS read RightAws::SqsGen2, RightAws::SqsGen2Interface and consult the Amazon SQS API documentation at
75
+ http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1214&categoryID=31
76
+
77
+ Amazon's Migration Guide for moving from first to second generation SQS is
78
+ avalable at:
79
+ http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1148
71
80
  * For SDB read RightAws::Sdb and consult the Amazon SDB API documentation at
72
81
  http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=141
73
82
 
data/Rakefile CHANGED
@@ -9,6 +9,18 @@ require 'lib/right_aws.rb'
9
9
 
10
10
  testglobs = ["test/ts_right_aws.rb"]
11
11
 
12
+
13
+ # Suppress Hoe's self-inclusion as a dependency for our Gem. This also keeps
14
+ # Rake & rubyforge out of the dependency list. Users must manually install
15
+ # these gems to run tests, etc.
16
+ class Hoe
17
+ def extra_deps
18
+ @extra_deps.reject do |x|
19
+ Array(x).first == 'hoe'
20
+ end
21
+ end
22
+ end
23
+
12
24
  Hoe.new('right_aws', RightAws::VERSION::STRING) do |p|
13
25
  p.rubyforge_name = 'rightaws'
14
26
  p.author = 'RightScale, Inc.'
@@ -36,6 +48,14 @@ task :testsqs do
36
48
  require 'test/sqs/test_right_sqs.rb'
37
49
  end
38
50
 
51
+ desc "Test just the second generation SQS interface"
52
+ task :testsqs2 do
53
+ require 'test/test_credentials'
54
+ require 'test/http_connection'
55
+ TestCredentials.get_credentials
56
+ require 'test/sqs/test_right_sqs_gen2.rb'
57
+ end
58
+
39
59
  desc "Test just the S3 interface"
40
60
  task :tests3 do
41
61
  require 'test/test_credentials'
@@ -30,6 +30,20 @@ module RightAws
30
30
  Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new("sha1"), aws_secret_access_key, auth_string)).strip
31
31
  end
32
32
 
33
+ # From Amazon's SQS Dev Guide, a brief description of how to escape:
34
+ # "URL encode the computed signature and other query parameters as specified in
35
+ # RFC1738, section 2.2. In addition, because the + character is interpreted as a blank space
36
+ # by Sun Java classes that perform URL decoding, make sure to encode the + character
37
+ # although it is not required by RFC1738."
38
+ # Avoid using CGI::escape to escape URIs.
39
+ # CGI::escape will escape characters in the protocol, host, and port
40
+ # sections of the URI. Only target chars in the query
41
+ # string should be escaped.
42
+ def self.URLencode(raw)
43
+ e = URI.escape(raw)
44
+ e.gsub(/\+/, "%2b")
45
+ end
46
+
33
47
  end
34
48
 
35
49
  class AwsBenchmarkingBlock #:nodoc:
data/lib/right_aws.rb CHANGED
@@ -43,13 +43,15 @@ require 's3/right_s3_interface'
43
43
  require 's3/right_s3'
44
44
  require 'sqs/right_sqs_interface'
45
45
  require 'sqs/right_sqs'
46
+ require 'sqs/right_sqs_gen2_interface'
47
+ require 'sqs/right_sqs_gen2'
46
48
  require 'sdb/right_sdb_interface'
47
49
 
48
50
 
49
51
  module RightAws #:nodoc:
50
52
  module VERSION #:nodoc:
51
53
  MAJOR = 1
52
- MINOR = 5
54
+ MINOR = 6
53
55
  TINY = 0
54
56
 
55
57
  STRING = [MAJOR, MINOR, TINY].join('.')
@@ -0,0 +1,278 @@
1
+ #
2
+ # Copyright (c) 2008 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ #
27
+ # RightAws::SqsGen2 -- RightScale's Amazon SQS interface, API version
28
+ # 2008-01-01 and later.
29
+ # The RightAws::SqsGen2 class provides a complete interface to the second generation of Amazon's Simple
30
+ # Queue Service.
31
+ # For explanations of the semantics
32
+ # of each call, please refer to Amazon's documentation at
33
+ # http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=31
34
+ #
35
+ #
36
+ # RightAws::SqsGen2 is built atop RightAws::SqsGen2Interface, a lower-level
37
+ # procedural API that may be appropriate for certain programs.
38
+ #
39
+ # Error handling: all operations raise an RightAws::AwsError in case
40
+ # of problems. Note that transient errors are automatically retried.
41
+ #
42
+ # sqs = RightAws::SqsGen2.new(aws_access_key_id, aws_secret_access_key)
43
+ # queue1 = sqs.queue('my_awesome_queue')
44
+ # ...
45
+ # queue2 = RightAws::SqsGen2::Queue.create(sqs, 'my_cool_queue', true)
46
+ # puts queue2.size
47
+ # ...
48
+ # message1 = queue2.receive
49
+ # message1.visibility = 0
50
+ # puts message1
51
+ # ...
52
+ # queue2.clear(true)
53
+ # queue2.send_message('Ola-la!')
54
+ # message2 = queue2.pop
55
+ # ...
56
+ #
57
+ # NB: Second-generation SQS has eliminated the entire access grant mechanism present in Gen 1.
58
+ class SqsGen2
59
+ attr_reader :interface
60
+
61
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
62
+ @interface = SqsGen2Interface.new(aws_access_key_id, aws_secret_access_key, params)
63
+ end
64
+
65
+ # Retrieves a list of queues.
66
+ # Returns an +array+ of +Queue+ instances.
67
+ #
68
+ # RightAws::Sqs.queues #=> array of queues
69
+ #
70
+ def queues(prefix=nil)
71
+ @interface.list_queues(prefix).map do |url|
72
+ Queue.new(self, url)
73
+ end
74
+ end
75
+
76
+ # Returns Queue instance by queue name.
77
+ # If the queue does not exist at Amazon SQS and +create+ is true, the method creates it.
78
+ #
79
+ # RightAws::SqsGen2.queue('my_awesome_queue') #=> #<RightAws::SqsGen2::Queue:0xb7b626e4 ... >
80
+ #
81
+ def queue(queue_name, create=true, visibility=nil)
82
+ url = @interface.queue_url_by_name(queue_name)
83
+ url = (create ? @interface.create_queue(queue_name, visibility) : nil) unless url
84
+ url ? Queue.new(self, url) : nil
85
+ end
86
+
87
+
88
+ class Queue
89
+ attr_reader :name, :url, :sqs
90
+
91
+ # Returns Queue instance by queue name.
92
+ # If the queue does not exist at Amazon SQS and +create+ is true, the method creates it.
93
+ #
94
+ # RightAws::SqsGen2::Queue.create(sqs, 'my_awesome_queue') #=> #<RightAws::SqsGen2::Queue:0xb7b626e4 ... >
95
+ #
96
+ def self.create(sqs, url_or_name, create=true, visibility=nil)
97
+ sqs.queue(url_or_name, create, visibility)
98
+ end
99
+
100
+ # Creates new Queue instance.
101
+ # Does not create a queue at Amazon.
102
+ #
103
+ # queue = RightAws::SqsGen2::Queue.new(sqs, 'my_awesome_queue')
104
+ #
105
+ def initialize(sqs, url_or_name)
106
+ @sqs = sqs
107
+ @url = @sqs.interface.queue_url_by_name(url_or_name)
108
+ @name = @sqs.interface.queue_name_by_url(@url)
109
+ end
110
+
111
+ # Retrieves queue size.
112
+ #
113
+ # queue.size #=> 1
114
+ #
115
+ def size
116
+ @sqs.interface.get_queue_length(@url)
117
+ end
118
+
119
+ # Clears queue, deleting only the visible messages. Any message within its visibility
120
+ # timeout will not be deleted, and will re-appear in the queue in the
121
+ # future when the timeout expires.
122
+ #
123
+ # To delete all messages in a queue and eliminate the chance of any
124
+ # messages re-appearing in the future, it's best to delete the queue and
125
+ # re-create it as a new queue. Note that doing this will take at least 60
126
+ # s since SQS does not allow re-creation of a queue within this interval.
127
+ #
128
+ # queue.clear() #=> true
129
+ #
130
+ def clear()
131
+ @sqs.interface.clear_queue(@url)
132
+ end
133
+
134
+ # Deletes queue. Any messages in the queue will be permanently lost.
135
+ # Returns +true+.
136
+ #
137
+ # NB: Use with caution; severe data loss is possible!
138
+ #
139
+ # queue.delete(true) #=> true
140
+ #
141
+ def delete(force=false)
142
+ @sqs.interface.delete_queue(@url)
143
+ end
144
+
145
+ # Sends new message to queue.
146
+ # Returns new Message instance that has been sent to queue.
147
+ def send_message(message)
148
+ message = message.to_s
149
+ res = @sqs.interface.send_message(@url, message)
150
+ msg = Message.new(self, res['MessageId'], nil, message)
151
+ msg.send_checksum = res['MD5OfMessageBody']
152
+ msg.sent_at = Time.now
153
+ msg
154
+ end
155
+ alias_method :push, :send_message
156
+
157
+ # Retrieves several messages from queue.
158
+ # Returns an array of Message instances.
159
+ #
160
+ # queue.receive_messages(2,10) #=> array of messages
161
+ #
162
+ def receive_messages(number_of_messages=1, visibility=nil)
163
+ list = @sqs.interface.receive_message(@url, number_of_messages, visibility)
164
+ list.map! do |entry|
165
+ msg = Message.new(self, entry['MessageId'], entry['ReceiptHandle'],
166
+ entry['Body'], visibility)
167
+ msg.received_at = Time.now
168
+ msg.receive_checksum = entry['MD5OfBody']
169
+ msg
170
+ end
171
+ end
172
+
173
+ # Retrieves first accessible message from queue.
174
+ # Returns Message instance or +nil+ it the queue is empty.
175
+ #
176
+ # queue.receive #=> #<RightAws::SqsGen2::Message:0xb7bf0884 ... >
177
+ #
178
+ def receive(visibility=nil)
179
+ list = receive_messages(1, visibility)
180
+ list.empty? ? nil : list[0]
181
+ end
182
+
183
+ # Pops (and deletes) first accessible message from queue.
184
+ # Returns Message instance or +nil+ it the queue is empty.
185
+ #
186
+ # queue.pop #=> #<RightAws::SqsGen2::Message:0xb7bf0884 ... >
187
+ #
188
+ def pop
189
+ list = @sqs.interface.pop_messages(@url, 1)
190
+ return nil if list == nil
191
+ entry = list[0]
192
+ msg = Message.new(self, entry['MessageId'], entry['ReceiptHandle'],
193
+ entry['Body'], visibility)
194
+ msg.received_at = Time.now
195
+ msg.receive_checksum = entry['MD5OfBody']
196
+ msg
197
+ end
198
+
199
+ # Retrieves +VisibilityTimeout+ value for the queue.
200
+ # Returns new timeout value.
201
+ #
202
+ # queue.visibility #=> 30
203
+ #
204
+ def visibility
205
+ @sqs.interface.get_queue_attributes(@url, 'VisibilityTimeout')['VisibilityTimeout']
206
+ end
207
+
208
+ # Sets new +VisibilityTimeout+ for the queue.
209
+ # Returns new timeout value.
210
+ #
211
+ # queue.visibility #=> 30
212
+ # queue.visibility = 33
213
+ # queue.visibility #=> 33
214
+ #
215
+ def visibility=(visibility_timeout)
216
+ @sqs.interface.set_queue_attributes(@url, 'VisibilityTimeout', visibility_timeout)
217
+ visibility_timeout
218
+ end
219
+
220
+ # Sets new queue attribute value.
221
+ # Not all attributes may be changed: +ApproximateNumberOfMessages+ (for example) is a read only attribute.
222
+ # Returns a value to be assigned to attribute.
223
+ # Currently, 'VisibilityTimeout' is the only settable queue attribute.
224
+ # Attempting to set non-existent attributes generates an indignant
225
+ # exception.
226
+ #
227
+ # queue.set_attribute('VisibilityTimeout', '100') #=> '100'
228
+ # queue.get_attribute('VisibilityTimeout') #=> '100'
229
+ #
230
+ def set_attribute(attribute, value)
231
+ @sqs.interface.set_queue_attributes(@url, attribute, value)
232
+ value
233
+ end
234
+
235
+ # Retrieves queue attributes.
236
+ # At this moment Amazon supports +VisibilityTimeout+ and +ApproximateNumberOfMessages+ only.
237
+ # If the name of attribute is set, returns its value. Otherwise, returns a hash of attributes.
238
+ #
239
+ # queue.get_attribute('VisibilityTimeout') #=> {"VisibilityTimeout"=>"45"}
240
+ #
241
+ def get_attribute(attribute='All')
242
+ attributes = @sqs.interface.get_queue_attributes(@url, attribute)
243
+ attribute=='All' ? attributes : attributes[attribute]
244
+ end
245
+ end
246
+
247
+ class Message
248
+ attr_reader :queue, :id, :body, :visibility, :receipt_handle
249
+ attr_accessor :sent_at, :received_at, :send_checksum, :receive_checksum
250
+
251
+ def initialize(queue, id=nil, rh = nil, body=nil, visibility=nil)
252
+ @queue = queue
253
+ @id = id
254
+ @receipt_handle = rh
255
+ @body = body
256
+ @visibility = visibility
257
+ @sent_at = nil
258
+ @received_at = nil
259
+ @send_checksum = nil
260
+ @receive_checksum = nil
261
+ end
262
+
263
+ # Returns +Message+ instance body.
264
+ def to_s
265
+ @body
266
+ end
267
+
268
+ # Removes message from queue.
269
+ # Returns +true+.
270
+ def delete
271
+ @queue.sqs.interface.delete_message(@queue.url, @receipt_handle) if @receipt_handle
272
+ end
273
+
274
+ end
275
+
276
+
277
+ end
278
+ end
@@ -0,0 +1,449 @@
1
+ #
2
+ # Copyright (c) 2007-2008 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ #
27
+ # Right::Aws::SqsGen2Interface - RightScale's low-level Amazon SQS interface
28
+ # for API version 2008-01-01 and later.
29
+ # For explanations of the semantics
30
+ # of each call, please refer to Amazon's documentation at
31
+ # http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=31
32
+ #
33
+ # This class provides a procedural interface to SQS. Conceptually it is
34
+ # mostly a pass-through interface to SQS and its API is very similar to the
35
+ # bare SQS API. For a somewhat higher-level and object-oriented interface, see
36
+ # RightAws::SqsGen2.
37
+
38
+ class SqsGen2Interface < RightAwsBase
39
+ include RightAwsBaseInterface
40
+
41
+ SIGNATURE_VERSION = "1"
42
+ API_VERSION = "2008-01-01"
43
+ DEFAULT_HOST = "queue.amazonaws.com"
44
+ DEFAULT_PORT = 443
45
+ DEFAULT_PROTOCOL = 'https'
46
+ REQUEST_TTL = 30
47
+ DEFAULT_VISIBILITY_TIMEOUT = 30
48
+
49
+
50
+ @@bench = AwsBenchmarkingBlock.new
51
+ def self.bench_xml
52
+ @@bench.xml
53
+ end
54
+ def self.bench_sqs
55
+ @@bench.service
56
+ end
57
+
58
+ @@api = API_VERSION
59
+ def self.api
60
+ @@api
61
+ end
62
+
63
+ # Creates a new SqsInterface instance. This instance is limited to
64
+ # operations on SQS objects created with Amazon's 2008-01-01 API version. This
65
+ # interface will not work on objects created with prior API versions. See
66
+ # Amazon's article "Migrating to Amazon SQS API version 2008-01-01" at:
67
+ # http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1148
68
+ #
69
+ # sqs = RightAws::SqsGen2Interface.new('1E3GDYEOGFJPIT75KDT40','hgTHt68JY07JKUY08ftHYtERkjgtfERn57DFE379', {:multi_thread => true, :logger => Logger.new('/tmp/x.log')})
70
+ #
71
+ # Params is a hash:
72
+ #
73
+ # {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com' (default)
74
+ # :port => 443 # Amazon service port: 80 or 443 (default)
75
+ # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false (default)
76
+ # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
77
+ #
78
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
79
+ init({ :name => 'SQS',
80
+ :default_host => ENV['SQS_URL'] ? URI.parse(ENV['SQS_URL']).host : DEFAULT_HOST,
81
+ :default_port => ENV['SQS_URL'] ? URI.parse(ENV['SQS_URL']).port : DEFAULT_PORT,
82
+ :default_protocol => ENV['SQS_URL'] ? URI.parse(ENV['SQS_URL']).scheme : DEFAULT_PROTOCOL },
83
+ aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'],
84
+ aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
85
+ params)
86
+ end
87
+
88
+
89
+ #-----------------------------------------------------------------
90
+ # Requests
91
+ #-----------------------------------------------------------------
92
+
93
+ # Generates a request hash for the query API
94
+ def generate_request(action, param={}) # :nodoc:
95
+ # For operation requests on a queue, the queue URI will be a parameter,
96
+ # so we first extract it from the call parameters. Next we remove any
97
+ # parameters with no value or with symbolic keys. We add the header
98
+ # fields required in all requests, and then the headers passed in as
99
+ # params. We sort the header fields alphabetically and then generate the
100
+ # signature before URL escaping the resulting query and sending it.
101
+ queue_uri = param[:queue_url] ? URI(param[:queue_url]).path : '/'
102
+ param.each{ |key, value| param.delete(key) if (value.nil? || key.is_a?(Symbol)) }
103
+ request_hash = { "Action" => action,
104
+ "Expires" => (Time.now + REQUEST_TTL).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
105
+ "AWSAccessKeyId" => @aws_access_key_id,
106
+ "Version" => API_VERSION,
107
+ "SignatureVersion" => SIGNATURE_VERSION }
108
+ request_hash.update(param)
109
+ request_data = request_hash.sort{|a,b| (a[0].to_s.downcase)<=>(b[0].to_s.downcase)}.to_s
110
+ request_hash['Signature'] = AwsUtils::sign(@aws_secret_access_key, request_data)
111
+ request_params = request_hash.to_a.collect{|key,val| key.to_s + "=" + val.to_s }.join("&")
112
+ request = Net::HTTP::Get.new(AwsUtils.URLencode("#{queue_uri}?#{request_params}"))
113
+ # prepare output hash
114
+ { :request => request,
115
+ :server => @params[:server],
116
+ :port => @params[:port],
117
+ :protocol => @params[:protocol] }
118
+ end
119
+
120
+ def generate_post_request(action, param={}) # :nodoc:
121
+ queue_uri = param[:queue_url] ? URI(param[:queue_url]).path : '/'
122
+ message = param[:message] # extract message body if nesessary
123
+ param.each{ |key, value| param.delete(key) if (value.nil? || key.is_a?(Symbol)) }
124
+ request_hash = { "Action" => action,
125
+ "Expires" => (Time.now + REQUEST_TTL).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
126
+ "AWSAccessKeyId" => @aws_access_key_id,
127
+ "MessageBody" => message,
128
+ "Version" => API_VERSION,
129
+ "SignatureVersion" => SIGNATURE_VERSION }
130
+ request_hash.update(param)
131
+ request_data = request_hash.sort{|a,b| (a[0].to_s.downcase)<=>(b[0].to_s.downcase)}.to_s
132
+ request_hash['Signature'] = AwsUtils::sign(@aws_secret_access_key, request_data)
133
+ request_body = request_hash.to_a.collect{|key,val| key.to_s + "=" + val.to_s }.join("&")
134
+ request = Net::HTTP::Post.new(AwsUtils.URLencode(queue_uri))
135
+ request['Content-Type'] = 'application/x-www-form-urlencoded'
136
+ request.body = AwsUtils.URLencode(request_body)
137
+ # prepare output hash
138
+ { :request => request,
139
+ :server => @params[:server],
140
+ :port => @params[:port],
141
+ :protocol => @params[:protocol] }
142
+ end
143
+
144
+
145
+ # Sends request to Amazon and parses the response
146
+ # Raises AwsError if any banana happened
147
+ def request_info(request, parser) # :nodoc:
148
+ thread = @params[:multi_thread] ? Thread.current : Thread.main
149
+ thread[:sqs_connection] ||= Rightscale::HttpConnection.new(:exception => AwsError, :logger => @logger)
150
+ request_info_impl(thread[:sqs_connection], @@bench, request, parser)
151
+ end
152
+
153
+
154
+ # Creates a new queue, returning its URI.
155
+ #
156
+ # sqs.create_queue('my_awesome_queue') #=> 'http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue'
157
+ #
158
+ def create_queue(queue_name, default_visibility_timeout=nil)
159
+ req_hash = generate_request('CreateQueue', 'QueueName' => queue_name,
160
+ 'DefaultVisibilityTimeout' => default_visibility_timeout || DEFAULT_VISIBILITY_TIMEOUT )
161
+ request_info(req_hash, SqsCreateQueueParser.new(:logger => @logger))
162
+ rescue
163
+ on_exception
164
+ end
165
+
166
+ # Lists all queues owned by this user that have names beginning with +queue_name_prefix+.
167
+ # If +queue_name_prefix+ is omitted then retrieves a list of all queues.
168
+ # Queue creation is an eventual operation and created queues may not show up in immediately subsequent list_queues calls.
169
+ #
170
+ # sqs.create_queue('my_awesome_queue')
171
+ # sqs.create_queue('my_awesome_queue_2')
172
+ # sqs.list_queues('my_awesome') #=> ['http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue','http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue_2']
173
+ #
174
+ def list_queues(queue_name_prefix=nil)
175
+ req_hash = generate_request('ListQueues', 'QueueNamePrefix' => queue_name_prefix)
176
+ request_info(req_hash, SqsListQueuesParser.new(:logger => @logger))
177
+ rescue
178
+ on_exception
179
+ end
180
+
181
+ # Deletes queue. Any messages in the queue are permanently lost.
182
+ # Returns +true+ or an exception.
183
+ # Queue deletion can take up to 60 s to propagate through SQS. Thus, after a deletion, subsequent list_queues calls
184
+ # may still show the deleted queue. It is not unusual within the 60 s window to see the deleted queue absent from
185
+ # one list_queues call but present in the subsequent one. Deletion is eventual.
186
+ #
187
+ # sqs.delete_queue('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue_2') #=> true
188
+ #
189
+ #
190
+ def delete_queue(queue_url)
191
+ req_hash = generate_request('DeleteQueue', :queue_url => queue_url)
192
+ request_info(req_hash, SqsStatusParser.new(:logger => @logger))
193
+ rescue
194
+ on_exception
195
+ end
196
+
197
+ # Retrieves the queue attribute(s). Returns a hash of attribute(s) or an exception.
198
+ #
199
+ # sqs.get_queue_attributes('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue')
200
+ # #=> {"ApproximateNumberOfMessages"=>"0", "VisibilityTimeout"=>"30"}
201
+ #
202
+ def get_queue_attributes(queue_url, attribute='All')
203
+ req_hash = generate_request('GetQueueAttributes', 'AttributeName' => attribute, :queue_url => queue_url)
204
+ request_info(req_hash, SqsGetQueueAttributesParser.new(:logger => @logger))
205
+ rescue
206
+ on_exception
207
+ end
208
+
209
+ # Sets queue attribute. Returns +true+ or an exception.
210
+ #
211
+ # sqs.set_queue_attributes('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue', "VisibilityTimeout", 10) #=> true
212
+ #
213
+ # From the SQS Dev Guide:
214
+ # "Currently, you can set only the
215
+ # VisibilityTimeout attribute for a queue...
216
+ # When you change a queue's attributes, the change can take up to 60 seconds to propagate
217
+ # throughout the SQS system."
218
+ #
219
+ # NB: Attribute values may not be immediately available to other queries
220
+ # for some time after an update. See the SQS documentation for
221
+ # semantics, but in general propagation can take up to 60 s.
222
+ def set_queue_attributes(queue_url, attribute, value)
223
+ req_hash = generate_request('SetQueueAttributes', 'Attribute.Name' => attribute, 'Attribute.Value' => value, :queue_url => queue_url)
224
+ request_info(req_hash, SqsStatusParser.new(:logger => @logger))
225
+ rescue
226
+ on_exception
227
+ end
228
+
229
+ # Retrieves a list of messages from queue. Returns an array of hashes in format: <tt>{:id=>'message_id', body=>'message_body'}</tt>
230
+ #
231
+ # sqs.receive_message('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue',10, 5) #=>
232
+ # [{"ReceiptHandle"=>"Euvo62...kw==", "MD5OfBody"=>"16af2171b5b83cfa35ce254966ba81e3",
233
+ # "Body"=>"Goodbyte World!", "MessageId"=>"MUM4WlAyR...pYOTA="}, ..., {}]
234
+ #
235
+ # Normally this call returns fewer messages than the maximum specified,
236
+ # even if they are available.
237
+ #
238
+ def receive_message(queue_url, max_number_of_messages=1, visibility_timeout=nil)
239
+ return [] if max_number_of_messages == 0
240
+ req_hash = generate_post_request('ReceiveMessage', 'MaxNumberOfMessages' => max_number_of_messages, 'VisibilityTimeout' => visibility_timeout,
241
+ :queue_url => queue_url )
242
+ request_info(req_hash, SqsReceiveMessageParser.new(:logger => @logger))
243
+ rescue
244
+ on_exception
245
+ end
246
+
247
+ # Sends a new message to a queue. Message size is limited to 8 KB.
248
+ # If successful, this call returns a hash containing key/value pairs for
249
+ # "MessageId" and "MD5OfMessageBody":
250
+ #
251
+ # sqs.send_message('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue', 'message_1') #=> "1234567890...0987654321"
252
+ # => {"MessageId"=>"MEs4M0JKNlRCRTBBSENaMjROTk58QVFRNzNEREhDVFlFOVJDQ1JKNjF8UTdBRllCUlJUMjhKMUI1WDJSWDE=", "MD5OfMessageBody"=>"16af2171b5b83cfa35ce254966ba81e3"}
253
+ #
254
+ # On failure, send_message raises an exception.
255
+ #
256
+ #
257
+ def send_message(queue_url, message)
258
+ req_hash = generate_post_request('SendMessage', :message => message, :queue_url => queue_url)
259
+ request_info(req_hash, SqsSendMessagesParser.new(:logger => @logger))
260
+ rescue
261
+ on_exception
262
+ end
263
+
264
+ # Same as send_message
265
+ alias_method :push_message, :send_message
266
+
267
+
268
+ # Deletes message from queue. Returns +true+ or an exception. Amazon
269
+ # returns +true+ on deletion of non-existent messages. You must use the
270
+ # receipt handle for a message to delete it, not the message ID.
271
+ #
272
+ # From the SQS Developer Guide:
273
+ # "It is possible you will receive a message even after you have deleted it. This might happen
274
+ # on rare occasions if one of the servers storing a copy of the message is unavailable when
275
+ # you request to delete the message. The copy remains on the server and might be returned to
276
+ # you again on a subsequent receive request. You should create your system to be
277
+ # idempotent so that receiving a particular message more than once is not a problem. "
278
+ #
279
+ # sqs.delete_message('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue', 'Euvo62/1nlIet...ao03hd9Sa0w==') #=> true
280
+ #
281
+ def delete_message(queue_url, receipt_handle)
282
+ req_hash = generate_request('DeleteMessage', 'ReceiptHandle' => receipt_handle, :queue_url => queue_url)
283
+ request_info(req_hash, SqsStatusParser.new(:logger => @logger))
284
+ rescue
285
+ on_exception
286
+ end
287
+
288
+ # Given the queue's short name, this call returns the queue URL or +nil+ if queue is not found
289
+ # sqs.queue_url_by_name('my_awesome_queue') #=> 'http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue'
290
+ #
291
+ def queue_url_by_name(queue_name)
292
+ return queue_name if queue_name.include?('/')
293
+ queue_urls = list_queues(queue_name)
294
+ queue_urls.each do |queue_url|
295
+ return queue_url if queue_name_by_url(queue_url) == queue_name
296
+ end
297
+ nil
298
+ rescue
299
+ on_exception
300
+ end
301
+
302
+ # Returns short queue name by url.
303
+ #
304
+ # RightSqs.queue_name_by_url('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue') #=> 'my_awesome_queue'
305
+ #
306
+ def self.queue_name_by_url(queue_url)
307
+ queue_url[/[^\/]*$/]
308
+ rescue
309
+ on_exception
310
+ end
311
+
312
+ # Returns short queue name by url.
313
+ #
314
+ # sqs.queue_name_by_url('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue') #=> 'my_awesome_queue'
315
+ #
316
+ def queue_name_by_url(queue_url)
317
+ self.class.queue_name_by_url(queue_url)
318
+ rescue
319
+ on_exception
320
+ end
321
+
322
+ # Returns approximate number of messages in queue.
323
+ #
324
+ # sqs.get_queue_length('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue') #=> 3
325
+ #
326
+ def get_queue_length(queue_url)
327
+ get_queue_attributes(queue_url)['ApproximateNumberOfMessages'].to_i
328
+ rescue
329
+ on_exception
330
+ end
331
+
332
+ # Removes all visible messages from queue. Return +true+ or an exception.
333
+ #
334
+ # sqs.clear_queue('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue') #=> true
335
+ #
336
+ def clear_queue(queue_url)
337
+ while (pop_messages(queue_url, 10).length > 0) ; end # delete all messages in queue
338
+ true
339
+ rescue
340
+ on_exception
341
+ end
342
+
343
+ # Pops (retrieves and deletes) up to 'number_of_messages' from queue. Returns an array of retrieved messages in format: <tt>[{:id=>'message_id', :body=>'message_body'}]</tt>.
344
+ #
345
+ # sqs.pop_messages('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue', 3) #=>
346
+ # [{"ReceiptHandle"=>"Euvo62/...+Zw==", "MD5OfBody"=>"16af2...81e3", "Body"=>"Goodbyte World!",
347
+ # "MessageId"=>"MEZI...JSWDE="}, {...}, ... , {...} ]
348
+ #
349
+ def pop_messages(queue_url, number_of_messages=1)
350
+ messages = receive_message(queue_url, number_of_messages)
351
+ messages.each do |message|
352
+ delete_message(queue_url, message['ReceiptHandle'])
353
+ end
354
+ messages
355
+ rescue
356
+ on_exception
357
+ end
358
+
359
+ # Pops (retrieves and deletes) first accessible message from queue. Returns the message in format <tt>{:id=>'message_id', :body=>'message_body'}</tt> or +nil+.
360
+ #
361
+ # sqs.pop_message('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue') #=>
362
+ # {:id=>"12345678904GEZX9746N|0N9ED344VK5Z3SV1DTM0|1RVYH4X3TJ0987654321", :body=>"message_1"}
363
+ #
364
+ def pop_message(queue_url)
365
+ messages = pop_messages(queue_url)
366
+ messages.blank? ? nil : messages[0]
367
+ rescue
368
+ on_exception
369
+ end
370
+
371
+ #-----------------------------------------------------------------
372
+ # PARSERS: Status Response Parser
373
+ #-----------------------------------------------------------------
374
+
375
+ class SqsStatusParser < RightAWSParser # :nodoc:
376
+ def tagend(name)
377
+ if name == 'ResponseMetadata'
378
+ @result = true
379
+ end
380
+ end
381
+ end
382
+
383
+ #-----------------------------------------------------------------
384
+ # PARSERS: Queue
385
+ #-----------------------------------------------------------------
386
+
387
+ class SqsCreateQueueParser < RightAWSParser # :nodoc:
388
+ def tagend(name)
389
+ @result = @text if name == 'QueueUrl'
390
+ end
391
+ end
392
+
393
+ class SqsListQueuesParser < RightAWSParser # :nodoc:
394
+ def reset
395
+ @result = []
396
+ end
397
+ def tagend(name)
398
+ @result << @text if name == 'QueueUrl'
399
+ end
400
+ end
401
+
402
+ class SqsGetQueueAttributesParser < RightAWSParser # :nodoc:
403
+ def reset
404
+ @result = {}
405
+ end
406
+ def tagend(name)
407
+ case name
408
+ when 'Name' ; @current_attribute = @text
409
+ when 'Value' ; @result[@current_attribute] = @text
410
+ end
411
+ end
412
+ end
413
+
414
+ #-----------------------------------------------------------------
415
+ # PARSERS: Messages
416
+ #-----------------------------------------------------------------
417
+
418
+ class SqsReceiveMessageParser < RightAWSParser # :nodoc:
419
+ def reset
420
+ @result = []
421
+ end
422
+ def tagstart(name, attributes)
423
+ @current_message = {} if name == 'Message'
424
+ end
425
+ def tagend(name)
426
+ case name
427
+ when 'MessageId' ; @current_message['MessageId'] = @text
428
+ when 'ReceiptHandle' ; @current_message['ReceiptHandle'] = @text
429
+ when 'MD5OfBody' ; @current_message['MD5OfBody'] = @text
430
+ when 'Body'; @current_message['Body'] = @text; @result << @current_message
431
+ end
432
+ end
433
+ end
434
+
435
+ class SqsSendMessagesParser < RightAWSParser # :nodoc:
436
+ def reset
437
+ @result = {}
438
+ end
439
+ def tagend(name)
440
+ case name
441
+ when 'MessageId' ; @result['MessageId'] = @text
442
+ when 'MD5OfMessageBody' ; @result['MD5OfMessageBody'] = @text
443
+ end
444
+ end
445
+ end
446
+
447
+ end
448
+
449
+ end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2007 RightScale Inc
2
+ # Copyright (c) 2007-2008 RightScale Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -50,7 +50,7 @@ module RightAws
50
50
 
51
51
  # Creates a new SqsInterface instance.
52
52
  #
53
- # sqs = RightAws::SqsInterface.new('1E3GDYEOGFJPIT75KDT40','hgTHt68JY07JKUY08ftHYtERkjgtfERn57DFE379', {:multi_thread => true, :logger => Logger.new('/tmp/x.log')}) #=> <RightSqs:0xb7af6264>
53
+ # sqs = RightAws::SqsInterface.new('1E3GDYEOGFJPIT75KDT40','hgTHt68JY07JKUY08ftHYtERkjgtfERn57DFE379', {:multi_thread => true, :logger => Logger.new('/tmp/x.log')})
54
54
  #
55
55
  # Params is a hash:
56
56
  #
@@ -0,0 +1,200 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestSqsGen2 < Test::Unit::TestCase
4
+
5
+ GRANTEE_EMAIL_ADDRESS = 'fester@example.com'
6
+ RIGHT_MESSAGE_TEXT = 'Right test message'
7
+
8
+
9
+ def setup
10
+ @sqs = Rightscale::SqsGen2Interface.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key)
11
+ @queue_name = 'right_sqs_test_gen2_queue'
12
+ # for classes
13
+ @s = Rightscale::SqsGen2.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key)
14
+ end
15
+
16
+ # Wait for the queue to appear in the queues list.
17
+ # Amazon needs some time to after the queue creation to place
18
+ # it to the accessible queues list. If we dont want to get
19
+ # the additional faults then wait a bit...
20
+ def wait_for_queue_url(queue_name)
21
+ queue_url = nil
22
+ until queue_url
23
+ queue_url = @sqs.queue_url_by_name(queue_name)
24
+ unless queue_url
25
+ print '-'
26
+ STDOUT.flush
27
+ sleep 1
28
+ end
29
+ end
30
+ queue_url
31
+ end
32
+
33
+
34
+ #---------------------------
35
+ # Rightscale::SqsInterface
36
+ #---------------------------
37
+
38
+ def test_01_create_queue
39
+ queue_url = @sqs.create_queue @queue_name
40
+ assert queue_url[/http.*#{@queue_name}/], 'New queue creation failed'
41
+ end
42
+
43
+ def test_02_list_queues
44
+ wait_for_queue_url(@queue_name)
45
+ queues = @sqs.list_queues('right_')
46
+ assert queues.size>0, 'Must more that 0 queues in list'
47
+ end
48
+
49
+ def test_03_set_and_get_queue_attributes
50
+ queue_url = @sqs.queue_url_by_name(@queue_name)
51
+ assert queue_url[/http.*#{@queue_name}/], "#{@queue_name} must exist!"
52
+ assert @sqs.set_queue_attributes(queue_url, 'VisibilityTimeout', 111), 'Set_queue_attributes fail'
53
+ sleep 20 # Amazon needs some time to change attribute
54
+ assert_equal '111', @sqs.get_queue_attributes(queue_url)['VisibilityTimeout'], 'New VisibilityTimeout must be equal to 111'
55
+ end
56
+
57
+ def test_06_send_message
58
+ queue_url = @sqs.queue_url_by_name(@queue_name)
59
+ # send 5 messages for the tests below
60
+ assert @sqs.send_message(queue_url, RIGHT_MESSAGE_TEXT)
61
+ assert @sqs.send_message(queue_url, RIGHT_MESSAGE_TEXT)
62
+ assert @sqs.send_message(queue_url, RIGHT_MESSAGE_TEXT)
63
+ assert @sqs.send_message(queue_url, RIGHT_MESSAGE_TEXT)
64
+ assert @sqs.send_message(queue_url, RIGHT_MESSAGE_TEXT)
65
+ end
66
+
67
+ def test_07_get_queue_length
68
+ queue_url = @sqs.queue_url_by_name(@queue_name)
69
+ assert_equal 5, @sqs.get_queue_length(queue_url), 'Queue must have 5 messages'
70
+ end
71
+
72
+ def test_08_receive_message
73
+ queue_url = @sqs.queue_url_by_name(@queue_name)
74
+ r_message = @sqs.receive_message(queue_url, 1)[0]
75
+ assert r_message, "Receive returned no message(s), but this is not necessarily incorrect"
76
+ assert_equal RIGHT_MESSAGE_TEXT, r_message['Body'], 'Receive message got wrong message text'
77
+ end
78
+
79
+ def test_09_delete_message
80
+ queue_url = @sqs.queue_url_by_name(@queue_name)
81
+ message = @sqs.receive_message(queue_url)[0]
82
+ assert @sqs.delete_message(queue_url, message['ReceiptHandle']), 'Delete_message fail'
83
+ assert @sqs.pop_message(queue_url), 'Pop_message fail'
84
+ end
85
+
86
+ def test_10_clear_and_delete_queue
87
+ queue_url = @sqs.queue_url_by_name(@queue_name)
88
+ assert @sqs.delete_queue(queue_url)
89
+ end
90
+
91
+ #---------------------------
92
+ # Rightscale::Sqs classes
93
+ #---------------------------
94
+
95
+ def test_20_sqs_create_delete_queue
96
+ assert @s, 'Rightscale::SqsGen2 must exist'
97
+ # get queues list
98
+ queues_size = @s.queues.size
99
+ # create new queue
100
+ queue = @s.queue("#{@queue_name}_20", true)
101
+ # check that it is created
102
+ assert queue.is_a?(Rightscale::SqsGen2::Queue)
103
+ wait_for_queue_url(@queue_name)
104
+ # check that amount of queues has increased
105
+ assert_equal queues_size + 1, @s.queues.size
106
+ # delete queue
107
+ assert queue.delete
108
+ end
109
+
110
+ def test_21_queue_create
111
+ # create new queue
112
+ queue = Rightscale::SqsGen2::Queue.create(@s, "#{@queue_name}_21", true)
113
+ # check that it is created
114
+ assert queue.is_a?(Rightscale::SqsGen2::Queue)
115
+ wait_for_queue_url(@queue_name)
116
+ end
117
+
118
+ def test_22_queue_attributes
119
+ queue = Rightscale::SqsGen2::Queue.create(@s, "#{@queue_name}_21", false)
120
+ # get a list of attrinutes
121
+ attributes = queue.get_attribute
122
+ assert attributes.is_a?(Hash) && attributes.size>0
123
+ # get attribute value and increase it by 10
124
+ v = (queue.get_attribute('VisibilityTimeout').to_i + 10).to_s
125
+ # set attribute
126
+ assert queue.set_attribute('VisibilityTimeout', v)
127
+ # wait a bit
128
+ sleep 20
129
+ # check that attribute has changed
130
+ assert_equal v, queue.get_attribute('VisibilityTimeout')
131
+ # get queue visibility timeout
132
+ assert_equal v, queue.visibility
133
+ # change it
134
+ queue.visibility = queue.visibility.to_i + 10
135
+ # make sure that it is changed
136
+ assert v.to_i + 10, queue.visibility
137
+ end
138
+
139
+ def test_24_send_size
140
+ queue = Rightscale::SqsGen2::Queue.create(@s, "#{@queue_name}_24", true)
141
+ # send 5 messages
142
+ assert queue.push('a1')
143
+ assert queue.push('a2')
144
+ assert queue.push('a3')
145
+ assert queue.push('a4')
146
+ assert queue.push('a5')
147
+ # check queue size
148
+ assert_equal 5, queue.size
149
+ # send one more
150
+ assert queue.push('a6')
151
+ # check queue size again
152
+ assert_equal 6, queue.size
153
+ end
154
+
155
+ def test_25_message_receive_pop_delete
156
+ queue = Rightscale::SqsGen2::Queue.create(@s, "#{@queue_name}_24", false)
157
+ # get queue size
158
+ size = queue.size
159
+ # get first message
160
+ m1 = queue.receive(10)
161
+ assert m1.is_a?(Rightscale::SqsGen2::Message)
162
+ # pop second message
163
+ m2 = queue.pop
164
+ assert m2.is_a?(Rightscale::SqsGen2::Message)
165
+ # make sure that queue size has decreased
166
+ assert_equal size-1, queue.size
167
+ # delete messsage
168
+ assert m1.delete
169
+ # make sure that queue size has decreased again
170
+ assert_equal size-2, queue.size
171
+ end
172
+
173
+ def test_26
174
+ queue = Rightscale::SqsGen2::Queue.create(@s, "#{@queue_name}_24", false)
175
+ # lock message
176
+ queue.receive(100)
177
+ # clear queue
178
+ assert queue.clear
179
+ # queue size is greater than zero
180
+ assert queue.size>0
181
+ end
182
+
183
+ def test_27_set_amazon_problems
184
+ original_problems = Rightscale::SqsGen2Interface.amazon_problems
185
+ assert(original_problems.length > 0)
186
+ Rightscale::SqsGen2Interface.amazon_problems= original_problems << "A New Problem"
187
+ new_problems = Rightscale::SqsGen2Interface.amazon_problems
188
+ assert_equal(new_problems, original_problems)
189
+
190
+ Rightscale::SqsGen2Interface.amazon_problems= nil
191
+ assert_nil(Rightscale::SqsGen2Interface.amazon_problems)
192
+ end
193
+
194
+ def test_28_check_threading_model
195
+ assert(!@sqs.multi_thread)
196
+ newsqs = Rightscale::SqsGen2Interface.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key, {:multi_thread => true})
197
+ assert(newsqs.multi_thread)
198
+ end
199
+
200
+ end
data/test/ts_right_aws.rb CHANGED
@@ -9,4 +9,5 @@ require 'ec2/test_right_ec2.rb'
9
9
  require 's3/test_right_s3.rb'
10
10
  require 's3/test_right_s3_stubbed.rb'
11
11
  require 'sqs/test_right_sqs.rb'
12
+ require 'sqs/test_right_sqs_gen2.rb'
12
13
  require 'sdb/test_right_sdb.rb'
metadata CHANGED
@@ -3,15 +3,15 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: right_aws
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.5.0
7
- date: 2008-02-11 00:00:00 -08:00
6
+ version: 1.6.0
7
+ date: 2008-03-03 00:00:00 -08:00
8
8
  summary: Interface classes for the Amazon EC2, SQS, and S3 Web Services
9
9
  require_paths:
10
10
  - lib
11
11
  email: support@rightscale.com
12
12
  homepage:
13
13
  rubyforge_project: rightaws
14
- description: "== DESCRIPTION: The RightScale AWS gems have been designed to provide a robust, fast, and secure interface to Amazon EC2, Amazon S3, Amazon SQS, and Amazon SDB. These gems have been used in production by RightScale since late 2006 and are being maintained to track enhancements made by Amazon. The RightScale AWS gems comprise: - RightAws::Ec2 -- interface to Amazon EC2 (Elastic Compute Cloud) - RightAws::S3 and RightAws::S3Interface -- interface to Amazon S3 (Simple Storage Service) - RightAws::Sqs and RightAws::SqsInterface -- interface to Amazon SQS (Simple Queue Service) - RightAws::SdbInterface -- interface to Amazon SDB (SimpleDB) == FEATURES:"
14
+ description: "== DESCRIPTION: The RightScale AWS gems have been designed to provide a robust, fast, and secure interface to Amazon EC2, Amazon S3, Amazon SQS, and Amazon SDB. These gems have been used in production by RightScale since late 2006 and are being maintained to track enhancements made by Amazon. The RightScale AWS gems comprise: - RightAws::Ec2 -- interface to Amazon EC2 (Elastic Compute Cloud) - RightAws::S3 and RightAws::S3Interface -- interface to Amazon S3 (Simple Storage Service) - RightAws::Sqs and RightAws::SqsInterface -- interface to first-generation Amazon SQS (Simple Queue Service) (API version 2007-05-01) - RightAws::SqsGen2 and RightAws::SqsGen2Interface -- interface to second-generation Amazon SQS (Simple Queue Service) (API version 2008-01-01) - RightAws::SdbInterface -- interface to Amazon SDB (SimpleDB) == FEATURES:"
15
15
  autorequire:
16
16
  default_executable:
17
17
  bindir: bin
@@ -43,6 +43,8 @@ files:
43
43
  - lib/sdb/right_sdb_interface.rb
44
44
  - lib/sqs/right_sqs.rb
45
45
  - lib/sqs/right_sqs_interface.rb
46
+ - lib/sqs/right_sqs_gen2.rb
47
+ - lib/sqs/right_sqs_gen2_interface.rb
46
48
  - test/ec2/test_helper.rb
47
49
  - test/ec2/test_right_ec2.rb
48
50
  - test/s3/test_helper.rb
@@ -52,6 +54,7 @@ files:
52
54
  - test/sdb/test_helper.rb
53
55
  - test/sqs/test_helper.rb
54
56
  - test/sqs/test_right_sqs.rb
57
+ - test/sqs/test_right_sqs_gen2.rb
55
58
  - test/ts_right_aws.rb
56
59
  - test/test_credentials.rb
57
60
  - test/http_connection.rb
@@ -80,12 +83,3 @@ dependencies:
80
83
  - !ruby/object:Gem::Version
81
84
  version: 1.2.1
82
85
  version:
83
- - !ruby/object:Gem::Dependency
84
- name: hoe
85
- version_requirement:
86
- version_requirements: !ruby/object:Gem::Version::Requirement
87
- requirements:
88
- - - ">="
89
- - !ruby/object:Gem::Version
90
- version: 1.3.0
91
- version: