sqs_async 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sqs.rb ADDED
@@ -0,0 +1,162 @@
1
+ require 'uri'
2
+ require 'cgi'
3
+ require 'hmac'
4
+ require 'hmac-sha2'
5
+ require 'base64'
6
+ require 'net/http'
7
+ require 'time'
8
+ require 'nokogiri'
9
+ require 'json'
10
+ require 'eventmachine'
11
+ require 'em-http-request'
12
+ require 'sqs_message'
13
+ require 'sqs_queue'
14
+ require 'sqs_attributes'
15
+ require 'logger'
16
+
17
+ module SQS
18
+ attr_accessor :aws_key, :aws_secret, :regions, :default_parameters, :post_options
19
+
20
+ def list_queues(options={})
21
+ prefix = options.delete(:prefix)
22
+ match = options.delete(:match)
23
+
24
+ options.merge!( "Action" => "ListQueues" )
25
+ options.merge!( "QueueNamePrefix" => encode(prefix) ) if prefix
26
+
27
+ call_amazon(options) do |req|
28
+ queues = SQSQueue.parse(req.response)
29
+ queues.select!{|q| q.queue_url.path.match(match) } if match
30
+ queues
31
+ end
32
+ end
33
+
34
+ def receive_message(options={})
35
+ raise "no target queue specified" unless options[:queue]
36
+ options.merge!("Action" => "ReceiveMessage", "MaxNumberOfMessages" => 10 )
37
+ call_amazon(options){ |req| SQSMessage.parse(req.response) }
38
+ end
39
+
40
+ def delete_message(options={})
41
+ raise "no Message specified" unless options[:message]
42
+ options.merge!("Action" => "DeleteMessage", "ReceiptHandle" => options.delete(:message).receipt_handle)
43
+ call_amazon(options)
44
+ end
45
+
46
+ def get_queue_attributes(options={})
47
+ raise "no target queue specified" unless options[:queue]
48
+ options.merge!( "Action" => "GetQueueAttributes", "AttributeName" => "All" )
49
+ call_amazon(options){ |req| SQSAttributes.parse(req.response) }
50
+ end
51
+
52
+ private
53
+
54
+ def call_amazon(options)
55
+ endpoint = (options[:queue] != nil) ? options.delete(:queue).queue_url : "http://" << ( options.delete(:host) || region_host(:us_east) )
56
+ callbacks = options.delete(:callbacks) || {:success=>nil, :failure =>nil }
57
+
58
+ params = sign_params( endpoint, options )
59
+ req = EM::HttpRequest.new("#{endpoint}?#{params}").get
60
+ req.callback do |req|
61
+ if(req.response.to_s.match(/<ErrorResponse>/i))
62
+ on_failure(req, callbacks)
63
+ else
64
+ result = req
65
+ result = yield req if block_given?
66
+ callbacks[:success].call(result) if callbacks[:success]
67
+ end
68
+ end
69
+ req.errback do |req|
70
+ on_failure(req, callbacks)
71
+ end
72
+ end
73
+
74
+ def on_failure(req, callbacks)
75
+ result = (req.error != nil) ? req.error : req.response
76
+ log result
77
+ callbacks[:failure].call(result) if callbacks[:failure]
78
+ end
79
+
80
+ def sign_params(uri, opts)
81
+ uri = URI.parse(uri) if uri.kind_of? String
82
+ opts = default_paramters.merge(opts)
83
+
84
+ sorted_params = opts.sort {|x,y| x[0] <=> y[0]}
85
+ encoded_params = sorted_params.collect do |p|
86
+ encode(p[0].to_s) << "=" << encode(p[1].to_s)
87
+ end
88
+ params_string = encoded_params.join("&")
89
+
90
+ req_desc = ["GET", uri.host.downcase, uri.request_uri, params_string].join("\n")
91
+ params_string << "&Signature=" << generate_signature(req_desc)
92
+ end
93
+
94
+ def generate_signature(request_description)
95
+ hmac = HMAC::SHA256.new(aws_secret)
96
+ hmac.update(request_description)
97
+ encode(Base64.encode64(hmac.digest).chomp)
98
+ end
99
+
100
+ def encoding_exclusions
101
+ /[^\w\d\-\_\.\~]/
102
+ end
103
+
104
+ def encode(val)
105
+ URI.encode(val, encoding_exclusions)
106
+ end
107
+
108
+ def region_host(key)
109
+ regions[key][:uri]
110
+ end
111
+
112
+ def regions
113
+ @regions ||= Regions
114
+ @regions
115
+ end
116
+
117
+ def default_paramters
118
+ @default_paramters ||= Parameters.merge("AWSAccessKeyId" => aws_key)
119
+ @default_paramters.merge("Expires" => (Time.now+(60*30)).utc.iso8601)
120
+ end
121
+
122
+ def post_options
123
+ @post_options ||= PostOptions
124
+ @post_options
125
+ end
126
+
127
+ def logger
128
+ return @logger if @logger
129
+
130
+ @logger = Logger.new @log_path || "./sqs_async.log"
131
+ @logger.level = @log_level || Logger::WARN
132
+ @logger
133
+ end
134
+
135
+ def log(msg)
136
+ log_msg = ["SERVICE ERROR"]
137
+ log_msg << caller[0..7].join("\n\t")
138
+ log_msg << "-".ljust(80, "-")
139
+ log_msg << msg
140
+ log_msg << "-".ljust(80, "-")
141
+ logger.error(log_msg.join("\n"))
142
+ end
143
+
144
+ Regions = {
145
+ :us_east => { :name => "US-East (Northern Virginia) Region", :uri => "sqs.us-east-1.amazonaws.com"},
146
+ :us_west => { :name => "US-West (Northern California) Region", :uri => "sqs.us-west-1.amazonaws.com"},
147
+ :eu => { :name => "EU (Ireland) Region", :uri => "sqs.eu-west-1.amazonaws.com"},
148
+ :asia_singapore => { :name => "Asia Pacific (Singapore) Region", :uri => "sqs.ap-southeast-1.amazonaws.com"},
149
+ :asia_tokyo => { :name => "Asia Pacific (Tokyo) Region", :uri => "sqs.ap-northeast-1.amazonaws.com"}
150
+ }
151
+
152
+
153
+ Parameters = {
154
+ "Version" => "2009-02-01",
155
+ "SignatureVersion"=>"2",
156
+ "SignatureMethod"=>"HmacSHA256",
157
+ }
158
+
159
+ PostOptions = {
160
+ "Content-Type" => "application/x-www-form-urlencoded"
161
+ }
162
+ end
@@ -0,0 +1,38 @@
1
+ require 'nokogiri'
2
+ require 'json'
3
+ require 'base64'
4
+ require 'ostruct'
5
+
6
+ class SQSAttributes
7
+ attr_accessor :approximate_number_of_messages,
8
+ :approximate_number_of_messages_not_visible,
9
+ :visibility_timeout,
10
+ :create_timestamp,
11
+ :last_modified_timestamp,
12
+ :policy,
13
+ :maximum_message_size,
14
+ :message_retention_period,
15
+ :queue_arn
16
+
17
+ def self.parse(xml)
18
+ doc = Nokogiri::XML(xml)
19
+ queue_data = SQSAttributes.new
20
+ doc.search("Attribute").each do |attribute|
21
+ meth = underscore(attribute.at("Name").text)
22
+ if queue_data.respond_to? meth.to_sym
23
+ queue_data.send "#{meth}=", attribute.at("Value").text
24
+ end
25
+ end
26
+ queue_data
27
+ end
28
+
29
+ # Taken from ActiveSupport. License information can be found at rubyonrails.org
30
+ def self.underscore(camel_cased_word)
31
+ word = camel_cased_word.to_s.dup
32
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
33
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
34
+ word.tr!("-", "_")
35
+ word.downcase!
36
+ word
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ require 'nokogiri'
2
+ require 'json'
3
+ require 'base64'
4
+ require 'ostruct'
5
+
6
+ class SQSMessage
7
+ attr_accessor :body, :md5_of_body, :message_id, :receipt_handle
8
+
9
+ def self.parse(xml)
10
+ doc = Nokogiri::XML(xml)
11
+ messages = []
12
+ doc.search("Message").each do |message_element|
13
+ s = SQSMessage.new
14
+ s.body = message_element.at("Body").text
15
+ s.md5_of_body = message_element.at("MD5OfBody").text
16
+ s.message_id = message_element.at("MessageId").text
17
+ s.receipt_handle = message_element.at("ReceiptHandle").text.strip
18
+ messages << s
19
+ end
20
+ messages
21
+ end
22
+ end
data/lib/sqs_queue.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'nokogiri'
2
+ require 'json'
3
+ require 'base64'
4
+
5
+ class SQSQueue
6
+ attr_accessor :queue_url
7
+
8
+ def self.parse(xml)
9
+ doc = Nokogiri::XML(xml)
10
+ queues = []
11
+ doc.search("QueueUrl").each do |element|
12
+ s = SQSQueue.new
13
+ s.queue_url = URI.parse(element.text)
14
+ queues << s
15
+ end
16
+ queues
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <DeleteQueueResponse>
3
+ <ResponseMetadata>
4
+ <RequestId>
5
+ 6fde8d1e-52cd-4581-8cd9-c512f4c64223
6
+ </RequestId>
7
+ </ResponseMetadata>
8
+ </DeleteQueueResponse>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ErrorResponse>
3
+ <Error>
4
+ <Type>
5
+ Sender
6
+ </Type>
7
+ <Code>
8
+ AuthFailure
9
+ </Code>
10
+ <Message>
11
+ The provided signature is not valid for this access token
12
+ </Message>
13
+ <Detail/>
14
+ </Error>
15
+ <RequestId>
16
+ ef3aba6a-dc84-4937-91bf-cef2ddd6775a
17
+ </RequestId>
18
+ </ErrorResponse>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ListQueuesResponse>
3
+ <ListQueuesResult>
4
+ <QueueUrl>
5
+ http://sqs.us-east-1.amazonaws.com/123456789012/testQueue
6
+ </QueueUrl>
7
+ </ListQueuesResult>
8
+ <ResponseMetadata>
9
+ <RequestId>
10
+ 725275ae-0b9b-4762-b238-436d7c65a1ac
11
+ </RequestId>
12
+ </ResponseMetadata>
13
+ </ListQueuesResponse>
@@ -0,0 +1,40 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <GetQueueAttributesResponse>
3
+ <GetQueueAttributesResult>
4
+ <Attribute>
5
+ <Name>VisibilityTimeout</Name>
6
+ <Value>30</Value>
7
+ </Attribute>
8
+ <Attribute>
9
+ <Name>ApproximateNumberOfMessages</Name>
10
+ <Value>0</Value>
11
+ </Attribute>
12
+ <Attribute>
13
+ <Name>ApproximateNumberOfMessagesNotVisible</Name>
14
+ <Value>0</Value>
15
+ </Attribute>
16
+ <Attribute>
17
+ <Name>CreatedTimestamp</Name>
18
+ <Value>1286771522</Value>
19
+ </Attribute>
20
+ <Attribute>
21
+ <Name>LastModifiedTimestamp</Name>
22
+ <Value>1286771522</Value>
23
+ </Attribute>
24
+ <Attribute>
25
+ <Name>QueueArn</Name>
26
+ <Value>arn:aws:sqs:us-east-1:123456789012:qfoo</Value>
27
+ </Attribute>
28
+ <Attribute>
29
+ <Name>MaximumMessageSize</Name>
30
+ <Value>8192</Value>
31
+ </Attribute>
32
+ <Attribute>
33
+ <Name>MessageRetentionPeriod</Name>
34
+ <Value>345600</Value>
35
+ </Attribute>
36
+ </GetQueueAttributesResult>
37
+ <ResponseMetadata>
38
+ <RequestId>1ea71be5-b5a2-4f9d-b85a-945d8d08cd0b</RequestId>
39
+ </ResponseMetadata>
40
+ </GetQueueAttributesResponse>
@@ -0,0 +1,40 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ReceiveMessageResponse>
3
+ <ReceiveMessageResult>
4
+ <Message>
5
+ <MessageId>
6
+ 5fea7756-0ea4-451a-a703-a558b933e274
7
+ </MessageId>
8
+ <ReceiptHandle>
9
+ MbZj6wDWli+JvwwJaBV+3dcjk2YW2vA3+STFFljTM8tJJg6HRG6PYSasuWXPJB+Cw
10
+ Lj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ+QE
11
+ auMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=
12
+ </ReceiptHandle>
13
+ <MD5OfBody>
14
+ fafb00f5732ab283681e124bf8747ed1
15
+ </MD5OfBody>
16
+ <Body>This is a test message</Body>
17
+ <Attribute>
18
+ <Name>SenderId</Name>
19
+ <Value>195004372649</Value>
20
+ </Attribute>
21
+ <Attribute>
22
+ <Name>SentTimestamp</Name>
23
+ <Value>1238099229000</Value>
24
+ </Attribute>
25
+ <Attribute>
26
+ <Name>ApproximateReceiveCount</Name>
27
+ <Value>5</Value>
28
+ </Attribute>
29
+ <Attribute>
30
+ <Name>ApproximateFirstReceiveTimestamp</Name>
31
+ <Value>1250700979248</Value>
32
+ </Attribute>
33
+ </Message>
34
+ </ReceiveMessageResult>
35
+ <ResponseMetadata>
36
+ <RequestId>
37
+ b6633655-283d-45b4-aee4-4e84e0ae6afa
38
+ </RequestId>
39
+ </ResponseMetadata>
40
+ </ReceiveMessageResponse>
@@ -0,0 +1,100 @@
1
+ ENV["BUBBLE_ENV"] = "test"
2
+
3
+ $:.unshift(File.dirname(__FILE__))
4
+ %w{ ../ lib config vendor/sqs_async/lib }.each do |d|
5
+ $:.unshift(File.dirname(__FILE__)+"/#{d}/")
6
+ end
7
+
8
+ require 'bundler/setup'
9
+ require 'rspec'
10
+ require 'timecop'
11
+ require 'em-http-request'
12
+
13
+ require 'sqs'
14
+ require 'sqs_message'
15
+ require 'sqs_queue'
16
+ require 'sqs_attributes'
17
+
18
+
19
+ RSpec.configure do |config|
20
+ config.mock_framework = :mocha
21
+
22
+ def xml_fixture(name)
23
+ File.read(File.dirname(__FILE__)+"/fixtures/#{name}.xml")
24
+ end
25
+ end
26
+
27
+ module EventMachine
28
+ class MockHttpRequest
29
+ def initialize *args
30
+ @callbacks = []
31
+ @errbacks = []
32
+ end
33
+
34
+ def get *args
35
+ return self
36
+ end
37
+
38
+ def post *args
39
+ return self
40
+ end
41
+
42
+ def callback &block
43
+ @callbacks << block
44
+ end
45
+
46
+ def errback &block
47
+ @errbacks << block
48
+ end
49
+
50
+ def succeed(response)
51
+ @callbacks.each {|c| c.call(response)}
52
+ reset
53
+ end
54
+
55
+ def error(response)
56
+ @errbacks.each {|c| c.call(response)}
57
+ reset
58
+ end
59
+
60
+ def reset
61
+ @callbacks = []
62
+ @errbacks = []
63
+ end
64
+ end
65
+
66
+ class HttpRequest
67
+ def self.new *args
68
+ request = MockHttpRequest.new
69
+ connection_instances << request
70
+ request
71
+ end
72
+
73
+ def self.connection_instances
74
+ @connection_instances ||= []
75
+ end
76
+
77
+ def self.succeed(response)
78
+ connection_instances.each do |conn|
79
+ conn.succeed(response)
80
+ end
81
+ end
82
+
83
+ def self.error(response)
84
+ connection_instances.each do |conn|
85
+ conn.error(response)
86
+ end
87
+ end
88
+ end
89
+
90
+ class MockResponse
91
+ def initialize(body)
92
+ @body = body
93
+ end
94
+
95
+ def response
96
+ @body
97
+ end
98
+ alias :error :response
99
+ end
100
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe "SQSAttributes" do
4
+ describe ".parse" do
5
+ let(:attributes_obj) { SQSAttributes.parse(xml_fixture(:queue_attributes)) }
6
+
7
+ it "returns SQSAttributes objects" do
8
+ attributes_obj.should be_a_kind_of(SQSAttributes)
9
+ end
10
+
11
+ it "parses attributes" do
12
+ attributes_obj.approximate_number_of_messages.should == "0"
13
+ attributes_obj.approximate_number_of_messages_not_visible.should == "0"
14
+ attributes_obj.visibility_timeout.should == "30"
15
+ attributes_obj.create_timestamp.should == nil
16
+ attributes_obj.last_modified_timestamp.should == "1286771522"
17
+ attributes_obj.policy.should == nil
18
+ attributes_obj.maximum_message_size.should == "8192"
19
+ attributes_obj.message_retention_period.should == "345600"
20
+ attributes_obj.queue_arn.should == "arn:aws:sqs:us-east-1:123456789012:qfoo"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe "SQSMessage" do
4
+ describe ".parse" do
5
+ let(:messages) { SQSMessage.parse(xml_fixture(:receive_message)) }
6
+
7
+ it "returns SQSMessage objects" do
8
+ messages.length.should == 1
9
+ messages.first.should be_a_kind_of(SQSMessage)
10
+ end
11
+
12
+ it "parses attributes" do
13
+ message = messages.first
14
+ message.body.should == "This is a test message"
15
+ message.receipt_handle.should match /MbZj6wDWli.+?/im
16
+ message.md5_of_body.should == "\n fafb00f5732ab283681e124bf8747ed1\n "
17
+ message.message_id.should == "\n 5fea7756-0ea4-451a-a703-a558b933e274\n "
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ require 'sqs_message'
3
+
4
+ describe "SQSQueue" do
5
+ describe ".parse" do
6
+ let(:queues) { SQSQueue.parse(xml_fixture(:list_queues)) }
7
+
8
+ it "returns SQSQueue objects" do
9
+ queues.length.should == 1
10
+ queues.first.should be_a_kind_of(SQSQueue)
11
+ end
12
+
13
+ it "parses attributes" do
14
+ queue = queues.first
15
+ queue.queue_url.should == URI.parse("http://sqs.us-east-1.amazonaws.com/123456789012/testQueue")
16
+ end
17
+ end
18
+ end
data/spec/sqs_spec.rb ADDED
@@ -0,0 +1,152 @@
1
+ require 'spec_helper'
2
+ require 'sqs'
3
+
4
+ class MySQSClient
5
+ include SQS
6
+ def initialize
7
+ self.aws_key = 'adsf'
8
+ self.aws_secret = 'adsffasdf'
9
+ end
10
+ end
11
+
12
+ describe "SQS" do
13
+ let(:client) { MySQSClient.new }
14
+ let(:queue) { SQSQueue.new.tap { |q| q.queue_url = URI.parse("http://sqs.us-east-1.amazonaws.com/123456789012/testQueue") } }
15
+ let(:message) { SQSMessage.new.tap {|msg| msg.receipt_handle = "foo" } }
16
+
17
+ # we are testing private members because the
18
+ # interaction with Amazon is stubbed. Therefore
19
+ # we want to ensure that these perform as expected
20
+ # even though they would normally be encapsulated by
21
+ # calls to amazon.
22
+ #
23
+ # Leon and John 5-31-11
24
+ context "Private member testing" do
25
+
26
+ before(:all) do
27
+ MySQSClient.send :public, :sign_params
28
+ MySQSClient.send :public, :generate_signature
29
+ end
30
+
31
+ after(:all) do
32
+ MySQSClient.send :private, :sign_params
33
+ MySQSClient.send :private, :generate_signature
34
+ end
35
+
36
+ it "signs requests prior to sending" do
37
+ Timecop.freeze(Time.parse("2011-04-20T00:00:00")) do
38
+ client.sign_params("http://edgecase.com/mysevice", {}).should == "AWSAccessKeyId=adsf&Expires=2011-04-20T04%3A30%3A00Z&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2009-02-01&Signature=oKFwSahHQIMKiSOabVZqwcZEFowOdqyyj2gamyjJ3oU%3D"
39
+ end
40
+ end
41
+
42
+ it "generates valid signatures based on params" do
43
+ req_desc = ["GET", 'foo', '/', "foo=bar&baz=fellini"].join("\n")
44
+ client.generate_signature(req_desc).should == "WHmv1xv6iqPMw6kaw0sXVlqXfmoqkFpkKqBi2ONpAa4%3D"
45
+ end
46
+ end
47
+
48
+ context "calls Amazon Endpoints asynchronously to" do
49
+ it "list available queues" do
50
+ client.list_queues(
51
+ :callbacks => {
52
+ :success => lambda{|queues|
53
+ queues.length.should == 1
54
+ queues.first.queue_url.to_s.should == "http://sqs.us-east-1.amazonaws.com/123456789012/testQueue"
55
+ }
56
+ }
57
+ )
58
+ EM::HttpRequest.succeed(EM::MockResponse.new(xml_fixture(:list_queues)))
59
+ end
60
+
61
+ it "pull a message from the queue" do
62
+ queue.queue_url = URI.parse("http://sqs.us-east-1.amazonaws.com/123456789012/testQueue")
63
+ client.receive_message(
64
+ :queue => queue,
65
+ :callbacks => {
66
+ :success => lambda{|messages|
67
+ messages.kind_of?(Enumerable).should == true
68
+ messages.length.should == 1
69
+ messages.first.kind_of?(SQSMessage).should == true
70
+ }
71
+ }
72
+ )
73
+
74
+ EM::HttpRequest.succeed(EM::MockResponse.new(xml_fixture(:receive_message)))
75
+ end
76
+
77
+ it "delete a message from the queue" do
78
+ mock_obj = mock();
79
+ mock_obj.expects(:call).once
80
+ client.delete_message(
81
+ :queue => queue,
82
+ :message => message,
83
+ :callbacks => { :success => mock_obj }
84
+ )
85
+
86
+ EM::HttpRequest.succeed(EM::MockResponse.new(xml_fixture(:delete_message)))
87
+ end
88
+
89
+ it "gets the queue's attributes" do
90
+ client.get_queue_attributes(
91
+ :queue => queue,
92
+ :callbacks => {
93
+ :success => lambda{|attr_obj|
94
+ attr_obj.kind_of?(SQSAttributes).should == true
95
+ }
96
+ }
97
+ )
98
+
99
+ EM::HttpRequest.succeed(EM::MockResponse.new(xml_fixture(:queue_attributes)))
100
+ end
101
+ end
102
+ context "error result" do
103
+ let(:fail_mock) do
104
+ fail_mock = mock
105
+ fail_mock.expects(:call).once
106
+ fail_mock
107
+ end
108
+
109
+ let(:error_result) do
110
+ EM::MockResponse.new(xml_fixture(:error_response))
111
+ end
112
+
113
+ it "list_queues failure" do
114
+ client.list_queues(
115
+ :callbacks => {
116
+ :failure => fail_mock
117
+ }
118
+ )
119
+ EM::HttpRequest.succeed(error_result)
120
+ end
121
+
122
+ it "list_queues failure on misc http error not related to amazon" do
123
+ client.list_queues(
124
+ :callbacks => {
125
+ :failure => fail_mock
126
+ }
127
+ )
128
+ EM::HttpRequest.error(error_result)
129
+ end
130
+
131
+ it "receive_message failure" do
132
+ client.receive_message(
133
+ :queue => queue,
134
+ :callbacks => {
135
+ :failure => fail_mock
136
+ }
137
+ )
138
+ EM::HttpRequest.succeed(error_result)
139
+ end
140
+
141
+ it "delete_message failure" do
142
+ client.delete_message(
143
+ :queue => queue,
144
+ :message => message,
145
+ :callbacks => {
146
+ :failure => fail_mock
147
+ }
148
+ )
149
+ EM::HttpRequest.succeed(error_result)
150
+ end
151
+ end
152
+ end
metadata ADDED
@@ -0,0 +1,240 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sqs_async
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - EdgeCase <contact@edgecase.com>
14
+ - John Andrews <john@edgecase.com>
15
+ - Leon Gersing <leon@edgecase.com>
16
+ autorequire:
17
+ bindir: bin
18
+ cert_chain: []
19
+
20
+ date: 2011-05-31 00:00:00 -04:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ name: eventmachine
25
+ prerelease: false
26
+ requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ~>
30
+ - !ruby/object:Gem::Version
31
+ hash: 62196357
32
+ segments:
33
+ - 1
34
+ - 0
35
+ - 0
36
+ - beta
37
+ - 3
38
+ version: 1.0.0.beta.3
39
+ type: :runtime
40
+ version_requirements: *id001
41
+ - !ruby/object:Gem::Dependency
42
+ name: em-http-request
43
+ prerelease: false
44
+ requirement: &id002 !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ hash: 62196363
50
+ segments:
51
+ - 1
52
+ - 0
53
+ - 0
54
+ - beta
55
+ - 4
56
+ version: 1.0.0.beta.4
57
+ type: :runtime
58
+ version_requirements: *id002
59
+ - !ruby/object:Gem::Dependency
60
+ name: nokogiri
61
+ prerelease: false
62
+ requirement: &id003 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ hash: 3
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ type: :runtime
72
+ version_requirements: *id003
73
+ - !ruby/object:Gem::Dependency
74
+ name: json
75
+ prerelease: false
76
+ requirement: &id004 !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ hash: 3
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ type: :runtime
86
+ version_requirements: *id004
87
+ - !ruby/object:Gem::Dependency
88
+ name: ruby-hmac
89
+ prerelease: false
90
+ requirement: &id005 !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: 3
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ type: :runtime
100
+ version_requirements: *id005
101
+ - !ruby/object:Gem::Dependency
102
+ name: rspec
103
+ prerelease: false
104
+ requirement: &id006 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ hash: 23
110
+ segments:
111
+ - 2
112
+ - 6
113
+ - 0
114
+ version: 2.6.0
115
+ type: :development
116
+ version_requirements: *id006
117
+ - !ruby/object:Gem::Dependency
118
+ name: rspec-core
119
+ prerelease: false
120
+ requirement: &id007 !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ hash: 3
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ type: :development
130
+ version_requirements: *id007
131
+ - !ruby/object:Gem::Dependency
132
+ name: rspec-expectations
133
+ prerelease: false
134
+ requirement: &id008 !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ hash: 3
140
+ segments:
141
+ - 0
142
+ version: "0"
143
+ type: :development
144
+ version_requirements: *id008
145
+ - !ruby/object:Gem::Dependency
146
+ name: mocha
147
+ prerelease: false
148
+ requirement: &id009 !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ hash: 3
154
+ segments:
155
+ - 0
156
+ version: "0"
157
+ type: :development
158
+ version_requirements: *id009
159
+ - !ruby/object:Gem::Dependency
160
+ name: timecop
161
+ prerelease: false
162
+ requirement: &id010 !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ hash: 3
168
+ segments:
169
+ - 0
170
+ version: "0"
171
+ type: :development
172
+ version_requirements: *id010
173
+ description: A simple library that leverages Event Machine to issue requests to the Amazon SQS service while blocking as little as possible
174
+ email: contact@edgecase.com
175
+ executables: []
176
+
177
+ extensions: []
178
+
179
+ extra_rdoc_files: []
180
+
181
+ files:
182
+ - lib/sqs.rb
183
+ - lib/sqs_attributes.rb
184
+ - lib/sqs_message.rb
185
+ - lib/sqs_queue.rb
186
+ - spec/fixtures/delete_message.xml
187
+ - spec/fixtures/error_response.xml
188
+ - spec/fixtures/list_queues.xml
189
+ - spec/fixtures/queue_attributes.xml
190
+ - spec/fixtures/receive_message.xml
191
+ - spec/spec_helper.rb
192
+ - spec/sqs_attributes_spec.rb
193
+ - spec/sqs_message_spec.rb
194
+ - spec/sqs_queue_spec.rb
195
+ - spec/sqs_spec.rb
196
+ has_rdoc: true
197
+ homepage: https://github.com/edgecase/sqs_async
198
+ licenses: []
199
+
200
+ post_install_message:
201
+ rdoc_options: []
202
+
203
+ require_paths:
204
+ - lib
205
+ required_ruby_version: !ruby/object:Gem::Requirement
206
+ none: false
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ hash: 3
211
+ segments:
212
+ - 0
213
+ version: "0"
214
+ required_rubygems_version: !ruby/object:Gem::Requirement
215
+ none: false
216
+ requirements:
217
+ - - ">="
218
+ - !ruby/object:Gem::Version
219
+ hash: 3
220
+ segments:
221
+ - 0
222
+ version: "0"
223
+ requirements: []
224
+
225
+ rubyforge_project: sqs_async
226
+ rubygems_version: 1.5.0
227
+ signing_key:
228
+ specification_version: 3
229
+ summary: Non-Blocking SQS library.
230
+ test_files:
231
+ - spec/fixtures/delete_message.xml
232
+ - spec/fixtures/error_response.xml
233
+ - spec/fixtures/list_queues.xml
234
+ - spec/fixtures/queue_attributes.xml
235
+ - spec/fixtures/receive_message.xml
236
+ - spec/spec_helper.rb
237
+ - spec/sqs_attributes_spec.rb
238
+ - spec/sqs_message_spec.rb
239
+ - spec/sqs_queue_spec.rb
240
+ - spec/sqs_spec.rb