aws 1.11.9 → 1.11.36

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,19 +0,0 @@
1
- History.txt
2
- Manifest.txt
3
- README.txt
4
- Rakefile
5
- lib/awsbase/benchmark_fix.rb
6
- lib/awsbase/right_awsbase.rb
7
- lib/awsbase/support.rb
8
- lib/ec2/right_ec2.rb
9
- lib/right_aws.rb
10
- lib/s3/right_s3.rb
11
- lib/s3/right_s3_interface.rb
12
- lib/sdb/active_sdb.rb
13
- lib/sdb/right_sdb_interface.rb
14
- lib/sqs/right_sqs.rb
15
- lib/sqs/right_sqs_gen2.rb
16
- lib/sqs/right_sqs_gen2_interface.rb
17
- lib/sqs/right_sqs_interface.rb
18
- lib/acf/right_acf_interface.rb
19
-
data/Rakefile DELETED
@@ -1,17 +0,0 @@
1
- # -*- ruby -*-
2
-
3
- require 'rubygems'
4
- require 'hoe'
5
- require 'lib/right_aws.rb'
6
-
7
-
8
- Hoe.new('aws', RightAws::VERSION::STRING) do |p|
9
- p.rubyforge_name = 'spacegems'
10
- p.developer('Travis Reeder', 'travis@appoxy.com')
11
- # p.author = 'RightScale, Inc.'
12
- # p.email = 'rubygems@rightscale.com'
13
-
14
- end
15
-
16
-
17
- # vim: syntax=Ruby
@@ -1,286 +0,0 @@
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
- #
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
- class SqsGen2
67
- attr_reader :interface
68
-
69
- def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
70
- @interface = SqsGen2Interface.new(aws_access_key_id, aws_secret_access_key, params)
71
- end
72
-
73
- # Retrieves a list of queues.
74
- # Returns an +array+ of +Queue+ instances.
75
- #
76
- # RightAws::Sqs.queues #=> array of queues
77
- #
78
- def queues(prefix=nil)
79
- @interface.list_queues(prefix).map do |url|
80
- Queue.new(self, url)
81
- end
82
- end
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
- # RightAws::SqsGen2.queue('my_awesome_queue') #=> #<RightAws::SqsGen2::Queue:0xb7b626e4 ... >
88
- #
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 ? Queue.new(self, url) : nil
93
- end
94
-
95
-
96
- class Queue
97
- attr_reader :name, :url, :sqs
98
-
99
- # Returns Queue instance by queue name.
100
- # If the queue does not exist at Amazon SQS and +create+ is true, the method creates it.
101
- #
102
- # RightAws::SqsGen2::Queue.create(sqs, 'my_awesome_queue') #=> #<RightAws::SqsGen2::Queue:0xb7b626e4 ... >
103
- #
104
- def self.create(sqs, url_or_name, create=true, visibility=nil)
105
- sqs.queue(url_or_name, create, visibility)
106
- end
107
-
108
- # Creates new Queue instance.
109
- # Does not create a queue at Amazon.
110
- #
111
- # queue = RightAws::SqsGen2::Queue.new(sqs, 'my_awesome_queue')
112
- #
113
- def initialize(sqs, url_or_name)
114
- @sqs = sqs
115
- @url = @sqs.interface.queue_url_by_name(url_or_name)
116
- @name = @sqs.interface.queue_name_by_url(@url)
117
- end
118
-
119
- # Retrieves queue size.
120
- #
121
- # queue.size #=> 1
122
- #
123
- def size
124
- @sqs.interface.get_queue_length(@url)
125
- end
126
-
127
- # Clears queue, deleting only the visible messages. Any message within its visibility
128
- # timeout will not be deleted, and will re-appear in the queue in the
129
- # future when the timeout expires.
130
- #
131
- # To delete all messages in a queue and eliminate the chance of any
132
- # messages re-appearing in the future, it's best to delete the queue and
133
- # re-create it as a new queue. Note that doing this will take at least 60
134
- # s since SQS does not allow re-creation of a queue within this interval.
135
- #
136
- # queue.clear() #=> true
137
- #
138
- def clear()
139
- @sqs.interface.clear_queue(@url)
140
- end
141
-
142
- # Deletes queue. Any messages in the queue will be permanently lost.
143
- # Returns +true+.
144
- #
145
- # NB: Use with caution; severe data loss is possible!
146
- #
147
- # queue.delete(true) #=> true
148
- #
149
- def delete(force=false)
150
- @sqs.interface.delete_queue(@url)
151
- end
152
-
153
- # Sends new message to queue.
154
- # Returns new Message instance that has been sent to queue.
155
- def send_message(message)
156
- message = message.to_s
157
- res = @sqs.interface.send_message(@url, message)
158
- msg = Message.new(self, res['MessageId'], nil, message)
159
- msg.send_checksum = res['MD5OfMessageBody']
160
- msg.sent_at = Time.now
161
- msg
162
- end
163
- alias_method :push, :send_message
164
-
165
- # Retrieves several messages from queue.
166
- # Returns an array of Message instances.
167
- #
168
- # queue.receive_messages(2,10) #=> array of messages
169
- #
170
- def receive_messages(number_of_messages=1, visibility=nil)
171
- list = @sqs.interface.receive_message(@url, number_of_messages, visibility)
172
- list.map! do |entry|
173
- msg = Message.new(self, entry['MessageId'], entry['ReceiptHandle'],
174
- entry['Body'], visibility)
175
- msg.received_at = Time.now
176
- msg.receive_checksum = entry['MD5OfBody']
177
- msg
178
- end
179
- end
180
-
181
- # Retrieves first accessible message from queue.
182
- # Returns Message instance or +nil+ it the queue is empty.
183
- #
184
- # queue.receive #=> #<RightAws::SqsGen2::Message:0xb7bf0884 ... >
185
- #
186
- def receive(visibility=nil)
187
- list = receive_messages(1, visibility)
188
- list.empty? ? nil : list[0]
189
- end
190
-
191
- # Pops (and deletes) first accessible message from queue.
192
- # Returns Message instance or +nil+ if the queue is empty.
193
- #
194
- # queue.pop #=> #<RightAws::SqsGen2::Message:0xb7bf0884 ... >
195
- #
196
- def pop
197
- list = @sqs.interface.pop_messages(@url, 1)
198
- return nil if list.empty?
199
- entry = list[0]
200
- msg = Message.new(self, entry['MessageId'], entry['ReceiptHandle'],
201
- entry['Body'], visibility)
202
- msg.received_at = Time.now
203
- msg.receive_checksum = entry['MD5OfBody']
204
- msg
205
- end
206
-
207
- # Retrieves +VisibilityTimeout+ value for the queue.
208
- # Returns new timeout value.
209
- #
210
- # queue.visibility #=> 30
211
- #
212
- def visibility
213
- @sqs.interface.get_queue_attributes(@url, 'VisibilityTimeout')['VisibilityTimeout']
214
- end
215
-
216
- # Sets new +VisibilityTimeout+ for the queue.
217
- # Returns new timeout value.
218
- #
219
- # queue.visibility #=> 30
220
- # queue.visibility = 33
221
- # queue.visibility #=> 33
222
- #
223
- def visibility=(visibility_timeout)
224
- @sqs.interface.set_queue_attributes(@url, 'VisibilityTimeout', visibility_timeout)
225
- visibility_timeout
226
- end
227
-
228
- # Sets new queue attribute value.
229
- # Not all attributes may be changed: +ApproximateNumberOfMessages+ (for example) is a read only attribute.
230
- # Returns a value to be assigned to attribute.
231
- # Currently, 'VisibilityTimeout' is the only settable queue attribute.
232
- # Attempting to set non-existent attributes generates an indignant
233
- # exception.
234
- #
235
- # queue.set_attribute('VisibilityTimeout', '100') #=> '100'
236
- # queue.get_attribute('VisibilityTimeout') #=> '100'
237
- #
238
- def set_attribute(attribute, value)
239
- @sqs.interface.set_queue_attributes(@url, attribute, value)
240
- value
241
- end
242
-
243
- # Retrieves queue attributes.
244
- # At this moment Amazon supports +VisibilityTimeout+ and +ApproximateNumberOfMessages+ only.
245
- # If the name of attribute is set, returns its value. Otherwise, returns a hash of attributes.
246
- #
247
- # queue.get_attribute('VisibilityTimeout') #=> {"VisibilityTimeout"=>"45"}
248
- #
249
- def get_attribute(attribute='All')
250
- attributes = @sqs.interface.get_queue_attributes(@url, attribute)
251
- attribute=='All' ? attributes : attributes[attribute]
252
- end
253
- end
254
-
255
- class Message
256
- attr_reader :queue, :id, :body, :visibility, :receipt_handle
257
- attr_accessor :sent_at, :received_at, :send_checksum, :receive_checksum
258
-
259
- def initialize(queue, id=nil, rh = nil, body=nil, visibility=nil)
260
- @queue = queue
261
- @id = id
262
- @receipt_handle = rh
263
- @body = body
264
- @visibility = visibility
265
- @sent_at = nil
266
- @received_at = nil
267
- @send_checksum = nil
268
- @receive_checksum = nil
269
- end
270
-
271
- # Returns +Message+ instance body.
272
- def to_s
273
- @body
274
- end
275
-
276
- # Removes message from queue.
277
- # Returns +true+.
278
- def delete
279
- @queue.sqs.interface.delete_message(@queue.url, @receipt_handle) if @receipt_handle
280
- end
281
-
282
- end
283
-
284
-
285
- end
286
- end
@@ -1,444 +0,0 @@
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
- API_VERSION = "2008-01-01"
42
- DEFAULT_HOST = "queue.amazonaws.com"
43
- DEFAULT_PORT = 443
44
- DEFAULT_PROTOCOL = 'https'
45
- REQUEST_TTL = 30
46
- DEFAULT_VISIBILITY_TIMEOUT = 30
47
-
48
-
49
- @@bench = AwsBenchmarkingBlock.new
50
- def self.bench_xml
51
- @@bench.xml
52
- end
53
- def self.bench_sqs
54
- @@bench.service
55
- end
56
-
57
- @@api = API_VERSION
58
- def self.api
59
- @@api
60
- end
61
-
62
- # Creates a new SqsInterface instance. This instance is limited to
63
- # operations on SQS objects created with Amazon's 2008-01-01 API version. This
64
- # interface will not work on objects created with prior API versions. See
65
- # Amazon's article "Migrating to Amazon SQS API version 2008-01-01" at:
66
- # http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1148
67
- #
68
- # sqs = RightAws::SqsGen2Interface.new('1E3GDYEOGFJPIT75KDT40','hgTHt68JY07JKUY08ftHYtERkjgtfERn57DFE379', {:multi_thread => true, :logger => Logger.new('/tmp/x.log')})
69
- #
70
- # Params is a hash:
71
- #
72
- # {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com' (default)
73
- # :port => 443 # Amazon service port: 80 or 443 (default)
74
- # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false (default)
75
- # :signature_version => '0' # The signature version : '0' or '1'(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
- service = param[:queue_url] ? URI(param[:queue_url]).path : '/'
102
- param.each{ |key, value| param.delete(key) if (value.nil? || key.is_a?(Symbol)) }
103
- service_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
- service_hash.update(param)
108
- service_params = signed_service_params(@aws_secret_access_key, service_hash, :get, @params[:server], service)
109
- request = Net::HTTP::Get.new("#{AwsUtils.URLencode(service)}?#{service_params}")
110
- # prepare output hash
111
- { :request => request,
112
- :server => @params[:server],
113
- :port => @params[:port],
114
- :protocol => @params[:protocol] }
115
- end
116
-
117
- def generate_post_request(action, param={}) # :nodoc:
118
- service = param[:queue_url] ? URI(param[:queue_url]).path : '/'
119
- message = param[:message] # extract message body if nesessary
120
- param.each{ |key, value| param.delete(key) if (value.nil? || key.is_a?(Symbol)) }
121
- service_hash = { "Action" => action,
122
- "Expires" => (Time.now + REQUEST_TTL).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
123
- "AWSAccessKeyId" => @aws_access_key_id,
124
- "MessageBody" => message,
125
- "Version" => API_VERSION }
126
- service_hash.update(param)
127
- #
128
- service_params = signed_service_params(@aws_secret_access_key, service_hash, :post, @params[:server], service)
129
- request = Net::HTTP::Post.new(AwsUtils::URLencode(service))
130
- request['Content-Type'] = 'application/x-www-form-urlencoded'
131
- request.body = service_params
132
- # prepare output hash
133
- { :request => request,
134
- :server => @params[:server],
135
- :port => @params[:port],
136
- :protocol => @params[:protocol] }
137
- end
138
-
139
-
140
- # Sends request to Amazon and parses the response
141
- # Raises AwsError if any banana happened
142
- def request_info(request, parser) # :nodoc:
143
- thread = @params[:multi_thread] ? Thread.current : Thread.main
144
- thread[:sqs_connection] ||= Rightscale::HttpConnection.new(:exception => AwsError, :logger => @logger)
145
- request_info_impl(thread[:sqs_connection], @@bench, request, parser)
146
- end
147
-
148
-
149
- # Creates a new queue, returning its URI.
150
- #
151
- # sqs.create_queue('my_awesome_queue') #=> 'http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue'
152
- #
153
- def create_queue(queue_name, default_visibility_timeout=nil)
154
- req_hash = generate_request('CreateQueue', 'QueueName' => queue_name,
155
- 'DefaultVisibilityTimeout' => default_visibility_timeout || DEFAULT_VISIBILITY_TIMEOUT )
156
- request_info(req_hash, SqsCreateQueueParser.new(:logger => @logger))
157
- rescue
158
- on_exception
159
- end
160
-
161
- # Lists all queues owned by this user that have names beginning with +queue_name_prefix+.
162
- # If +queue_name_prefix+ is omitted then retrieves a list of all queues.
163
- # Queue creation is an eventual operation and created queues may not show up in immediately subsequent list_queues calls.
164
- #
165
- # sqs.create_queue('my_awesome_queue')
166
- # sqs.create_queue('my_awesome_queue_2')
167
- # sqs.list_queues('my_awesome') #=> ['http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue','http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue_2']
168
- #
169
- def list_queues(queue_name_prefix=nil)
170
- req_hash = generate_request('ListQueues', 'QueueNamePrefix' => queue_name_prefix)
171
- request_info(req_hash, SqsListQueuesParser.new(:logger => @logger))
172
- rescue
173
- on_exception
174
- end
175
-
176
- # Deletes queue. Any messages in the queue are permanently lost.
177
- # Returns +true+ or an exception.
178
- # Queue deletion can take up to 60 s to propagate through SQS. Thus, after a deletion, subsequent list_queues calls
179
- # may still show the deleted queue. It is not unusual within the 60 s window to see the deleted queue absent from
180
- # one list_queues call but present in the subsequent one. Deletion is eventual.
181
- #
182
- # sqs.delete_queue('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue_2') #=> true
183
- #
184
- #
185
- def delete_queue(queue_url)
186
- req_hash = generate_request('DeleteQueue', :queue_url => queue_url)
187
- request_info(req_hash, SqsStatusParser.new(:logger => @logger))
188
- rescue
189
- on_exception
190
- end
191
-
192
- # Retrieves the queue attribute(s). Returns a hash of attribute(s) or an exception.
193
- #
194
- # sqs.get_queue_attributes('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue')
195
- # #=> {"ApproximateNumberOfMessages"=>"0", "VisibilityTimeout"=>"30"}
196
- #
197
- def get_queue_attributes(queue_url, attribute='All')
198
- req_hash = generate_request('GetQueueAttributes', 'AttributeName' => attribute, :queue_url => queue_url)
199
- request_info(req_hash, SqsGetQueueAttributesParser.new(:logger => @logger))
200
- rescue
201
- on_exception
202
- end
203
-
204
- # Sets queue attribute. Returns +true+ or an exception.
205
- #
206
- # sqs.set_queue_attributes('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue', "VisibilityTimeout", 10) #=> true
207
- #
208
- # From the SQS Dev Guide:
209
- # "Currently, you can set only the
210
- # VisibilityTimeout attribute for a queue...
211
- # When you change a queue's attributes, the change can take up to 60 seconds to propagate
212
- # throughout the SQS system."
213
- #
214
- # NB: Attribute values may not be immediately available to other queries
215
- # for some time after an update. See the SQS documentation for
216
- # semantics, but in general propagation can take up to 60 s.
217
- def set_queue_attributes(queue_url, attribute, value)
218
- req_hash = generate_request('SetQueueAttributes', 'Attribute.Name' => attribute, 'Attribute.Value' => value, :queue_url => queue_url)
219
- request_info(req_hash, SqsStatusParser.new(:logger => @logger))
220
- rescue
221
- on_exception
222
- end
223
-
224
- # Retrieves a list of messages from queue. Returns an array of hashes in format: <tt>{:id=>'message_id', body=>'message_body'}</tt>
225
- #
226
- # sqs.receive_message('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue',10, 5) #=>
227
- # [{"ReceiptHandle"=>"Euvo62...kw==", "MD5OfBody"=>"16af2171b5b83cfa35ce254966ba81e3",
228
- # "Body"=>"Goodbyte World!", "MessageId"=>"MUM4WlAyR...pYOTA="}, ..., {}]
229
- #
230
- # Normally this call returns fewer messages than the maximum specified,
231
- # even if they are available.
232
- #
233
- def receive_message(queue_url, max_number_of_messages=1, visibility_timeout=nil)
234
- return [] if max_number_of_messages == 0
235
- req_hash = generate_post_request('ReceiveMessage', 'MaxNumberOfMessages' => max_number_of_messages, 'VisibilityTimeout' => visibility_timeout,
236
- :queue_url => queue_url )
237
- request_info(req_hash, SqsReceiveMessageParser.new(:logger => @logger))
238
- rescue
239
- on_exception
240
- end
241
-
242
- # Sends a new message to a queue. Message size is limited to 8 KB.
243
- # If successful, this call returns a hash containing key/value pairs for
244
- # "MessageId" and "MD5OfMessageBody":
245
- #
246
- # sqs.send_message('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue', 'message_1') #=> "1234567890...0987654321"
247
- # => {"MessageId"=>"MEs4M0JKNlRCRTBBSENaMjROTk58QVFRNzNEREhDVFlFOVJDQ1JKNjF8UTdBRllCUlJUMjhKMUI1WDJSWDE=", "MD5OfMessageBody"=>"16af2171b5b83cfa35ce254966ba81e3"}
248
- #
249
- # On failure, send_message raises an exception.
250
- #
251
- #
252
- def send_message(queue_url, message)
253
- req_hash = generate_post_request('SendMessage', :message => message, :queue_url => queue_url)
254
- request_info(req_hash, SqsSendMessagesParser.new(:logger => @logger))
255
- rescue
256
- on_exception
257
- end
258
-
259
- # Same as send_message
260
- alias_method :push_message, :send_message
261
-
262
-
263
- # Deletes message from queue. Returns +true+ or an exception. Amazon
264
- # returns +true+ on deletion of non-existent messages. You must use the
265
- # receipt handle for a message to delete it, not the message ID.
266
- #
267
- # From the SQS Developer Guide:
268
- # "It is possible you will receive a message even after you have deleted it. This might happen
269
- # on rare occasions if one of the servers storing a copy of the message is unavailable when
270
- # you request to delete the message. The copy remains on the server and might be returned to
271
- # you again on a subsequent receive request. You should create your system to be
272
- # idempotent so that receiving a particular message more than once is not a problem. "
273
- #
274
- # sqs.delete_message('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue', 'Euvo62/1nlIet...ao03hd9Sa0w==') #=> true
275
- #
276
- def delete_message(queue_url, receipt_handle)
277
- req_hash = generate_request('DeleteMessage', 'ReceiptHandle' => receipt_handle, :queue_url => queue_url)
278
- request_info(req_hash, SqsStatusParser.new(:logger => @logger))
279
- rescue
280
- on_exception
281
- end
282
-
283
- # Given the queue's short name, this call returns the queue URL or +nil+ if queue is not found
284
- # sqs.queue_url_by_name('my_awesome_queue') #=> 'http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue'
285
- #
286
- def queue_url_by_name(queue_name)
287
- return queue_name if queue_name.include?('/')
288
- queue_urls = list_queues(queue_name)
289
- queue_urls.each do |queue_url|
290
- return queue_url if queue_name_by_url(queue_url) == queue_name
291
- end
292
- nil
293
- rescue
294
- on_exception
295
- end
296
-
297
- # Returns short queue name by url.
298
- #
299
- # RightSqs.queue_name_by_url('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue') #=> 'my_awesome_queue'
300
- #
301
- def self.queue_name_by_url(queue_url)
302
- queue_url[/[^\/]*$/]
303
- rescue
304
- on_exception
305
- end
306
-
307
- # Returns short queue name by url.
308
- #
309
- # sqs.queue_name_by_url('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue') #=> 'my_awesome_queue'
310
- #
311
- def queue_name_by_url(queue_url)
312
- self.class.queue_name_by_url(queue_url)
313
- rescue
314
- on_exception
315
- end
316
-
317
- # Returns approximate number of messages in queue.
318
- #
319
- # sqs.get_queue_length('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue') #=> 3
320
- #
321
- def get_queue_length(queue_url)
322
- get_queue_attributes(queue_url)['ApproximateNumberOfMessages'].to_i
323
- rescue
324
- on_exception
325
- end
326
-
327
- # Removes all visible messages from queue. Return +true+ or an exception.
328
- #
329
- # sqs.clear_queue('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue') #=> true
330
- #
331
- def clear_queue(queue_url)
332
- while (pop_messages(queue_url, 10).length > 0) ; end # delete all messages in queue
333
- true
334
- rescue
335
- on_exception
336
- end
337
-
338
- # 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>.
339
- #
340
- # sqs.pop_messages('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue', 3) #=>
341
- # [{"ReceiptHandle"=>"Euvo62/...+Zw==", "MD5OfBody"=>"16af2...81e3", "Body"=>"Goodbyte World!",
342
- # "MessageId"=>"MEZI...JSWDE="}, {...}, ... , {...} ]
343
- #
344
- def pop_messages(queue_url, number_of_messages=1)
345
- messages = receive_message(queue_url, number_of_messages)
346
- messages.each do |message|
347
- delete_message(queue_url, message['ReceiptHandle'])
348
- end
349
- messages
350
- rescue
351
- on_exception
352
- end
353
-
354
- # Pops (retrieves and deletes) first accessible message from queue. Returns the message in format <tt>{:id=>'message_id', :body=>'message_body'}</tt> or +nil+.
355
- #
356
- # sqs.pop_message('http://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue') #=>
357
- # {:id=>"12345678904GEZX9746N|0N9ED344VK5Z3SV1DTM0|1RVYH4X3TJ0987654321", :body=>"message_1"}
358
- #
359
- def pop_message(queue_url)
360
- messages = pop_messages(queue_url)
361
- messages.blank? ? nil : messages[0]
362
- rescue
363
- on_exception
364
- end
365
-
366
- #-----------------------------------------------------------------
367
- # PARSERS: Status Response Parser
368
- #-----------------------------------------------------------------
369
-
370
- class SqsStatusParser < RightAWSParser # :nodoc:
371
- def tagend(name)
372
- if name == 'ResponseMetadata'
373
- @result = true
374
- end
375
- end
376
- end
377
-
378
- #-----------------------------------------------------------------
379
- # PARSERS: Queue
380
- #-----------------------------------------------------------------
381
-
382
- class SqsCreateQueueParser < RightAWSParser # :nodoc:
383
- def tagend(name)
384
- @result = @text if name == 'QueueUrl'
385
- end
386
- end
387
-
388
- class SqsListQueuesParser < RightAWSParser # :nodoc:
389
- def reset
390
- @result = []
391
- end
392
- def tagend(name)
393
- @result << @text if name == 'QueueUrl'
394
- end
395
- end
396
-
397
- class SqsGetQueueAttributesParser < RightAWSParser # :nodoc:
398
- def reset
399
- @result = {}
400
- end
401
- def tagend(name)
402
- case name
403
- when 'Name' ; @current_attribute = @text
404
- when 'Value' ; @result[@current_attribute] = @text
405
- end
406
- end
407
- end
408
-
409
- #-----------------------------------------------------------------
410
- # PARSERS: Messages
411
- #-----------------------------------------------------------------
412
-
413
- class SqsReceiveMessageParser < RightAWSParser # :nodoc:
414
- def reset
415
- @result = []
416
- end
417
- def tagstart(name, attributes)
418
- @current_message = {} if name == 'Message'
419
- end
420
- def tagend(name)
421
- case name
422
- when 'MessageId' ; @current_message['MessageId'] = @text
423
- when 'ReceiptHandle' ; @current_message['ReceiptHandle'] = @text
424
- when 'MD5OfBody' ; @current_message['MD5OfBody'] = @text
425
- when 'Body'; @current_message['Body'] = @text; @result << @current_message
426
- end
427
- end
428
- end
429
-
430
- class SqsSendMessagesParser < RightAWSParser # :nodoc:
431
- def reset
432
- @result = {}
433
- end
434
- def tagend(name)
435
- case name
436
- when 'MessageId' ; @result['MessageId'] = @text
437
- when 'MD5OfMessageBody' ; @result['MD5OfMessageBody'] = @text
438
- end
439
- end
440
- end
441
-
442
- end
443
-
444
- end