aws 2.4.4 → 2.4.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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