sqs_transport 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README +24 -0
- data/lib/sqs/config.rb +32 -0
- data/lib/sqs/message.rb +132 -0
- data/lib/sqs/message_size_error.rb +4 -0
- data/lib/sqs/queue.rb +17 -0
- data/lib/sqs/transport.rb +176 -0
- data/lib/sqs_transport.rb +9 -0
- data/test/mock_queue.rb +13 -0
- data/test/test_helper.rb +15 -0
- data/test/test_sqs_config.rb +57 -0
- data/test/test_sqs_message.rb +221 -0
- data/test/test_sqs_queue.rb +52 -0
- data/test/test_sqs_transport.rb +186 -0
- metadata +87 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Ben Koski
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
= sqs_transport
|
2
|
+
|
3
|
+
== OVERVIEW
|
4
|
+
|
5
|
+
sqs_transport is a wrapper around RightScale's excellent {RightAws::SqsGen2 library}[http://rightscale.rubyforge.org/right_aws_gem_doc/]
|
6
|
+
to facilitate simple queue and receive operations.
|
7
|
+
|
8
|
+
sqs_transport has four major components:
|
9
|
+
|
10
|
+
* SQS::Config, a class to hold AWS credentials. You'll need to define credential values for queueing to actually work.
|
11
|
+
* SQS::Queue, a class to easily create RightAws::SqsGen2 instances, given a queue name
|
12
|
+
* SQS::Message, a class allowing arbitrary contents (strings, hashes, arrays) to be queued and dequeued from SQS
|
13
|
+
* SQS::Transport, a mixin to quickly add <tt>queue!</tt>, <tt>dequeue!</tt>, and <tt>receive!</tt> methods to push class data through SQS.
|
14
|
+
|
15
|
+
See class docs for specific examples.
|
16
|
+
|
17
|
+
== LINKS
|
18
|
+
|
19
|
+
* Source code: http://github.com/bkoski/sqs_transport
|
20
|
+
* Documentation: http://sqs-transport.rubyforge.org
|
21
|
+
|
22
|
+
== AUTHOR
|
23
|
+
|
24
|
+
Ben Koski, http://github.com/bkoski, ben.koski (at) gmail.com
|
data/lib/sqs/config.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'facets'
|
2
|
+
|
3
|
+
|
4
|
+
module SQS
|
5
|
+
|
6
|
+
# SQS::Config stores your AWS access_key and secret_access_key. These attributes raise exceptions
|
7
|
+
# if they are checked but have not been set.
|
8
|
+
class Config
|
9
|
+
|
10
|
+
@@access_key = nil
|
11
|
+
@@secret_access_key = nil
|
12
|
+
|
13
|
+
cattr_writer :access_key, :secret_access_key
|
14
|
+
|
15
|
+
def self.access_key
|
16
|
+
raise ArgumentError, "No access key defined!" if @@access_key.nil?
|
17
|
+
return @@access_key
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.secret_access_key
|
21
|
+
raise ArgumentError, "No secret access key defined!" if @@secret_access_key.nil?
|
22
|
+
return @@secret_access_key
|
23
|
+
end
|
24
|
+
|
25
|
+
# Load configuration from a YAML::load-generated hash
|
26
|
+
def self.parse yaml_hash
|
27
|
+
self.access_key = yaml_hash['access_key'] unless yaml_hash['access_key'].nil? || yaml_hash['access_key'].empty?
|
28
|
+
self.secret_access_key = yaml_hash['secret_access_key'] unless yaml_hash['secret_access_key'].nil? || yaml_hash['secret_access_key'].empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/lib/sqs/message.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
module SQS
|
2
|
+
|
3
|
+
# SQS::Message provides a light wrapper over the RightAWS SQS API. It embeds the message payload
|
4
|
+
# in a JSON container to allow enqueue time and time_in_queue calculations.
|
5
|
+
#
|
6
|
+
# Note that by default, JSON serialization is used to encode <tt>contents</tt>. This means that
|
7
|
+
# <tt>contents</tt> must be JSON-serializable (i.e. no cyclical objects, singleton strings, etc.)
|
8
|
+
# If this is problematic, the serialization mechanism can be customized by overriding the <tt>serialize</tt>
|
9
|
+
# and <tt>self.deserialize</tt> methods.
|
10
|
+
#
|
11
|
+
# To use, simply instantiate, set the <tt>contents</tt> and call queue!
|
12
|
+
# For example:
|
13
|
+
#
|
14
|
+
# m = SQS::Message.new 'my_test_queue'
|
15
|
+
# m.contents = {:var1 => 1, :var2 => 2}
|
16
|
+
# m.queue!
|
17
|
+
#
|
18
|
+
# pushes a message containing {:var1 => 1, :var2 => 2} to the 'my_test_queue' queue on SQS
|
19
|
+
#
|
20
|
+
# To retrieve the message, simply call:
|
21
|
+
# m = SQS::Message.receive 'my_test_queue'
|
22
|
+
#
|
23
|
+
# You can then inspect the contents
|
24
|
+
# m.contents # returns {'var1' => 1, 'var2' => 2 }
|
25
|
+
# remove from the SQS queue
|
26
|
+
# m.dequeue!
|
27
|
+
# or check the time in queue
|
28
|
+
# m.time_in_queue
|
29
|
+
# You can also retrieve the SQS id for the message with the <tt>id</tt> method.
|
30
|
+
#
|
31
|
+
class Message
|
32
|
+
|
33
|
+
# The raw RightAws message retrieved from SQS
|
34
|
+
attr_accessor :raw_message
|
35
|
+
|
36
|
+
# Payload to be sent across the wire
|
37
|
+
attr_accessor :contents
|
38
|
+
|
39
|
+
attr_accessor :enqueued_at, :received_at, :queue_name
|
40
|
+
|
41
|
+
# Retrieves one or more Message objects from an SQS queue
|
42
|
+
# * <tt>queue_name</tt> is the name of the SQS queue
|
43
|
+
# * <tt>number_to_receive</tt> sets the maximum number of messages to return. If set to 1, a single instance is returned; if > 1 an array is returned. Defaults to 1.
|
44
|
+
#
|
45
|
+
# Valid options:
|
46
|
+
# * <tt>:visiblity</tt> - sets the visiblity timeout on the message in seconds
|
47
|
+
def self.receive queue_name, number_to_receive=1, opts={}
|
48
|
+
messages = SQS::Queue[queue_name].receive_messages(number_to_receive, opts[:visibility])
|
49
|
+
received_at = Time.now.utc
|
50
|
+
messages.map! { |m| self.create_from_raw_message(queue_name, m, received_at) }
|
51
|
+
|
52
|
+
number_to_receive == 1 ? messages.first : messages
|
53
|
+
end
|
54
|
+
|
55
|
+
# Retrives one or more messages from the queue, but sets their visiblity to zero so that
|
56
|
+
# they can immediately be picked up by another worker. Useful for previewing messages on the queue.
|
57
|
+
# * <tt>queue_name</tt> is the name of the SQS queue
|
58
|
+
# * <tt>number_to_view</tt> sets the maximum number of messages to return. If set to 1, a single instance is returned; if > 1 an array is returned. Defaults to 1.
|
59
|
+
# No options at this time.
|
60
|
+
def self.peek queue_name, number_to_view=1, opts={}
|
61
|
+
self.receive(queue_name, number_to_view, :visibility => 0)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Initialize with the name of the name of the SQS queue. When queue! is called on an instance,
|
65
|
+
# data will be pushed to this queue.
|
66
|
+
def initialize new_queue_name
|
67
|
+
@queue_name = new_queue_name
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns the SQS id for this message; nil if the message has not yet been queued.
|
71
|
+
def id
|
72
|
+
raw_message ? raw_message.id : nil
|
73
|
+
end
|
74
|
+
|
75
|
+
# Serializes <tt>contents</tt> and pushes data onto the SQS queue.
|
76
|
+
def queue!
|
77
|
+
@enqueued_at = Time.now.utc
|
78
|
+
raise SQS::MessageSizeError, "Message exceeds 8k limit by #{sqs_message_body.size - 8_000} bytes" if sqs_message_body.size > 8_000
|
79
|
+
raw_message = SQS::Queue[queue_name].push(sqs_message_body)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Call after retrieving to delete the message from SQS so that it cannot be retrieved by another client.
|
83
|
+
def dequeue!
|
84
|
+
raw_message.delete
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns time message spent on queue in seconds.
|
88
|
+
# Raises an ArgumentError if called on a message that has not been dequeued.
|
89
|
+
def time_in_queue
|
90
|
+
raise ArgumentError, "This message has not been dequeued properly; either enqueued_at or received_at is nil" if enqueued_at.nil? || received_at.nil?
|
91
|
+
enqueued_at - received_at
|
92
|
+
end
|
93
|
+
|
94
|
+
# Given an object, serialize it to a string. By default, this simply calls to_json
|
95
|
+
# on the object, but could be overriden to serialize using YAML or Marshal.dump.
|
96
|
+
def serialize object
|
97
|
+
object.to_json
|
98
|
+
end
|
99
|
+
|
100
|
+
# Given a string, deserialize an object. By default this calls JSON.parse
|
101
|
+
# but could be overriden to use another deserialization method.
|
102
|
+
def self.deserialize str
|
103
|
+
str.nil? ? nil : JSON.parse(str)
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
# Build the message to send to SQS
|
108
|
+
def sqs_message_body
|
109
|
+
{:contents => self.serialize(contents), :enqueued_at => enqueued_at}.to_json
|
110
|
+
end
|
111
|
+
|
112
|
+
# Create a SQSMessage instance from its compnent parts
|
113
|
+
def self.create_from_raw_message queue_name, raw_message, received_at
|
114
|
+
message = self.new(queue_name)
|
115
|
+
data = self.parse_sqs_message_body(raw_message.body)
|
116
|
+
|
117
|
+
message.contents = data['contents']
|
118
|
+
message.raw_message = raw_message
|
119
|
+
message.enqueued_at = data['enqueued_at']
|
120
|
+
message.received_at = received_at
|
121
|
+
|
122
|
+
return message
|
123
|
+
end
|
124
|
+
|
125
|
+
# Parse a RightAws SQS message body to the :contents, :enqueued_at hash needed to create a new message
|
126
|
+
def self.parse_sqs_message_body message_string
|
127
|
+
message = message_string.blank? ? {} : JSON.parse(message_string)
|
128
|
+
message['contents'] = self.deserialize(message['contents'])
|
129
|
+
return message
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/lib/sqs/queue.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module SQS
|
2
|
+
|
3
|
+
# Call SQS::Queue['queue_name'] to retrieve a RightAws::SqsGen2 queue instance
|
4
|
+
module Queue
|
5
|
+
|
6
|
+
def self.[] queue_name
|
7
|
+
@sqs ||= RightAws::SqsGen2.new(SQS::Config.access_key, SQS::Config.secret_access_key, :logger => self.logger)
|
8
|
+
@sqs.queue(queue_name, true)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.logger
|
12
|
+
logger = Logger.new(STDOUT)
|
13
|
+
logger.level = Logger::FATAL
|
14
|
+
return logger
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
module SQS
|
2
|
+
|
3
|
+
# Include the SQS::Transport mixin in a class to add SQS enqueue and dequeue capabilities.
|
4
|
+
#
|
5
|
+
# After including, call <tt>set_queue_name</tt> to specify which SQS queue will receive messages.
|
6
|
+
#
|
7
|
+
# There are two ways to define the data that will be included in queued messages:
|
8
|
+
# * call <tt>include_in_sqs_message</tt> with an array of attributes to include
|
9
|
+
# * implement <tt>to_sqs_message</tt> and return an :attr => value hash
|
10
|
+
#
|
11
|
+
# <tt>validate_message</tt> can be implemented to validate message data before it is pushed to SQS.
|
12
|
+
# If this method raises an exception, the message will not be queued.
|
13
|
+
#
|
14
|
+
# As an example:
|
15
|
+
#
|
16
|
+
# class MyMessage
|
17
|
+
# include SQS::Transport
|
18
|
+
#
|
19
|
+
# set_queue_name :widgets
|
20
|
+
#
|
21
|
+
# attr_accessor :color, :size
|
22
|
+
# include_in_sqs_message :color, :size
|
23
|
+
#
|
24
|
+
# def validate_message
|
25
|
+
# raise "Must have both size and color" if color.nil? || size.nil?
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# creates a class that would then allow:
|
31
|
+
#
|
32
|
+
# message = MyMessage.new
|
33
|
+
# message.color = 'red'
|
34
|
+
# message.size = 'xtrasmall'
|
35
|
+
# message.queue!
|
36
|
+
#
|
37
|
+
# at which point a :size => trasmall, :color => red message would be pushed onto the "widgets" SQS queue
|
38
|
+
#
|
39
|
+
# A client using the same class could then call:
|
40
|
+
#
|
41
|
+
# incoming = MyMessage.receive
|
42
|
+
# puts incoming.color # "red"
|
43
|
+
# puts incoming.size # "xtrasmall"
|
44
|
+
# incoming.dequeue! # message is removed from SQS queue
|
45
|
+
#
|
46
|
+
# Note that by default JSON serializtion is used, so some type semanitics are not preseved.
|
47
|
+
# For example, if you set <tt>incoming.color</tt> to <tt>{:shade => :red}</tt> the data would be received as a string (<tt>{'shade' => 'red'}</tt>)
|
48
|
+
# The serialization method is customizable by overriding <tt>serialize</tt> on SQS::Message.
|
49
|
+
#
|
50
|
+
# SQS::Transport stamps the enqueue and dequeue times, which can be used to calculate time in queue
|
51
|
+
#
|
52
|
+
# puts incoming.enqueued_at # Mon Jul 06 22:16:15 UTC 2009
|
53
|
+
# puts incoming.dequeued_at # Mon Jul 06 22:16:25 UTC 2009
|
54
|
+
# puts incoming.time_in_queue # 10
|
55
|
+
#
|
56
|
+
# In addition, the class includes a <tt>peek</tt> method that can be used to inspect queued messages without removing them from the queue.
|
57
|
+
#
|
58
|
+
module Transport
|
59
|
+
|
60
|
+
def self.included(base) # :nodoc:
|
61
|
+
base.extend ClassMethods
|
62
|
+
end
|
63
|
+
|
64
|
+
module ClassMethods
|
65
|
+
|
66
|
+
# Defines associated SQS queue
|
67
|
+
def set_queue_name name
|
68
|
+
@sqs_queue_name = name.to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns name of associated SQS Queue; raises exception if name has not yet been defined
|
72
|
+
def sqs_queue_name
|
73
|
+
raise "undefined queue name!" if @sqs_queue_name.nil?
|
74
|
+
@sqs_queue_name
|
75
|
+
end
|
76
|
+
|
77
|
+
# Defines the attributes to be included in the message sent to SQS. Not necessary if <tt>to_sqs_message</tt> is overridden.
|
78
|
+
def include_in_sqs_message *attrs_to_include
|
79
|
+
@attrs_for_sqs_message = attrs_to_include
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns the list of attrs to be sent to SQS; raises an exception if attrs have not yet been defined.
|
83
|
+
def attrs_for_sqs_message
|
84
|
+
raise "Message requires at least one attribute. Call include_in_sqs_message to define which attributes are included in SQS message" if @attrs_for_sqs_message.nil? || @attrs_for_sqs_message.empty?
|
85
|
+
@attrs_for_sqs_message
|
86
|
+
end
|
87
|
+
|
88
|
+
# Pops one or more messages off the SQS queue, parses the contents, and returns them as instances of the class.
|
89
|
+
# * <tt>number_to_recieve</tt> is optional. If not passed, a single message will be returned. If number_to_receive == 1, a single instance will be returned; otherwise an array will be returned.
|
90
|
+
#
|
91
|
+
# Valid options:
|
92
|
+
# * <tt>:visiblity</tt> - sets the visiblity timeout on the message in seconds
|
93
|
+
def receive number_to_receive=1, opts={}
|
94
|
+
result = SQS::Message.receive(self.sqs_queue_name, number_to_receive, opts)
|
95
|
+
|
96
|
+
if number_to_receive == 1
|
97
|
+
reconstitute_instance(result)
|
98
|
+
else
|
99
|
+
result.map {|m| reconstitute_instance(m)}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def reconstitute_instance sqs_message
|
104
|
+
new_instance = self.new
|
105
|
+
sqs_message.contents.each { |field, value| new_instance.send("#{field}=", value) }
|
106
|
+
new_instance.sqs_message = sqs_message
|
107
|
+
return new_instance
|
108
|
+
end
|
109
|
+
|
110
|
+
# Retrives one or more messages from the queue, but sets their visiblity to zero so that
|
111
|
+
# they can immediately be picked up by another worker. Useful for previewing messages on the queue.
|
112
|
+
# * <tt>queue_name</tt> is the name of the SQS queue
|
113
|
+
# * <tt>number_to_view</tt> sets the maximum number of messages to return. If set to 1, a single instance is returned; if > 1 an array is returned. Defaults to 1.
|
114
|
+
# No options at this time.
|
115
|
+
def peek number_to_view=1, opts={}
|
116
|
+
self.receive(number_to_view, opts.merge(:visibility => 0))
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
attr_writer :sqs_message
|
122
|
+
|
123
|
+
# Returns a hash that will be serialized and sent to SQS. By default, returns a <tt>{'attr' => 'value'}</tt>
|
124
|
+
# hash containing all attributes defined by the <tt>include_in_sqs_message</tt> call.
|
125
|
+
#
|
126
|
+
# Override this to return a custom {'attr' => 'value'} hash for more control over serialization.
|
127
|
+
def to_sqs_message
|
128
|
+
Hash[*self.class.attrs_for_sqs_message.collect {|a| [a, self.send(a)]}.flatten]
|
129
|
+
end
|
130
|
+
|
131
|
+
# Implement <tt>validate_message</tt> to check message data before it is sent to SQS.
|
132
|
+
# If this method raises an exception, message will not be queued.
|
133
|
+
def validate_message
|
134
|
+
end
|
135
|
+
|
136
|
+
# Validates the message, then pushes it onto the associated queue.
|
137
|
+
# If validation raises an exception, the message will not be queued and the exception will bubble up.
|
138
|
+
def queue!
|
139
|
+
validate_message
|
140
|
+
sqs_message.contents = to_sqs_message
|
141
|
+
sqs_message.queue!
|
142
|
+
end
|
143
|
+
|
144
|
+
# Removes a retrieved instance from the SQS queue.
|
145
|
+
def dequeue!
|
146
|
+
sqs_message.dequeue!
|
147
|
+
end
|
148
|
+
|
149
|
+
# Returns the associated SQS::Message instance
|
150
|
+
def sqs_message
|
151
|
+
@sqs_message ||= SQS::Message.new(self.class.sqs_queue_name)
|
152
|
+
return @sqs_message
|
153
|
+
end
|
154
|
+
|
155
|
+
# Returns the Amazon id for the SQS message.
|
156
|
+
def sqs_message_id
|
157
|
+
sqs_message.id
|
158
|
+
end
|
159
|
+
|
160
|
+
# Returns the time the message was queued
|
161
|
+
def enqueued_at
|
162
|
+
sqs_message.enqueued_at
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns the time the message was dequeued
|
166
|
+
def dequeued_at
|
167
|
+
sqs_message.dequeued_at
|
168
|
+
end
|
169
|
+
|
170
|
+
# Returns the amount of time a message spent in the queue, in seconds.
|
171
|
+
def time_in_queue
|
172
|
+
sqs_message.time_in_queue
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'json/add/core'
|
3
|
+
require 'right_aws'
|
4
|
+
|
5
|
+
require File.join(File.dirname(__FILE__), 'sqs/config')
|
6
|
+
require File.join(File.dirname(__FILE__), 'sqs/queue')
|
7
|
+
require File.join(File.dirname(__FILE__), 'sqs/message_size_error')
|
8
|
+
require File.join(File.dirname(__FILE__), 'sqs/message')
|
9
|
+
require File.join(File.dirname(__FILE__), 'sqs/transport')
|
data/test/mock_queue.rb
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'mocha'
|
5
|
+
require 'time_warp' # on github as 'iridesco-time-warp'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
require 'sqs_transport'
|
9
|
+
require 'mock_queue'
|
10
|
+
|
11
|
+
SQS::Config.access_key = 'test1234'
|
12
|
+
SQS::Config.secret_access_key = 'ASDF KEY'
|
13
|
+
|
14
|
+
class Test::Unit::TestCase
|
15
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class TestSQSConfig < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "defaults" do
|
6
|
+
setup do
|
7
|
+
SQS::Config.access_key = nil
|
8
|
+
SQS::Config.secret_access_key = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
should "raise an ArgumentError if access_key is undefined" do
|
13
|
+
assert_raises(ArgumentError) { SQS::Config.access_key }
|
14
|
+
end
|
15
|
+
|
16
|
+
should "raise an ArgumentError if secret_access_key is undefined" do
|
17
|
+
assert_raises(ArgumentError) { SQS::Config.secret_access_key }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "setters" do
|
22
|
+
should "return value for access_key if defined" do
|
23
|
+
SQS::Config.access_key = 'TeSt'
|
24
|
+
assert_equal 'TeSt', SQS::Config.access_key
|
25
|
+
end
|
26
|
+
|
27
|
+
should "return value for secret_access_key if defined" do
|
28
|
+
SQS::Config.secret_access_key = 'TeStSecr3t'
|
29
|
+
assert_equal 'TeStSecr3t', SQS::Config.secret_access_key
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "parse" do
|
34
|
+
should "set access_key if provided" do
|
35
|
+
SQS::Config.parse({'access_key' => '1234'})
|
36
|
+
assert_equal '1234', SQS::Config.access_key
|
37
|
+
end
|
38
|
+
|
39
|
+
should "not set access_key if provided as blank string" do
|
40
|
+
SQS::Config.parse({'access_key' => '1234'})
|
41
|
+
SQS::Config.parse({'access_key' => ''})
|
42
|
+
assert_equal '1234', SQS::Config.access_key
|
43
|
+
end
|
44
|
+
|
45
|
+
should "set secret_access_key if provided" do
|
46
|
+
SQS::Config.parse({'secret_access_key' => '1234ABC'})
|
47
|
+
assert_equal '1234ABC', SQS::Config.secret_access_key
|
48
|
+
end
|
49
|
+
|
50
|
+
should "not set secret_access_key if provided as blank string" do
|
51
|
+
SQS::Config.parse({'secret_access_key' => '1234ABC'})
|
52
|
+
SQS::Config.parse({'secret_access_key' => ''})
|
53
|
+
assert_equal '1234ABC', SQS::Config.secret_access_key
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class SQS::Message
|
4
|
+
public :sqs_message_body
|
5
|
+
end
|
6
|
+
|
7
|
+
class TestSQSMessage < Test::Unit::TestCase
|
8
|
+
|
9
|
+
context "self.receive" do
|
10
|
+
setup do
|
11
|
+
@mock_queue = MockQueue.new
|
12
|
+
SQS::Queue.stubs(:[]).with('test_queue').returns(@mock_queue)
|
13
|
+
end
|
14
|
+
|
15
|
+
should "call sqs_queue.recieve_messages for the specified number of messages" do
|
16
|
+
@mock_queue.expects(:receive_messages).with(7, anything).returns([])
|
17
|
+
SQS::Message.receive('test_queue', 7)
|
18
|
+
end
|
19
|
+
|
20
|
+
should "call sqs_queue.receive for a single message if no message count is specified" do
|
21
|
+
@mock_queue.expects(:receive_messages).with(1, anything).returns([])
|
22
|
+
SQS::Message.receive('test_queue')
|
23
|
+
end
|
24
|
+
|
25
|
+
should "call sqs_queue.receive with visibility specified as :visibility in options" do
|
26
|
+
@mock_queue.expects(:receive_messages).with(anything, 23).returns([])
|
27
|
+
SQS::Message.receive('test_queue', 1, :visibility => 23)
|
28
|
+
end
|
29
|
+
|
30
|
+
should "call sqs_queue.receive with nil visiblity if :visiblity not provided in options" do
|
31
|
+
@mock_queue.expects(:receive_messages).with(anything, nil).returns([])
|
32
|
+
SQS::Message.receive('test_queue', 1)
|
33
|
+
end
|
34
|
+
|
35
|
+
should "return a single instance of class if a single message is requested" do
|
36
|
+
@mock_queue.stubs(:receive_messages).returns([mock_message])
|
37
|
+
assert_kind_of SQS::Message, SQS::Message.receive('test_queue', 1)
|
38
|
+
end
|
39
|
+
|
40
|
+
should "return an array of objects if multiple messages are requested" do
|
41
|
+
message_array = [mock_message, mock_message, mock_message]
|
42
|
+
@mock_queue.stubs(:receive_messages).returns(message_array)
|
43
|
+
assert_equal message_array, SQS::Message.receive('test_queue', 7)
|
44
|
+
end
|
45
|
+
|
46
|
+
should "return an array of objects if multiple messages are requested, even if there is only a single message in the queue" do
|
47
|
+
message_array = [mock_message]
|
48
|
+
@mock_queue.stubs(:receive_messages).returns(message_array)
|
49
|
+
assert_equal message_array, SQS::Message.receive('test_queue', 7)
|
50
|
+
end
|
51
|
+
|
52
|
+
should "set received_at on returned messages to the time dequeue! was invoked" do
|
53
|
+
message_array = [mock_message]
|
54
|
+
@mock_queue.stubs(:receive_messages).returns(message_array)
|
55
|
+
|
56
|
+
expected_received_at = Time.now.utc - 5_000
|
57
|
+
received_message = nil
|
58
|
+
|
59
|
+
pretend_now_is(expected_received_at) do
|
60
|
+
received_message = SQS::Message.receive('test_queue')
|
61
|
+
end
|
62
|
+
|
63
|
+
assert_in_delta expected_received_at, received_message.received_at, 0.5
|
64
|
+
end
|
65
|
+
|
66
|
+
should "stamp a consistent received_at across all messages returned" do
|
67
|
+
message_array = [mock_message, mock_message, mock_message]
|
68
|
+
@mock_queue.stubs(:receive_messages).returns(message_array)
|
69
|
+
|
70
|
+
messages = SQS::Message.receive('test_queue', 3)
|
71
|
+
|
72
|
+
assert_equal 1, messages.collect { |m| m.received_at }.uniq.length
|
73
|
+
end
|
74
|
+
|
75
|
+
should "assign the enqueued_at time on returned message" do
|
76
|
+
expected_message = SQS::Message.new 'test_queue'
|
77
|
+
expected_message.contents = {:value_1 => 1}
|
78
|
+
|
79
|
+
@mock_queue.stubs(:receive_messages).returns([mock_message(expected_message.sqs_message_body)])
|
80
|
+
|
81
|
+
message = SQS::Message.receive('test_queue')
|
82
|
+
assert_equal expected_message.enqueued_at, message.enqueued_at
|
83
|
+
end
|
84
|
+
|
85
|
+
should "assign the contents on returned message" do
|
86
|
+
expected_message = SQS::Message.new 'test_queue'
|
87
|
+
expected_message.contents = {'value_1' => 1}
|
88
|
+
|
89
|
+
@mock_queue.stubs(:receive_messages).returns([mock_message(expected_message.sqs_message_body)])
|
90
|
+
|
91
|
+
message = SQS::Message.receive('test_queue')
|
92
|
+
assert_equal expected_message.contents, message.contents
|
93
|
+
end
|
94
|
+
|
95
|
+
should "assign the raw message returned from SQS to raw_message" do
|
96
|
+
expected_message = mock()
|
97
|
+
expected_message.stubs(:body)
|
98
|
+
@mock_queue.stubs(:receive_messages).returns([expected_message])
|
99
|
+
message = SQS::Message.receive('test_queue')
|
100
|
+
assert_equal expected_message.object_id, message.raw_message.object_id
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "self.peek" do
|
105
|
+
should "receive number_to_view with :visibility => 0" do
|
106
|
+
SQS::Message.expects(:receive).with('test_queue', 10, :visibility => 0)
|
107
|
+
SQS::Message.peek('test_queue', 10)
|
108
|
+
end
|
109
|
+
|
110
|
+
should "receive 1 message with :visiblity => 0 if number_to_view not specified" do
|
111
|
+
SQS::Message.expects(:receive).with('test_queue', 1, :visibility => 0)
|
112
|
+
SQS::Message.peek('test_queue')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "queue!" do
|
117
|
+
setup do
|
118
|
+
@expected_contents = {:value_1 => 1, :value_2 => 2}
|
119
|
+
@mock_queue = MockQueue.new
|
120
|
+
SQS::Queue.stubs(:[]).with('test_queue').returns(@mock_queue)
|
121
|
+
@test_instance = SQS::Message.new 'test_queue'
|
122
|
+
end
|
123
|
+
|
124
|
+
should "push a JSON message containing :content => serialized_content onto queue specified in init" do
|
125
|
+
@test_instance.contents = @expected_contents
|
126
|
+
@test_instance.queue!
|
127
|
+
|
128
|
+
assert_equal @test_instance.serialize(@expected_contents), JSON.parse(@mock_queue.messages.first)['contents']
|
129
|
+
end
|
130
|
+
|
131
|
+
should "push a JSON message containing :enqueue_time => Time.now.utc onto queue specified in init" do
|
132
|
+
enqueue_time = Time.now
|
133
|
+
|
134
|
+
@test_instance.contents = {:value_1 => 1}
|
135
|
+
pretend_now_is(enqueue_time) do
|
136
|
+
@test_instance.queue!
|
137
|
+
end
|
138
|
+
|
139
|
+
assert_equal enqueue_time.to_i, JSON.parse(@mock_queue.messages.first)['enqueued_at'].to_i
|
140
|
+
end
|
141
|
+
|
142
|
+
should "raise a SQS::MessageSizeError if message contents are too big" do
|
143
|
+
@test_instance.stubs(:sqs_message_body).returns('a' * 10_000)
|
144
|
+
assert_raises(SQS::MessageSizeError) { @test_instance.queue! }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "dequeue!" do
|
149
|
+
should "call delete on the raw message" do
|
150
|
+
raw_message = mock()
|
151
|
+
raw_message.expects(:delete)
|
152
|
+
|
153
|
+
instance = SQS::Message.new 'test_queue'
|
154
|
+
instance.stubs(:raw_message).returns(raw_message)
|
155
|
+
instance.dequeue!
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context "id" do
|
160
|
+
should "return the id from raw_message if it is set" do
|
161
|
+
expected_id = 'ASDF-1234'
|
162
|
+
raw_message = mock()
|
163
|
+
raw_message.stubs(:id).returns(expected_id)
|
164
|
+
|
165
|
+
instance = SQS::Message.new 'test_queue'
|
166
|
+
instance.stubs(:raw_message).returns(raw_message)
|
167
|
+
|
168
|
+
assert_equal expected_id, instance.id
|
169
|
+
end
|
170
|
+
|
171
|
+
should "return nil if raw_message is not set" do
|
172
|
+
instance = SQS::Message.new 'test_queue'
|
173
|
+
instance.stubs(:raw_message).returns(nil)
|
174
|
+
assert_nil instance.id
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context "queue_name" do
|
179
|
+
should "return the queue name specified at init time" do
|
180
|
+
expected_name = 'test_queue'
|
181
|
+
instance = SQS::Message.new expected_name
|
182
|
+
assert_equal expected_name, instance.queue_name
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context "time_in_queue" do
|
187
|
+
should "raise an ArgumentError if enqueued_at is nil" do
|
188
|
+
instance = SQS::Message.new 'test_queue'
|
189
|
+
instance.stubs(:enqueued_at).returns(nil)
|
190
|
+
instance.stubs(:received_at).returns(DateTime.now)
|
191
|
+
assert_raises(ArgumentError) { instance.time_in_queue }
|
192
|
+
end
|
193
|
+
|
194
|
+
should "raise an ArgumentError if received_at is nil" do
|
195
|
+
instance = SQS::Message.new 'test_queue'
|
196
|
+
instance.stubs(:enqueued_at).returns(nil)
|
197
|
+
instance.stubs(:received_at).returns(DateTime.now)
|
198
|
+
assert_raises(ArgumentError) { instance.time_in_queue }
|
199
|
+
end
|
200
|
+
|
201
|
+
should "return received_at - enqueued_at" do
|
202
|
+
instance = SQS::Message.new 'test_queue'
|
203
|
+
|
204
|
+
expected_received_at = DateTime.now
|
205
|
+
expected_enqueued_at = expected_received_at - 200
|
206
|
+
|
207
|
+
instance.stubs(:enqueued_at).returns(expected_enqueued_at)
|
208
|
+
instance.stubs(:received_at).returns(expected_received_at)
|
209
|
+
assert_equal expected_enqueued_at - expected_received_at, instance.time_in_queue
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
private
|
214
|
+
def mock_message mock_body=nil
|
215
|
+
message = mock()
|
216
|
+
message.stubs(:body).returns(mock_body)
|
217
|
+
|
218
|
+
return message
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Queue caches its RightAws instance; this needs to be busted between tests
|
4
|
+
module SQS
|
5
|
+
module Queue
|
6
|
+
def self.flush_cache
|
7
|
+
@sqs = nil
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class TestSQSQueue < Test::Unit::TestCase
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@mock_right_aws = mock()
|
16
|
+
@mock_right_aws.stubs(:queue)
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
SQS::Queue.flush_cache
|
21
|
+
end
|
22
|
+
|
23
|
+
should "instantiate a new RightAws::SQSGen2 using the access key from the SQS::Config" do
|
24
|
+
SQS::Config.access_key = 'ASDF'
|
25
|
+
RightAws::SqsGen2.expects(:new).with(SQS::Config.access_key, anything, anything).returns(@mock_right_aws)
|
26
|
+
SQS::Queue['test_queue']
|
27
|
+
end
|
28
|
+
|
29
|
+
should "instantiate a new RightAws::SQSGen2 using the secret access key from the SQS::Config" do
|
30
|
+
SQS::Config.secret_access_key = 'ASDF123'
|
31
|
+
RightAws::SqsGen2.expects(:new).with(anything, SQS::Config.secret_access_key, anything).returns(@mock_right_aws)
|
32
|
+
SQS::Queue['test_queue']
|
33
|
+
end
|
34
|
+
|
35
|
+
should "make a find/create call for the specified queue" do
|
36
|
+
SQS::Config.secret_access_key = 'ASDF123'
|
37
|
+
RightAws::SqsGen2.stubs(:new).returns(@mock_right_aws)
|
38
|
+
@mock_right_aws.expects(:queue).with('test_queue', true)
|
39
|
+
SQS::Queue['test_queue']
|
40
|
+
end
|
41
|
+
|
42
|
+
should "return a queue object" do
|
43
|
+
SQS::Config.secret_access_key = 'ASDF123'
|
44
|
+
RightAws::SqsGen2.stubs(:new).returns(@mock_right_aws)
|
45
|
+
|
46
|
+
mock_queue = mock()
|
47
|
+
@mock_right_aws.stubs(:queue).returns(mock_queue)
|
48
|
+
|
49
|
+
assert_equal mock_queue.object_id, SQS::Queue['test_queue'].object_id
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class TestTransport
|
4
|
+
include SQS::Transport
|
5
|
+
|
6
|
+
attr_reader :source_message # allow source to be read for testing
|
7
|
+
attr_accessor :value1, :value2
|
8
|
+
include_in_sqs_message :value1, :value2
|
9
|
+
|
10
|
+
set_queue_name 'testQ'
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestTransportNoQueue
|
14
|
+
include SQS::Transport
|
15
|
+
|
16
|
+
attr_accessor :value1
|
17
|
+
end
|
18
|
+
|
19
|
+
class TestTransportSymbolQueue
|
20
|
+
include SQS::Transport
|
21
|
+
set_queue_name :testQueue2
|
22
|
+
|
23
|
+
attr_accessor :value1
|
24
|
+
include_in_sqs_message :value1
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
class TestSQSTransport < Test::Unit::TestCase
|
29
|
+
|
30
|
+
context "self.sqs_queue_name" do
|
31
|
+
should "raise an exception if set_queue_name has not been called" do
|
32
|
+
assert_raises(RuntimeError) { TestTransportNoQueue.sqs_queue_name }
|
33
|
+
end
|
34
|
+
|
35
|
+
should "return value set using set_queue_name" do
|
36
|
+
assert_equal 'testQ', TestTransport.sqs_queue_name
|
37
|
+
end
|
38
|
+
|
39
|
+
should "return string, even if set_queue_name awas called with symbol" do
|
40
|
+
assert_equal 'testQueue2', TestTransportSymbolQueue.sqs_queue_name
|
41
|
+
assert_kind_of String, TestTransportSymbolQueue.sqs_queue_name
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "self.attrs_for_sqs_message" do
|
46
|
+
should "raise an exception if include_in_sqs_message has not been called" do
|
47
|
+
assert_raises(RuntimeError) { TestTransportNoQueue.attrs_for_sqs_message }
|
48
|
+
end
|
49
|
+
|
50
|
+
should "return value set using include_in_sqs_message" do
|
51
|
+
assert_equal [:value1, :value2], TestTransport.attrs_for_sqs_message
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "self.receive" do
|
56
|
+
should "proxy request to SQS::Message.receive" do
|
57
|
+
SQS::Message.expects(:receive).with(TestTransport.sqs_queue_name, 5, :visibility => 10).returns([])
|
58
|
+
TestTransport.receive(5, :visibility => 10)
|
59
|
+
end
|
60
|
+
|
61
|
+
should "return reconstituted instance of original if number_to_receive = 1" do
|
62
|
+
original = TestTransport.new
|
63
|
+
original.value1 = 'test'
|
64
|
+
original.value2 = 10
|
65
|
+
|
66
|
+
SQS::Message.any_instance.stubs(:queue!)
|
67
|
+
original.queue!
|
68
|
+
SQS::Message.stubs(:receive).returns(original.sqs_message)
|
69
|
+
|
70
|
+
new_instance = TestTransport.receive
|
71
|
+
assert_equal original.value1, new_instance.value1
|
72
|
+
assert_equal original.value2, new_instance.value2
|
73
|
+
end
|
74
|
+
|
75
|
+
should "set the new instance's sqs_message = received message" do
|
76
|
+
original = TestTransport.new
|
77
|
+
original.value1 = 'test'
|
78
|
+
original.value2 = 10
|
79
|
+
|
80
|
+
SQS::Message.any_instance.stubs(:queue!)
|
81
|
+
original.queue!
|
82
|
+
SQS::Message.stubs(:receive).returns(original.sqs_message)
|
83
|
+
|
84
|
+
new_instance = TestTransport.receive
|
85
|
+
assert_equal original.sqs_message, new_instance.sqs_message
|
86
|
+
end
|
87
|
+
|
88
|
+
should "return array of reconstituted originals if number_to_receive > 1" do
|
89
|
+
originals = []
|
90
|
+
|
91
|
+
original1 = TestTransport.new
|
92
|
+
original1.value1 = 'test'
|
93
|
+
original1.value2 = 10
|
94
|
+
originals << original1
|
95
|
+
|
96
|
+
original2 = TestTransport.new
|
97
|
+
original2.value1 = 'test2'
|
98
|
+
original2.value2 = 20
|
99
|
+
originals << original2
|
100
|
+
|
101
|
+
SQS::Message.any_instance.stubs(:queue!)
|
102
|
+
originals.each {|o| o.queue!}
|
103
|
+
SQS::Message.stubs(:receive).returns(originals.collect {|o| o.sqs_message})
|
104
|
+
|
105
|
+
instances = TestTransport.receive(3)
|
106
|
+
instances.each_with_index do |actual, i|
|
107
|
+
assert_equal originals[i].value1, actual.value1
|
108
|
+
assert_equal originals[i].value2, actual.value2
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "self.peek" do
|
114
|
+
should "call self.receive with :visibility => 0" do
|
115
|
+
TestTransport.expects(:receive).with(5, :visibility => 0)
|
116
|
+
TestTransport.peek(5)
|
117
|
+
end
|
118
|
+
|
119
|
+
should "receive a single instance by default" do
|
120
|
+
TestTransport.expects(:receive).with(1, :visibility => 0)
|
121
|
+
TestTransport.peek
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "queue!" do
|
126
|
+
setup do
|
127
|
+
@test_instance = TestTransport.new
|
128
|
+
@test_instance.value1 = 'test1'
|
129
|
+
@test_instance.value2 = 'test2'
|
130
|
+
SQS::Message.any_instance.stubs(:queue!)
|
131
|
+
end
|
132
|
+
|
133
|
+
should "call validate_message" do
|
134
|
+
@test_instance.expects(:validate_message)
|
135
|
+
@test_instance.queue!
|
136
|
+
end
|
137
|
+
|
138
|
+
should "not call sqs_message.queue! if validate message throws exception" do
|
139
|
+
@test_instance.stubs(:validate_message).raises(RuntimeError)
|
140
|
+
SQS::Message.any_instance.expects(:queue!).never
|
141
|
+
begin
|
142
|
+
@test_instance.queue!
|
143
|
+
rescue
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
should "set sqs_message.contents = to_sqs_message" do
|
148
|
+
@test_instance.queue!
|
149
|
+
assert_equal @test_instance.to_sqs_message, @test_instance.sqs_message.contents
|
150
|
+
end
|
151
|
+
|
152
|
+
should "invoke queue! on the sqs_message" do
|
153
|
+
@test_instance.sqs_message.expects(:queue!)
|
154
|
+
@test_instance.queue!
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "to_sqs_message - default implementation" do
|
159
|
+
should "return attrs_for_sqs_message in hash, with attrs as keys and values as values" do
|
160
|
+
instance = TestTransport.new
|
161
|
+
instance.value1 = '1234'
|
162
|
+
instance.value2 = 'abcd'
|
163
|
+
|
164
|
+
assert_equal({:value1 => '1234', :value2 => 'abcd'}, instance.to_sqs_message)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "proxy to SQS::Message instance" do
|
169
|
+
setup do
|
170
|
+
@test_instance = TestTransport.new
|
171
|
+
end
|
172
|
+
|
173
|
+
should "proxy sqs_message_id to sqs_message.id" do
|
174
|
+
@test_instance.sqs_message.expects(:id)
|
175
|
+
@test_instance.sqs_message_id
|
176
|
+
end
|
177
|
+
|
178
|
+
['dequeue!','enqueued_at','dequeued_at','time_in_queue'].each do |proxy_method|
|
179
|
+
should "proxy #{proxy_method} to sqs_message.#{proxy_method}" do
|
180
|
+
@test_instance.sqs_message.expects(proxy_method)
|
181
|
+
@test_instance.send(proxy_method)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sqs_transport
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ben Koski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-10 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: right_aws
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
description: Provides simple enqueue/dequeue facilities for Amazon SQS.
|
36
|
+
email: gems@benkoski.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- lib/sqs
|
45
|
+
- lib/sqs_transport.rb
|
46
|
+
- lib/sqs/config.rb
|
47
|
+
- lib/sqs/message.rb
|
48
|
+
- lib/sqs/message_size_error.rb
|
49
|
+
- lib/sqs/queue.rb
|
50
|
+
- lib/sqs/transport.rb
|
51
|
+
- test/mock_queue.rb
|
52
|
+
- test/test_helper.rb
|
53
|
+
- test/test_sqs_config.rb
|
54
|
+
- test/test_sqs_message.rb
|
55
|
+
- test/test_sqs_queue.rb
|
56
|
+
- test/test_sqs_transport.rb
|
57
|
+
- README
|
58
|
+
- LICENSE
|
59
|
+
has_rdoc: true
|
60
|
+
homepage: http://github.com/bkoski/sqs_transport
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options:
|
63
|
+
- --inline-source
|
64
|
+
- --charset=UTF-8
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
requirements: []
|
80
|
+
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 1.3.1
|
83
|
+
signing_key:
|
84
|
+
specification_version: 2
|
85
|
+
summary: Provides simple enqueue/dequeue facilities for Amazon SQS.
|
86
|
+
test_files: []
|
87
|
+
|