aws 2.4.4 → 2.4.5

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.
@@ -323,14 +323,14 @@ module Aws
323
323
  # - :pull_out_array => an array of levels to dig into when generating return value (see rds.rb for example)
324
324
  def request_info_xml_simple(connection_name, lib_params, request, logger, params = {})
325
325
 
326
- @connection = get_conn(connection_name, lib_params, logger)
326
+ connection = get_conn(connection_name, lib_params, logger)
327
327
  begin
328
328
  @last_request = request[:request]
329
329
  @last_response = nil
330
330
 
331
- response = @connection.request(request)
331
+ response = connection.request(request)
332
332
  # puts "response=" + response.body
333
- # benchblock.service.add!{ response = @connection.request(request) }
333
+ # benchblock.service.add!{ response = connection.request(request) }
334
334
  # check response for errors...
335
335
  @last_response = response
336
336
  if response.is_a?(Net::HTTPSuccess)
@@ -395,7 +395,7 @@ module Aws
395
395
  raise AwsError2.new(@last_response.code, @last_request_id, request_text_data, @last_response.body)
396
396
  end
397
397
  ensure
398
- @connection.finish if @connection && lib_params[:connection_mode] == :per_request
398
+ connection.finish if connection && lib_params[:connection_mode] == :per_request
399
399
  end
400
400
 
401
401
  end
@@ -472,7 +472,7 @@ module Aws
472
472
 
473
473
 
474
474
  def request_info_impl(connection, benchblock, request, parser, options={}, &block) #:nodoc:
475
- @connection = connection
475
+ connection = connection
476
476
  @last_request = request[:request]
477
477
  @last_response = nil
478
478
  response =nil
@@ -489,7 +489,7 @@ module Aws
489
489
  # Exceptions can originate from code directly in the block, or from user
490
490
  # code called in the other block which is passed to response.read_body.
491
491
  benchblock.service.add! do
492
- responsehdr = @connection.request(request) do |response|
492
+ responsehdr = connection.request(request) do |response|
493
493
  #########
494
494
  begin
495
495
  @last_response = response
@@ -522,7 +522,7 @@ module Aws
522
522
  return parser.result
523
523
  end
524
524
  else
525
- benchblock.service.add! { response = @connection.request(request) }
525
+ benchblock.service.add! { response = connection.request(request) }
526
526
  # check response for errors...
527
527
  @last_response = response
528
528
  if response.is_a?(Net::HTTPSuccess)
@@ -1,288 +1,292 @@
1
- module Aws
2
-
3
- # Exception class to signal any Amazon errors. All errors occuring during calls to Amazon's
4
- # web services raise this type of error.
5
- # Attribute inherited by RuntimeError:
6
- # message - the text of the error, generally as returned by AWS in its XML response.
7
- class AwsError < RuntimeError
8
-
9
- # either an array of errors where each item is itself an array of [code, message]),
10
- # or an error string if the error was raised manually, as in <tt>AwsError.new('err_text')</tt>
11
- attr_reader :errors
12
-
13
- # Request id (if exists)
14
- attr_reader :request_id
15
-
16
- # Response HTTP error code
17
- attr_reader :http_code
18
-
19
- # Raw request text data to AWS
20
- attr_reader :request_data
21
-
22
- attr_reader :response
23
-
24
- def initialize(errors=nil, http_code=nil, request_id=nil, request_data=nil, response=nil)
25
- @errors = errors
26
- @request_id = request_id
27
- @http_code = http_code
28
- @request_data = request_data
29
- @response = response
30
- msg = @errors.is_a?(Array) ? @errors.map { |code, msg| "#{code}: #{msg}" }.join("; ") : @errors.to_s
31
- msg += "\nREQUEST=#{@request_data} " unless @request_data.nil?
32
- msg += "\nREQUEST ID=#{@request_id} " unless @request_id.nil?
33
- super(msg)
34
- end
35
-
36
- # Does any of the error messages include the regexp +pattern+?
37
- # Used to determine whether to retry request.
38
- def include?(pattern)
39
- if @errors.is_a?(Array)
40
- @errors.each { |code, msg| return true if code =~ pattern }
41
- else
42
- return true if @errors_str =~ pattern
43
- end
44
- false
45
- end
46
-
47
- # Generic handler for AwsErrors. +aws+ is the Aws::S3, Aws::EC2, or Aws::SQS
48
- # object that caused the exception (it must provide last_request and last_response). Supported
49
- # boolean options are:
50
- # * <tt>:log</tt> print a message into the log using aws.logger to access the Logger
51
- # * <tt>:puts</tt> do a "puts" of the error
52
- # * <tt>:raise</tt> re-raise the error after logging
53
- def self.on_aws_exception(aws, options={:raise=>true, :log=>true})
54
- # Only log & notify if not user error
55
- if !options[:raise] || system_error?($!)
56
- error_text = "#{$!.inspect}\n#{$@}.join('\n')}"
57
- puts error_text if options[:puts]
58
- # Log the error
59
- if options[:log]
60
- request = aws.last_request ? aws.last_request.path : '-none-'
61
- response = aws.last_response ? "#{aws.last_response.code} -- #{aws.last_response.message} -- #{aws.last_response.body}" : '-none-'
62
- @response = response
63
- aws.logger.error error_text
64
- aws.logger.error "Request was: #{request}"
65
- aws.logger.error "Response was: #{response}"
66
- end
67
- end
68
- raise if options[:raise] # re-raise an exception
69
- return nil
70
- end
71
-
72
- # True if e is an AWS system error, i.e. something that is for sure not the caller's fault.
73
- # Used to force logging.
74
- def self.system_error?(e)
75
- !e.is_a?(self) || e.message =~ /InternalError|InsufficientInstanceCapacity|Unavailable/
76
- end
77
-
78
- end
79
-
80
- # Simplified version
81
- class AwsError2 < RuntimeError
82
- # Request id (if exists)
83
- attr_reader :request_id
84
-
85
- # Response HTTP error code
86
- attr_reader :http_code
87
-
88
- # Raw request text data to AWS
89
- attr_reader :request_data
90
-
91
- attr_reader :response
92
-
93
- attr_reader :errors
94
-
95
- def initialize(http_code=nil, request_id=nil, request_data=nil, response=nil)
96
-
97
- @request_id = request_id
98
- @http_code = http_code
99
- @request_data = request_data
100
- @response = response
101
- # puts '@response=' + @response.inspect
102
-
103
- if @response
104
- ref = XmlSimple.xml_in(@response, {"ForceArray"=>false})
105
- # puts "refxml=" + ref.inspect
106
- msg = "#{ref['Error']['Code']}: #{ref['Error']['Message']}"
107
- else
108
- msg = "#{@http_code}: REQUEST(#{@request_data})"
109
- end
110
- msg += "\nREQUEST ID=#{@request_id} " unless @request_id.nil?
111
- super(msg)
112
- end
113
-
114
-
115
- end
116
-
117
-
118
- class AWSErrorHandler
119
- # 0-100 (%)
120
- DEFAULT_CLOSE_ON_4XX_PROBABILITY = 10
121
-
122
- @@reiteration_start_delay = 0.2
123
-
124
- def self.reiteration_start_delay
125
- @@reiteration_start_delay
126
- end
127
-
128
- def self.reiteration_start_delay=(reiteration_start_delay)
129
- @@reiteration_start_delay = reiteration_start_delay
130
- end
131
-
132
- @@reiteration_time = 5
133
-
134
- def self.reiteration_time
135
- @@reiteration_time
136
- end
137
-
138
- def self.reiteration_time=(reiteration_time)
139
- @@reiteration_time = reiteration_time
140
- end
141
-
142
- @@close_on_error = true
143
-
144
- def self.close_on_error
145
- @@close_on_error
146
- end
147
-
148
- def self.close_on_error=(close_on_error)
149
- @@close_on_error = close_on_error
150
- end
151
-
152
- @@close_on_4xx_probability = DEFAULT_CLOSE_ON_4XX_PROBABILITY
153
-
154
- def self.close_on_4xx_probability
155
- @@close_on_4xx_probability
156
- end
157
-
158
- def self.close_on_4xx_probability=(close_on_4xx_probability)
159
- @@close_on_4xx_probability = close_on_4xx_probability
160
- end
161
-
162
- # params:
163
- # :reiteration_time
164
- # :errors_list
165
- # :close_on_error = true | false
166
- # :close_on_4xx_probability = 1-100
167
- def initialize(aws, parser, params={}) #:nodoc:
168
- @aws = aws # Link to RightEc2 | RightSqs | RightS3 instance
169
- @parser = parser # parser to parse Amazon response
170
- @started_at = Time.now
171
- @stop_at = @started_at + (params[:reiteration_time] || @@reiteration_time)
172
- @errors_list = params[:errors_list] || []
173
- @reiteration_delay = @@reiteration_start_delay
174
- @retries = 0
175
- # close current HTTP(S) connection on 5xx, errors from list and 4xx errors
176
- @close_on_error = params[:close_on_error].nil? ? @@close_on_error : params[:close_on_error]
177
- @close_on_4xx_probability = params[:close_on_4xx_probability] || @@close_on_4xx_probability
178
- end
179
-
180
- # Returns false if
181
- def check(request, options={}) #:nodoc:
182
- result = false
183
- error_found = false
184
- redirect_detected = false
185
- error_match = nil
186
- last_errors_text = ''
187
- response = @aws.last_response
188
- # log error
189
- request_text_data = "#{request[:server]}:#{request[:port]}#{request[:request].path}"
190
- # is this a redirect?
191
- # yes!
192
- if response.is_a?(Net::HTTPRedirection)
193
- redirect_detected = true
194
- else
195
- # no, it's an error ...
196
- @aws.logger.warn("##### #{@aws.class.name} returned an error: #{response.code} #{response.message}\n#{response.body} #####")
197
- @aws.logger.warn("##### #{@aws.class.name} request: #{request_text_data} ####")
198
- end
199
- # Check response body: if it is an Amazon XML document or not:
200
- if redirect_detected || (response.body && response.body[/<\?xml/]) # ... it is a xml document
201
- @aws.class.bench_xml.add! do
202
- error_parser = RightErrorResponseParser.new
203
- error_parser.parse(response)
204
- @aws.last_errors = error_parser.errors
205
- @aws.last_request_id = error_parser.requestID
206
- last_errors_text = @aws.last_errors.flatten.join("\n")
207
- # on redirect :
208
- if redirect_detected
209
- location = response['location']
210
- # ... log information and ...
211
- @aws.logger.info("##### #{@aws.class.name} redirect requested: #{response.code} #{response.message} #####")
212
- @aws.logger.info("##### New location: #{location} #####")
213
- # ... fix the connection data
214
- request[:server] = URI.parse(location).host
215
- request[:protocol] = URI.parse(location).scheme
216
- request[:port] = URI.parse(location).port
217
- end
218
- end
219
- else # ... it is not a xml document(probably just a html page?)
220
- @aws.last_errors = [[response.code, "#{response.message} (#{request_text_data})"]]
221
- @aws.last_request_id = '-undefined-'
222
- last_errors_text = response.message
223
- end
224
- # now - check the error
225
- unless redirect_detected
226
- @errors_list.each do |error_to_find|
227
- if last_errors_text[/#{error_to_find}/i]
228
- error_found = true
229
- error_match = error_to_find
230
- @aws.logger.warn("##### Retry is needed, error pattern match: #{error_to_find} #####")
231
- break
232
- end
233
- end
234
- end
235
- # check the time has gone from the first error come
236
- if redirect_detected || error_found
237
- # Close the connection to the server and recreate a new one.
238
- # It may have a chance that one server is a semi-down and reconnection
239
- # will help us to connect to the other server
240
- if !redirect_detected && @close_on_error
241
- @aws.connection.finish "#{self.class.name}: error match to pattern '#{error_match}'"
242
- end
243
- # puts 'OPTIONS3=' + options.inspect
244
- if options[:retries].nil? || @retries < options[:retries]
245
- if (Time.now < @stop_at)
246
- @retries += 1
247
- unless redirect_detected
248
- @aws.logger.warn("##### Retry ##{@retries} is being performed. Sleeping for #{@reiteration_delay} sec. Whole time: #{Time.now-@started_at} sec ####")
249
- sleep @reiteration_delay
250
- @reiteration_delay *= 2
251
-
252
- # Always make sure that the fp is set to point to the beginning(?)
253
- # of the File/IO. TODO: it assumes that offset is 0, which is bad.
254
- if (request[:request].body_stream && request[:request].body_stream.respond_to?(:pos))
255
- begin
256
- request[:request].body_stream.pos = 0
257
- rescue Exception => e
258
- @logger.warn("Retry may fail due to unable to reset the file pointer" +
259
- " -- #{self.class.name} : #{e.inspect}")
260
- end
261
- end
262
- else
263
- @aws.logger.info("##### Retry ##{@retries} is being performed due to a redirect. ####")
264
- end
265
- result = @aws.request_info(request, @parser, options)
266
- else
267
- @aws.logger.warn("##### Ooops, time is over... ####")
268
- end
269
- else
270
- @aws.logger.info("##### Stopped retrying because retries=#{@retries} and max=#{options[:retries]} ####")
271
- end
272
- # aha, this is unhandled error:
273
- elsif @close_on_error
274
- # Is this a 5xx error ?
275
- if @aws.last_response.code.to_s[/^5\d\d$/]
276
- @aws.connection.finish "#{self.class.name}: code: #{@aws.last_response.code}: '#{@aws.last_response.message}'"
277
- # Is this a 4xx error ?
278
- elsif @aws.last_response.code.to_s[/^4\d\d$/] && @close_on_4xx_probability > rand(100)
279
- @aws.connection.finish "#{self.class.name}: code: #{@aws.last_response.code}: '#{@aws.last_response.message}', " +
280
- "probability: #{@close_on_4xx_probability}%"
281
- end
282
- end
283
- result
284
- end
285
-
286
- end
287
-
1
+ module Aws
2
+
3
+ class ResourceNotFoundError < StandardError
4
+
5
+ end
6
+
7
+ # Exception class to signal any Amazon errors. All errors occuring during calls to Amazon's
8
+ # web services raise this type of error.
9
+ # Attribute inherited by RuntimeError:
10
+ # message - the text of the error, generally as returned by AWS in its XML response.
11
+ class AwsError < RuntimeError
12
+
13
+ # either an array of errors where each item is itself an array of [code, message]),
14
+ # or an error string if the error was raised manually, as in <tt>AwsError.new('err_text')</tt>
15
+ attr_reader :errors
16
+
17
+ # Request id (if exists)
18
+ attr_reader :request_id
19
+
20
+ # Response HTTP error code
21
+ attr_reader :http_code
22
+
23
+ # Raw request text data to AWS
24
+ attr_reader :request_data
25
+
26
+ attr_reader :response
27
+
28
+ def initialize(errors=nil, http_code=nil, request_id=nil, request_data=nil, response=nil)
29
+ @errors = errors
30
+ @request_id = request_id
31
+ @http_code = http_code
32
+ @request_data = request_data
33
+ @response = response
34
+ msg = @errors.is_a?(Array) ? @errors.map { |code, msg| "#{code}: #{msg}" }.join("; ") : @errors.to_s
35
+ msg += "\nREQUEST=#{@request_data} " unless @request_data.nil?
36
+ msg += "\nREQUEST ID=#{@request_id} " unless @request_id.nil?
37
+ super(msg)
38
+ end
39
+
40
+ # Does any of the error messages include the regexp +pattern+?
41
+ # Used to determine whether to retry request.
42
+ def include?(pattern)
43
+ if @errors.is_a?(Array)
44
+ @errors.each { |code, msg| return true if code =~ pattern }
45
+ else
46
+ return true if @errors_str =~ pattern
47
+ end
48
+ false
49
+ end
50
+
51
+ # Generic handler for AwsErrors. +aws+ is the Aws::S3, Aws::EC2, or Aws::SQS
52
+ # object that caused the exception (it must provide last_request and last_response). Supported
53
+ # boolean options are:
54
+ # * <tt>:log</tt> print a message into the log using aws.logger to access the Logger
55
+ # * <tt>:puts</tt> do a "puts" of the error
56
+ # * <tt>:raise</tt> re-raise the error after logging
57
+ def self.on_aws_exception(aws, options={:raise=>true, :log=>true})
58
+ # Only log & notify if not user error
59
+ if !options[:raise] || system_error?($!)
60
+ error_text = "#{$!.inspect}\n#{$@}.join('\n')}"
61
+ puts error_text if options[:puts]
62
+ # Log the error
63
+ if options[:log]
64
+ request = aws.last_request ? aws.last_request.path : '-none-'
65
+ response = aws.last_response ? "#{aws.last_response.code} -- #{aws.last_response.message} -- #{aws.last_response.body}" : '-none-'
66
+ @response = response
67
+ aws.logger.error error_text
68
+ aws.logger.error "Request was: #{request}"
69
+ aws.logger.error "Response was: #{response}"
70
+ end
71
+ end
72
+ raise if options[:raise] # re-raise an exception
73
+ return nil
74
+ end
75
+
76
+ # True if e is an AWS system error, i.e. something that is for sure not the caller's fault.
77
+ # Used to force logging.
78
+ def self.system_error?(e)
79
+ !e.is_a?(self) || e.message =~ /InternalError|InsufficientInstanceCapacity|Unavailable/
80
+ end
81
+
82
+ end
83
+
84
+ # Simplified version
85
+ class AwsError2 < RuntimeError
86
+ # Request id (if exists)
87
+ attr_reader :request_id
88
+
89
+ # Response HTTP error code
90
+ attr_reader :http_code
91
+
92
+ # Raw request text data to AWS
93
+ attr_reader :request_data
94
+
95
+ attr_reader :response
96
+
97
+ attr_reader :errors
98
+
99
+ def initialize(http_code=nil, request_id=nil, request_data=nil, response=nil)
100
+
101
+ @request_id = request_id
102
+ @http_code = http_code
103
+ @request_data = request_data
104
+ @response = response
105
+ # puts '@response=' + @response.inspect
106
+
107
+ if @response
108
+ ref = XmlSimple.xml_in(@response, {"ForceArray"=>false})
109
+ # puts "refxml=" + ref.inspect
110
+ msg = "#{ref['Error']['Code']}: #{ref['Error']['Message']}"
111
+ else
112
+ msg = "#{@http_code}: REQUEST(#{@request_data})"
113
+ end
114
+ msg += "\nREQUEST ID=#{@request_id} " unless @request_id.nil?
115
+ super(msg)
116
+ end
117
+
118
+
119
+ end
120
+
121
+
122
+ class AWSErrorHandler
123
+ # 0-100 (%)
124
+ DEFAULT_CLOSE_ON_4XX_PROBABILITY = 10
125
+
126
+ @@reiteration_start_delay = 0.2
127
+
128
+ def self.reiteration_start_delay
129
+ @@reiteration_start_delay
130
+ end
131
+
132
+ def self.reiteration_start_delay=(reiteration_start_delay)
133
+ @@reiteration_start_delay = reiteration_start_delay
134
+ end
135
+
136
+ @@reiteration_time = 5
137
+
138
+ def self.reiteration_time
139
+ @@reiteration_time
140
+ end
141
+
142
+ def self.reiteration_time=(reiteration_time)
143
+ @@reiteration_time = reiteration_time
144
+ end
145
+
146
+ @@close_on_error = true
147
+
148
+ def self.close_on_error
149
+ @@close_on_error
150
+ end
151
+
152
+ def self.close_on_error=(close_on_error)
153
+ @@close_on_error = close_on_error
154
+ end
155
+
156
+ @@close_on_4xx_probability = DEFAULT_CLOSE_ON_4XX_PROBABILITY
157
+
158
+ def self.close_on_4xx_probability
159
+ @@close_on_4xx_probability
160
+ end
161
+
162
+ def self.close_on_4xx_probability=(close_on_4xx_probability)
163
+ @@close_on_4xx_probability = close_on_4xx_probability
164
+ end
165
+
166
+ # params:
167
+ # :reiteration_time
168
+ # :errors_list
169
+ # :close_on_error = true | false
170
+ # :close_on_4xx_probability = 1-100
171
+ def initialize(aws, parser, params={}) #:nodoc:
172
+ @aws = aws # Link to RightEc2 | RightSqs | RightS3 instance
173
+ @parser = parser # parser to parse Amazon response
174
+ @started_at = Time.now
175
+ @stop_at = @started_at + (params[:reiteration_time] || @@reiteration_time)
176
+ @errors_list = params[:errors_list] || []
177
+ @reiteration_delay = @@reiteration_start_delay
178
+ @retries = 0
179
+ # close current HTTP(S) connection on 5xx, errors from list and 4xx errors
180
+ @close_on_error = params[:close_on_error].nil? ? @@close_on_error : params[:close_on_error]
181
+ @close_on_4xx_probability = params[:close_on_4xx_probability] || @@close_on_4xx_probability
182
+ end
183
+
184
+ # Returns false if
185
+ def check(request, options={}) #:nodoc:
186
+ result = false
187
+ error_found = false
188
+ redirect_detected = false
189
+ error_match = nil
190
+ last_errors_text = ''
191
+ response = @aws.last_response
192
+ # log error
193
+ request_text_data = "#{request[:server]}:#{request[:port]}#{request[:request].path}"
194
+ # is this a redirect?
195
+ # yes!
196
+ if response.is_a?(Net::HTTPRedirection)
197
+ redirect_detected = true
198
+ else
199
+ # no, it's an error ...
200
+ @aws.logger.warn("##### #{@aws.class.name} returned an error: #{response.code} #{response.message}\n#{response.body} #####")
201
+ @aws.logger.warn("##### #{@aws.class.name} request: #{request_text_data} ####")
202
+ end
203
+ # Check response body: if it is an Amazon XML document or not:
204
+ if redirect_detected || (response.body && response.body[/<\?xml/]) # ... it is a xml document
205
+ @aws.class.bench_xml.add! do
206
+ error_parser = RightErrorResponseParser.new
207
+ error_parser.parse(response)
208
+ @aws.last_errors = error_parser.errors
209
+ @aws.last_request_id = error_parser.requestID
210
+ last_errors_text = @aws.last_errors.flatten.join("\n")
211
+ # on redirect :
212
+ if redirect_detected
213
+ location = response['location']
214
+ # ... log information and ...
215
+ @aws.logger.info("##### #{@aws.class.name} redirect requested: #{response.code} #{response.message} #####")
216
+ @aws.logger.info("##### New location: #{location} #####")
217
+ # ... fix the connection data
218
+ request[:server] = URI.parse(location).host
219
+ request[:protocol] = URI.parse(location).scheme
220
+ request[:port] = URI.parse(location).port
221
+ end
222
+ end
223
+ else # ... it is not a xml document(probably just a html page?)
224
+ @aws.last_errors = [[response.code, "#{response.message} (#{request_text_data})"]]
225
+ @aws.last_request_id = '-undefined-'
226
+ last_errors_text = response.message
227
+ end
228
+ # now - check the error
229
+ unless redirect_detected
230
+ @errors_list.each do |error_to_find|
231
+ if last_errors_text[/#{error_to_find}/i]
232
+ error_found = true
233
+ error_match = error_to_find
234
+ @aws.logger.warn("##### Retry is needed, error pattern match: #{error_to_find} #####")
235
+ break
236
+ end
237
+ end
238
+ end
239
+ # check the time has gone from the first error come
240
+ if redirect_detected || error_found
241
+ # Close the connection to the server and recreate a new one.
242
+ # It may have a chance that one server is a semi-down and reconnection
243
+ # will help us to connect to the other server
244
+ if !redirect_detected && @close_on_error
245
+ @aws.connection.finish "#{self.class.name}: error match to pattern '#{error_match}'"
246
+ end
247
+ # puts 'OPTIONS3=' + options.inspect
248
+ if options[:retries].nil? || @retries < options[:retries]
249
+ if (Time.now < @stop_at)
250
+ @retries += 1
251
+ unless redirect_detected
252
+ @aws.logger.warn("##### Retry ##{@retries} is being performed. Sleeping for #{@reiteration_delay} sec. Whole time: #{Time.now-@started_at} sec ####")
253
+ sleep @reiteration_delay
254
+ @reiteration_delay *= 2
255
+
256
+ # Always make sure that the fp is set to point to the beginning(?)
257
+ # of the File/IO. TODO: it assumes that offset is 0, which is bad.
258
+ if (request[:request].body_stream && request[:request].body_stream.respond_to?(:pos))
259
+ begin
260
+ request[:request].body_stream.pos = 0
261
+ rescue Exception => e
262
+ @logger.warn("Retry may fail due to unable to reset the file pointer" +
263
+ " -- #{self.class.name} : #{e.inspect}")
264
+ end
265
+ end
266
+ else
267
+ @aws.logger.info("##### Retry ##{@retries} is being performed due to a redirect. ####")
268
+ end
269
+ result = @aws.request_info(request, @parser, options)
270
+ else
271
+ @aws.logger.warn("##### Ooops, time is over... ####")
272
+ end
273
+ else
274
+ @aws.logger.info("##### Stopped retrying because retries=#{@retries} and max=#{options[:retries]} ####")
275
+ end
276
+ # aha, this is unhandled error:
277
+ elsif @close_on_error
278
+ # Is this a 5xx error ?
279
+ if @aws.last_response.code.to_s[/^5\d\d$/]
280
+ @aws.connection.finish "#{self.class.name}: code: #{@aws.last_response.code}: '#{@aws.last_response.message}'"
281
+ # Is this a 4xx error ?
282
+ elsif @aws.last_response.code.to_s[/^4\d\d$/] && @close_on_4xx_probability > rand(100)
283
+ @aws.connection.finish "#{self.class.name}: code: #{@aws.last_response.code}: '#{@aws.last_response.message}', " +
284
+ "probability: #{@close_on_4xx_probability}%"
285
+ end
286
+ end
287
+ result
288
+ end
289
+
290
+ end
291
+
288
292
  end
@@ -23,46 +23,46 @@
23
23
 
24
24
  module Aws
25
25
 
26
- #
27
- # Aws::Sqs -- RightScale's Amazon SQS interface, API version
28
- # 2008-01-01 and later.
29
- # The Aws::Sqs 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
- # Aws::Sqs is built atop Aws::SqsInterface, a lower-level
37
- # procedural API that may be appropriate for certain programs.
38
- #
39
- # Error handling: all operations raise an Aws::AwsError in case
40
- # of problems. Note that transient errors are automatically retried.
41
- #
42
- # sqs = Aws::Sqs.new(aws_access_key_id, aws_secret_access_key)
43
- # queue1 = sqs.queue('my_awesome_queue')
44
- # ...
45
- # queue2 = Aws::Sqs::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
- #
59
- # Params is a hash:
60
- #
61
- # {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com' (default)
62
- # :port => 443 # Amazon service port: 80 or 443 (default)
63
- # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false (default)
64
- # :signature_version => '0' # The signature version : '0' or '1'(default)
65
- # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
26
+ #
27
+ # Aws::Sqs -- RightScale's Amazon SQS interface, API version
28
+ # 2008-01-01 and later.
29
+ # The Aws::Sqs 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
+ # Aws::Sqs is built atop Aws::SqsInterface, a lower-level
37
+ # procedural API that may be appropriate for certain programs.
38
+ #
39
+ # Error handling: all operations raise an Aws::AwsError in case
40
+ # of problems. Note that transient errors are automatically retried.
41
+ #
42
+ # sqs = Aws::Sqs.new(aws_access_key_id, aws_secret_access_key)
43
+ # queue1 = sqs.queue('my_awesome_queue')
44
+ # ...
45
+ # queue2 = Aws::Sqs::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
+ #
59
+ # Params is a hash:
60
+ #
61
+ # {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com' (default)
62
+ # :port => 443 # Amazon service port: 80 or 443 (default)
63
+ # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false (default)
64
+ # :signature_version => '0' # The signature version : '0' or '1'(default)
65
+ # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
66
66
  class Sqs
67
67
  attr_reader :interface
68
68
 
@@ -70,26 +70,29 @@ module Aws
70
70
  @interface = SqsInterface.new(aws_access_key_id, aws_secret_access_key, params)
71
71
  end
72
72
 
73
- # Retrieves a list of queues.
74
- # Returns an +array+ of +Queue+ instances.
75
- #
76
- # Aws::Sqs.queues #=> array of queues
77
- #
73
+ # Retrieves a list of queues.
74
+ # Returns an +array+ of +Queue+ instances.
75
+ #
76
+ # Aws::Sqs.queues #=> array of queues
77
+ #
78
78
  def queues(prefix=nil)
79
79
  @interface.list_queues(prefix).map do |url|
80
80
  Queue.new(self, url)
81
81
  end
82
82
  end
83
83
 
84
- # Returns Queue instance by queue name.
85
- # If the queue does not exist at Amazon SQS and +create+ is true, the method creates it.
86
- #
87
- # Aws::Sqs.queue('my_awesome_queue') #=> #<Aws::Sqs::Queue:0xb7b626e4 ... >
88
- #
84
+ # Returns Queue instance by queue name.
85
+ # If the queue does not exist at Amazon SQS and +create+ is true, the method creates it.
86
+ #
87
+ # Aws::Sqs.queue('my_awesome_queue') #=> #<Aws::Sqs::Queue:0xb7b626e4 ... >
88
+ #
89
89
  def queue(queue_name, create=true, visibility=nil)
90
- # url = @interface.queue_url_by_name(queue_name)
91
- # url = (create ? @interface.create_queue(queue_name, visibility) : nil) unless url
92
- url = @interface.create_queue(queue_name, visibility) # this returns the url even if it exists
90
+ if create
91
+ url = @interface.create_queue(queue_name, visibility) # this returns the url even if it exists
92
+ else
93
+ url = @interface.queue_url_by_name(queue_name)
94
+ end
95
+
93
96
  url ? Queue.new(self, url) : nil
94
97
  end
95
98
 
@@ -97,62 +100,63 @@ module Aws
97
100
  class Queue
98
101
  attr_reader :name, :url, :sqs
99
102
 
100
- # Returns Queue instance by queue name.
101
- # If the queue does not exist at Amazon SQS and +create+ is true, the method creates it.
102
- #
103
- # Aws::Sqs::Queue.create(sqs, 'my_awesome_queue') #=> #<Aws::Sqs::Queue:0xb7b626e4 ... >
104
- #
103
+ # Returns Queue instance by queue name.
104
+ # If the queue does not exist at Amazon SQS and +create+ is true, the method creates it.
105
+ #
106
+ # Aws::Sqs::Queue.create(sqs, 'my_awesome_queue') #=> #<Aws::Sqs::Queue:0xb7b626e4 ... >
107
+ #
105
108
  def self.create(sqs, url_or_name, create=true, visibility=nil)
106
109
  sqs.queue(url_or_name, create, visibility)
107
110
  end
108
111
 
109
- # Creates new Queue instance.
110
- # Does not create a queue at Amazon.
111
- #
112
- # queue = Aws::Sqs::Queue.new(sqs, 'my_awesome_queue')
113
- #
112
+ # Creates new Queue instance.
113
+ # Does not create a queue at Amazon.
114
+ #
115
+ # queue = Aws::Sqs::Queue.new(sqs, 'my_awesome_queue')
116
+ #
114
117
  def initialize(sqs, url_or_name)
115
- @sqs = sqs
116
- @url = @sqs.interface.queue_url_by_name(url_or_name)
118
+ @sqs = sqs
119
+ @url = @sqs.interface.queue_url_by_name(url_or_name)
120
+ raise ResourceNotFoundError, "Queue '#{url_or_name}' not found." unless @url
117
121
  @name = @sqs.interface.queue_name_by_url(@url)
118
122
  end
119
123
 
120
- # Retrieves queue size.
121
- #
122
- # queue.size #=> 1
123
- #
124
+ # Retrieves queue size.
125
+ #
126
+ # queue.size #=> 1
127
+ #
124
128
  def size
125
129
  @sqs.interface.get_queue_length(@url)
126
130
  end
127
131
 
128
- # Clears queue, deleting only the visible messages. Any message within its visibility
129
- # timeout will not be deleted, and will re-appear in the queue in the
130
- # future when the timeout expires.
131
- #
132
- # To delete all messages in a queue and eliminate the chance of any
133
- # messages re-appearing in the future, it's best to delete the queue and
134
- # re-create it as a new queue. Note that doing this will take at least 60
135
- # s since SQS does not allow re-creation of a queue within this interval.
136
- #
137
- # queue.clear() #=> true
138
- #
132
+ # Clears queue, deleting only the visible messages. Any message within its visibility
133
+ # timeout will not be deleted, and will re-appear in the queue in the
134
+ # future when the timeout expires.
135
+ #
136
+ # To delete all messages in a queue and eliminate the chance of any
137
+ # messages re-appearing in the future, it's best to delete the queue and
138
+ # re-create it as a new queue. Note that doing this will take at least 60
139
+ # s since SQS does not allow re-creation of a queue within this interval.
140
+ #
141
+ # queue.clear() #=> true
142
+ #
139
143
  def clear()
140
- @sqs.interface.clear_queue(@url)
144
+ @sqs.interface.clear_queue(@url)
141
145
  end
142
146
 
143
- # Deletes queue. Any messages in the queue will be permanently lost.
144
- # Returns +true+.
145
- #
146
- # NB: Use with caution; severe data loss is possible!
147
- #
148
- # queue.delete(true) #=> true
149
- #
147
+ # Deletes queue. Any messages in the queue will be permanently lost.
148
+ # Returns +true+.
149
+ #
150
+ # NB: Use with caution; severe data loss is possible!
151
+ #
152
+ # queue.delete(true) #=> true
153
+ #
150
154
  def delete(force=false)
151
155
  @sqs.interface.delete_queue(@url)
152
156
  end
153
157
 
154
- # Sends new message to queue.
155
- # Returns new Message instance that has been sent to queue.
158
+ # Sends new message to queue.
159
+ # Returns new Message instance that has been sent to queue.
156
160
  def send_message(message)
157
161
  message = message.to_s
158
162
  res = @sqs.interface.send_message(@url, message)
@@ -161,13 +165,14 @@ module Aws
161
165
  msg.sent_at = Time.now
162
166
  msg
163
167
  end
168
+
164
169
  alias_method :push, :send_message
165
170
 
166
- # Retrieves several messages from queue.
167
- # Returns an array of Message instances.
168
- #
169
- # queue.receive_messages(2,10) #=> array of messages
170
- #
171
+ # Retrieves several messages from queue.
172
+ # Returns an array of Message instances.
173
+ #
174
+ # queue.receive_messages(2,10) #=> array of messages
175
+ #
171
176
  def receive_messages(number_of_messages=1, visibility=nil)
172
177
  list = @sqs.interface.receive_message(@url, number_of_messages, visibility)
173
178
  list.map! do |entry|
@@ -179,74 +184,74 @@ module Aws
179
184
  end
180
185
  end
181
186
 
182
- # Retrieves first accessible message from queue.
183
- # Returns Message instance or +nil+ it the queue is empty.
184
- #
185
- # queue.receive #=> #<Aws::Sqs::Message:0xb7bf0884 ... >
186
- #
187
+ # Retrieves first accessible message from queue.
188
+ # Returns Message instance or +nil+ it the queue is empty.
189
+ #
190
+ # queue.receive #=> #<Aws::Sqs::Message:0xb7bf0884 ... >
191
+ #
187
192
  def receive(visibility=nil)
188
193
  list = receive_messages(1, visibility)
189
194
  list.empty? ? nil : list[0]
190
195
  end
191
196
 
192
- # Pops (and deletes) first accessible message from queue.
193
- # Returns Message instance or +nil+ if the queue is empty.
194
- #
195
- # queue.pop #=> #<Aws::Sqs::Message:0xb7bf0884 ... >
196
- #
197
+ # Pops (and deletes) first accessible message from queue.
198
+ # Returns Message instance or +nil+ if the queue is empty.
199
+ #
200
+ # queue.pop #=> #<Aws::Sqs::Message:0xb7bf0884 ... >
201
+ #
197
202
  def pop
198
203
  list = @sqs.interface.pop_messages(@url, 1)
199
204
  return nil if list.empty?
200
205
  entry = list[0]
201
206
  msg = Message.new(self, entry['MessageId'], entry['ReceiptHandle'],
202
- entry['Body'], visibility)
207
+ entry['Body'], visibility)
203
208
  msg.received_at = Time.now
204
209
  msg.receive_checksum = entry['MD5OfBody']
205
210
  msg
206
211
  end
207
212
 
208
- # Retrieves +VisibilityTimeout+ value for the queue.
209
- # Returns new timeout value.
210
- #
211
- # queue.visibility #=> 30
212
- #
213
+ # Retrieves +VisibilityTimeout+ value for the queue.
214
+ # Returns new timeout value.
215
+ #
216
+ # queue.visibility #=> 30
217
+ #
213
218
  def visibility
214
219
  @sqs.interface.get_queue_attributes(@url, 'VisibilityTimeout')['VisibilityTimeout']
215
220
  end
216
221
 
217
- # Sets new +VisibilityTimeout+ for the queue.
218
- # Returns new timeout value.
219
- #
220
- # queue.visibility #=> 30
221
- # queue.visibility = 33
222
- # queue.visibility #=> 33
223
- #
222
+ # Sets new +VisibilityTimeout+ for the queue.
223
+ # Returns new timeout value.
224
+ #
225
+ # queue.visibility #=> 30
226
+ # queue.visibility = 33
227
+ # queue.visibility #=> 33
228
+ #
224
229
  def visibility=(visibility_timeout)
225
230
  @sqs.interface.set_queue_attributes(@url, 'VisibilityTimeout', visibility_timeout)
226
231
  visibility_timeout
227
232
  end
228
233
 
229
- # Sets new queue attribute value.
230
- # Not all attributes may be changed: +ApproximateNumberOfMessages+ (for example) is a read only attribute.
231
- # Returns a value to be assigned to attribute.
232
- # Currently, 'VisibilityTimeout' is the only settable queue attribute.
233
- # Attempting to set non-existent attributes generates an indignant
234
- # exception.
235
- #
236
- # queue.set_attribute('VisibilityTimeout', '100') #=> '100'
237
- # queue.get_attribute('VisibilityTimeout') #=> '100'
238
- #
234
+ # Sets new queue attribute value.
235
+ # Not all attributes may be changed: +ApproximateNumberOfMessages+ (for example) is a read only attribute.
236
+ # Returns a value to be assigned to attribute.
237
+ # Currently, 'VisibilityTimeout' is the only settable queue attribute.
238
+ # Attempting to set non-existent attributes generates an indignant
239
+ # exception.
240
+ #
241
+ # queue.set_attribute('VisibilityTimeout', '100') #=> '100'
242
+ # queue.get_attribute('VisibilityTimeout') #=> '100'
243
+ #
239
244
  def set_attribute(attribute, value)
240
245
  @sqs.interface.set_queue_attributes(@url, attribute, value)
241
246
  value
242
247
  end
243
248
 
244
- # Retrieves queue attributes.
245
- # At this moment Amazon supports +VisibilityTimeout+ and +ApproximateNumberOfMessages+ only.
246
- # If the name of attribute is set, returns its value. Otherwise, returns a hash of attributes.
247
- #
248
- # queue.get_attribute('VisibilityTimeout') #=> {"VisibilityTimeout"=>"45"}
249
- #
249
+ # Retrieves queue attributes.
250
+ # At this moment Amazon supports +VisibilityTimeout+ and +ApproximateNumberOfMessages+ only.
251
+ # If the name of attribute is set, returns its value. Otherwise, returns a hash of attributes.
252
+ #
253
+ # queue.get_attribute('VisibilityTimeout') #=> {"VisibilityTimeout"=>"45"}
254
+ #
250
255
  def get_attribute(attribute='All')
251
256
  attributes = @sqs.interface.get_queue_attributes(@url, attribute)
252
257
  attribute=='All' ? attributes : attributes[attribute]
@@ -254,37 +259,37 @@ module Aws
254
259
  end
255
260
 
256
261
  class Message
257
- attr_reader :queue, :id, :body, :visibility, :receipt_handle
262
+ attr_reader :queue, :id, :body, :visibility, :receipt_handle
258
263
  attr_accessor :sent_at, :received_at, :send_checksum, :receive_checksum
259
264
 
260
265
  def initialize(queue, id=nil, rh = nil, body=nil, visibility=nil)
261
- @queue = queue
262
- @id = id
266
+ @queue = queue
267
+ @id = id
263
268
  @receipt_handle = rh
264
- @body = body
265
- @visibility = visibility
266
- @sent_at = nil
269
+ @body = body
270
+ @visibility = visibility
271
+ @sent_at = nil
267
272
  @received_at = nil
268
273
  @send_checksum = nil
269
274
  @receive_checksum = nil
270
275
  end
271
276
 
272
- # Returns +Message+ instance body.
277
+ # Returns +Message+ instance body.
273
278
  def to_s
274
279
  @body
275
280
  end
276
281
 
277
- # Removes message from queue.
278
- # Returns +true+.
282
+ # Removes message from queue.
283
+ # Returns +true+.
279
284
  def delete
280
285
  @queue.sqs.interface.delete_message(@queue.url, @receipt_handle) if @receipt_handle
281
286
  end
282
-
287
+
283
288
  # Updates visibility timeout.
284
289
  def visibility=(visibility_timeout)
285
290
  if @receipt_handle
286
291
  @queue.sqs.interface.change_message_visibility(
287
- @queue.url, @receipt_handle, visibility_timeout
292
+ @queue.url, @receipt_handle, visibility_timeout
288
293
  )
289
294
  @visibility = visibility_timeout
290
295
  end
@@ -325,8 +325,8 @@ module Aws
325
325
  #
326
326
  def self.queue_name_by_url(queue_url)
327
327
  queue_url[/[^\/]*$/]
328
- rescue
329
- on_exception
328
+ # rescue
329
+ # on_exception
330
330
  end
331
331
 
332
332
  # Returns short queue name by url.
@@ -33,6 +33,13 @@ class TestSqs < Test::Unit::TestCase
33
33
  queue_url
34
34
  end
35
35
 
36
+ def test_on_exception_no_method_error
37
+ assert_raise Aws::ResourceNotFoundError do
38
+ Aws::Sqs::Queue.new(@s, "some_nonexistant_queue")
39
+ end
40
+ end
41
+
42
+
36
43
 
37
44
  #---------------------------
38
45
  # Rightscale::SqsInterface
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.4
4
+ version: 2.4.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,12 +11,12 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2011-02-25 00:00:00.000000000 -08:00
14
+ date: 2011-03-10 00:00:00.000000000 -08:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: uuidtools
19
- requirement: &28505268 !ruby/object:Gem::Requirement
19
+ requirement: &27101172 !ruby/object:Gem::Requirement
20
20
  none: false
21
21
  requirements:
22
22
  - - ! '>='
@@ -24,10 +24,10 @@ dependencies:
24
24
  version: '0'
25
25
  type: :runtime
26
26
  prerelease: false
27
- version_requirements: *28505268
27
+ version_requirements: *27101172
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: http_connection
30
- requirement: &28504980 !ruby/object:Gem::Requirement
30
+ requirement: &27100884 !ruby/object:Gem::Requirement
31
31
  none: false
32
32
  requirements:
33
33
  - - ! '>='
@@ -35,10 +35,10 @@ dependencies:
35
35
  version: '0'
36
36
  type: :runtime
37
37
  prerelease: false
38
- version_requirements: *28504980
38
+ version_requirements: *27100884
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: xml-simple
41
- requirement: &28504692 !ruby/object:Gem::Requirement
41
+ requirement: &27100596 !ruby/object:Gem::Requirement
42
42
  none: false
43
43
  requirements:
44
44
  - - ! '>='
@@ -46,10 +46,10 @@ dependencies:
46
46
  version: '0'
47
47
  type: :runtime
48
48
  prerelease: false
49
- version_requirements: *28504692
49
+ version_requirements: *27100596
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: activesupport
52
- requirement: &28504404 !ruby/object:Gem::Requirement
52
+ requirement: &27100308 !ruby/object:Gem::Requirement
53
53
  none: false
54
54
  requirements:
55
55
  - - ! '>='
@@ -57,7 +57,7 @@ dependencies:
57
57
  version: '0'
58
58
  type: :runtime
59
59
  prerelease: false
60
- version_requirements: *28504404
60
+ version_requirements: *27100308
61
61
  description: AWS Ruby Library for interfacing with Amazon Web Services including EC2,
62
62
  S3, SQS, SimpleDB and most of their other services as well. By http://www.appoxy.com
63
63
  email: travis@appoxy.com
@@ -135,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
135
  version: '0'
136
136
  requirements: []
137
137
  rubyforge_project:
138
- rubygems_version: 1.5.2
138
+ rubygems_version: 1.6.2
139
139
  signing_key:
140
140
  specification_version: 3
141
141
  summary: AWS Ruby Library for interfacing with Amazon Web Services. By http://www.appoxy.com