propono 1.7.0 → 2.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +2 -9
- data/CHANGELOG.md +9 -0
- data/Gemfile +0 -2
- data/README.md +35 -91
- data/lib/propono.rb +4 -144
- data/lib/propono/components/aws_client.rb +78 -0
- data/lib/propono/components/aws_config.rb +4 -9
- data/lib/propono/components/client.rb +93 -0
- data/lib/propono/components/queue.rb +4 -6
- data/lib/propono/components/queue_subscription.rb +32 -22
- data/lib/propono/components/sqs_message.rb +3 -6
- data/lib/propono/components/topic.rb +6 -5
- data/lib/propono/configuration.rb +0 -2
- data/lib/propono/services/publisher.rb +21 -44
- data/lib/propono/services/queue_listener.rb +54 -57
- data/lib/propono/version.rb +1 -1
- data/propono.gemspec +3 -2
- data/test/components/aws_config_test.rb +4 -4
- data/test/components/client_test.rb +68 -0
- data/test/components/queue_subscription_test.rb +68 -70
- data/test/components/queue_test.rb +6 -3
- data/test/components/topic_test.rb +4 -2
- data/test/configuration_test.rb +27 -55
- data/test/integration/integration_test.rb +4 -7
- data/test/integration/slow_queue_test.rb +11 -8
- data/test/integration/sns_to_sqs_test.rb +17 -17
- data/test/services/publisher_test.rb +59 -156
- data/test/services/queue_listener_test.rb +96 -103
- data/test/test_helper.rb +21 -48
- metadata +26 -39
- data/lib/propono/components/post_subscription.rb +0 -19
- data/lib/propono/components/sns.rb +0 -11
- data/lib/propono/components/sqs.rb +0 -12
- data/lib/propono/services/queue_creator.rb +0 -29
- data/lib/propono/services/subscriber.rb +0 -12
- data/lib/propono/services/tcp_listener.rb +0 -48
- data/lib/propono/services/topic_creator.rb +0 -23
- data/lib/propono/services/udp_listener.rb +0 -52
- data/test/components/post_subscription_test.rb +0 -29
- data/test/components/sns_test.rb +0 -25
- data/test/components/sqs_test.rb +0 -26
- data/test/integration/tcp_to_sqs_test.rb +0 -53
- data/test/integration/udp_proxy_test.rb +0 -50
- data/test/integration/udp_to_sqs_test.rb +0 -53
- data/test/propono_test.rb +0 -83
- data/test/services/queue_creator_test.rb +0 -61
- data/test/services/subscriber_test.rb +0 -21
- data/test/services/tcp_listener_test.rb +0 -76
- data/test/services/topic_creator_test.rb +0 -40
- data/test/services/udp_listener_test.rb +0 -73
@@ -1,11 +1,6 @@
|
|
1
1
|
module Propono
|
2
|
-
|
3
|
-
def self.aws_options
|
4
|
-
AwsConfig.new(Propono.config).aws_options
|
5
|
-
end
|
6
|
-
|
7
2
|
class AwsConfig
|
8
|
-
|
3
|
+
|
9
4
|
def initialize(config)
|
10
5
|
@config = config
|
11
6
|
end
|
@@ -18,11 +13,11 @@ module Propono
|
|
18
13
|
}
|
19
14
|
else
|
20
15
|
{
|
21
|
-
:
|
22
|
-
:
|
16
|
+
:access_key_id => @config.access_key,
|
17
|
+
:secret_access_key => @config.secret_key,
|
23
18
|
:region => @config.queue_region
|
24
19
|
}
|
25
20
|
end
|
26
21
|
end
|
27
22
|
end
|
28
|
-
end
|
23
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Propono
|
2
|
+
class Client
|
3
|
+
|
4
|
+
# Propono configuration settings.
|
5
|
+
#
|
6
|
+
# Settings should be set in an initializer or using some
|
7
|
+
# other method that insures they are set before any
|
8
|
+
# Propono code is used. They can be set as followed:
|
9
|
+
#
|
10
|
+
# Propono.config.access_key = "my-access-key"
|
11
|
+
#
|
12
|
+
# The following settings are allowed:
|
13
|
+
#
|
14
|
+
# * <tt>:access_key</tt> - The AWS access key
|
15
|
+
# * <tt>:secret_key</tt> - The AWS secret key
|
16
|
+
# * <tt>:queue_region</tt> - The AWS region
|
17
|
+
# * <tt>:application_name</tt> - The name of the application Propono
|
18
|
+
# is included in.
|
19
|
+
# * <tt>:queue_suffix</tt> - Optional string to append to topic and queue names.
|
20
|
+
# * <tt>:logger</tt> - A logger object that responds to puts.
|
21
|
+
|
22
|
+
attr_reader :config, :aws_client
|
23
|
+
def initialize(settings = {}, &block)
|
24
|
+
@config = Configuration.new
|
25
|
+
if block_given?
|
26
|
+
configure(&block)
|
27
|
+
else
|
28
|
+
settings.each do |key, value|
|
29
|
+
config.send("#{key}=", value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@aws_client = AwsClient.new(AwsConfig.new(config))
|
34
|
+
end
|
35
|
+
|
36
|
+
def configure(&block)
|
37
|
+
yield config
|
38
|
+
end
|
39
|
+
|
40
|
+
# Publishes a new message into the Propono pub/sub network.
|
41
|
+
#
|
42
|
+
# This requires a topic and a message. By default this pushes
|
43
|
+
# out AWS SNS.
|
44
|
+
#
|
45
|
+
# @param [String] topic The name of the topic to publish to.
|
46
|
+
# @param [String] message The message to post.
|
47
|
+
def publish(topic, message, options = {})
|
48
|
+
suffixed_topic = "#{topic}#{config.queue_suffix}"
|
49
|
+
Publisher.publish(aws_client, config, suffixed_topic, message, options)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Creates a new SNS-SQS subscription on the specified topic.
|
53
|
+
#
|
54
|
+
# This is implicitly called by {#listen_to_queue}.
|
55
|
+
#
|
56
|
+
# @param [String] topic The name of the topic to subscribe to.
|
57
|
+
def subscribe(topic)
|
58
|
+
QueueSubscription.create(aws_client, config, topic)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Listens on a queue and yields for each message
|
62
|
+
#
|
63
|
+
# Calling this will enter a queue-listening loop that
|
64
|
+
# yields the message_processor for each messages.
|
65
|
+
#
|
66
|
+
# This method will automatically create a subscription if
|
67
|
+
# one does not exist, so there is no need to call
|
68
|
+
# <tt>subscribe</tt> in addition.
|
69
|
+
#
|
70
|
+
# @param [String] topic The topic to subscribe to.
|
71
|
+
# @param &message_processor The block to yield for each message.
|
72
|
+
def listen(topic_name, &message_processor)
|
73
|
+
QueueListener.listen(aws_client, config, topic_name, &message_processor)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Listens on a queue and yields for each message
|
77
|
+
#
|
78
|
+
# Calling this will enter a queue-listening loop that
|
79
|
+
# yields the message_processor for each messages. The
|
80
|
+
# loop will end when all messages have been processed.
|
81
|
+
#
|
82
|
+
# This method will automatically create a subscription if
|
83
|
+
# one does not exist, so there is no need to call
|
84
|
+
# <tt>subscribe</tt> in addition.
|
85
|
+
#
|
86
|
+
# @param [String] topic The topic to subscribe to.
|
87
|
+
# @param &message_processor The block to yield for each message.
|
88
|
+
def drain_queue(topic, &message_processor)
|
89
|
+
QueueListener.drain(aws_client, config, topic, &message_processor)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
@@ -1,16 +1,14 @@
|
|
1
1
|
module Propono
|
2
2
|
class Queue
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
attr_reader :url
|
7
|
-
def initialize(url)
|
4
|
+
attr_reader :url, :attributes
|
5
|
+
def initialize(url, attributes)
|
8
6
|
@url = url
|
7
|
+
@attributes = attributes
|
9
8
|
end
|
10
9
|
|
11
10
|
def arn
|
12
|
-
|
13
|
-
attributes["QueueArn"]
|
11
|
+
@arn ||= attributes["QueueArn"]
|
14
12
|
end
|
15
13
|
end
|
16
14
|
end
|
@@ -1,37 +1,47 @@
|
|
1
1
|
module Propono
|
2
2
|
class QueueSubscription
|
3
3
|
|
4
|
-
|
5
|
-
include Sqs
|
4
|
+
attr_reader :aws_client, :propono_config, :topic_arn, :queue_name, :queue, :failed_queue, :corrupt_queue, :slow_queue
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
def self.create(topic_id, options = {})
|
10
|
-
new(topic_id, options).tap do |subscription|
|
6
|
+
def self.create(*args)
|
7
|
+
new(*args).tap do |subscription|
|
11
8
|
subscription.create
|
12
9
|
end
|
13
10
|
end
|
14
11
|
|
15
|
-
def initialize(
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
12
|
+
def initialize(aws_client, propono_config, topic_name)
|
13
|
+
@aws_client = aws_client
|
14
|
+
@propono_config = propono_config
|
15
|
+
@topic_name = topic_name
|
16
|
+
@suffixed_topic_name = "#{topic_name}#{propono_config.queue_suffix}"
|
17
|
+
@suffixed_slow_topic_name = "#{topic_name}#{propono_config.queue_suffix}-slow"
|
18
|
+
@queue_name = "#{propono_config.application_name.gsub(" ", "_")}-#{@suffixed_topic_name}"
|
20
19
|
end
|
21
20
|
|
22
21
|
def create
|
23
|
-
raise ProponoError.new("
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
raise ProponoError.new("topic_name is nil") unless @topic_name
|
23
|
+
create_and_subscribe_main_queue
|
24
|
+
create_and_subscribe_slow_queue
|
25
|
+
create_misc_queues
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_and_subscribe_main_queue
|
29
|
+
@queue = aws_client.create_queue(queue_name)
|
30
|
+
topic = aws_client.create_topic(@suffixed_topic_name)
|
31
|
+
aws_client.subscribe_sqs_to_sns(@queue, topic)
|
32
|
+
aws_client.set_sqs_policy(@queue, generate_policy(@queue, topic))
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_misc_queues
|
36
|
+
@failed_queue = aws_client.create_queue("#{queue_name}-failed")
|
37
|
+
@corrupt_queue = aws_client.create_queue("#{queue_name}-corrupt")
|
38
|
+
end
|
30
39
|
|
31
|
-
|
32
|
-
@
|
33
|
-
|
34
|
-
|
40
|
+
def create_and_subscribe_slow_queue
|
41
|
+
@slow_queue = aws_client.create_queue("#{queue_name}-slow")
|
42
|
+
slow_topic = aws_client.create_topic(@suffixed_slow_topic_name)
|
43
|
+
aws_client.subscribe_sqs_to_sns(@slow_queue, slow_topic)
|
44
|
+
aws_client.set_sqs_policy(@slow_queue, generate_policy(@slow_queue, slow_topic))
|
35
45
|
end
|
36
46
|
|
37
47
|
private
|
@@ -1,18 +1,15 @@
|
|
1
1
|
module Propono
|
2
2
|
class SqsMessage
|
3
|
-
|
4
|
-
|
5
|
-
attr_reader :context, :message, :raw_message, :receipt_handle, :failure_count
|
3
|
+
attr_reader :context, :message, :receipt_handle, :failure_count
|
6
4
|
def initialize(raw_message)
|
7
|
-
raw_body = raw_message
|
5
|
+
raw_body = raw_message.body
|
8
6
|
@raw_body_json = JSON.parse(raw_body)
|
9
7
|
body = JSON.parse(@raw_body_json["Message"])
|
10
8
|
|
11
|
-
@raw_message = raw_message
|
12
9
|
@context = Propono::Utils.symbolize_keys body
|
13
10
|
@failure_count = context[:num_failures] || 0
|
14
11
|
@message = context.delete(:message)
|
15
|
-
@receipt_handle = raw_message
|
12
|
+
@receipt_handle = raw_message.receipt_handle
|
16
13
|
end
|
17
14
|
|
18
15
|
def to_json_with_exception(exception)
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module Propono
|
2
2
|
class Topic
|
3
|
+
attr_reader :aws_topic
|
4
|
+
def initialize(aws_topic)
|
5
|
+
@aws_topic = aws_topic
|
6
|
+
end
|
3
7
|
|
4
|
-
|
5
|
-
|
6
|
-
attr_reader :arn
|
7
|
-
def initialize(arn)
|
8
|
-
@arn = arn
|
8
|
+
def arn
|
9
|
+
@arn ||= aws_topic.topic_arn
|
9
10
|
end
|
10
11
|
end
|
11
12
|
end
|
@@ -5,76 +5,53 @@ module Propono
|
|
5
5
|
end
|
6
6
|
|
7
7
|
class Publisher
|
8
|
-
|
9
|
-
|
10
|
-
def self.publish(topic_id, message, options = {})
|
11
|
-
new(topic_id, message, options).publish
|
8
|
+
def self.publish(*args)
|
9
|
+
new(*args).publish
|
12
10
|
end
|
13
11
|
|
14
|
-
attr_reader :
|
12
|
+
attr_reader :aws_client, :propono_config, :topic_name, :message, :id, :async
|
15
13
|
|
16
|
-
def initialize(
|
17
|
-
raise PublisherError.new("Topic is nil") if
|
14
|
+
def initialize(aws_client, propono_config, topic_name, message, async: false, id: nil)
|
15
|
+
raise PublisherError.new("Topic is nil") if topic_name.nil?
|
18
16
|
raise PublisherError.new("Message is nil") if message.nil?
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
@
|
18
|
+
@aws_client = aws_client
|
19
|
+
@propono_config = propono_config
|
20
|
+
@topic_name = topic_name
|
23
21
|
@message = message
|
24
|
-
@
|
25
|
-
|
26
|
-
|
27
|
-
@
|
22
|
+
@async = async
|
23
|
+
|
24
|
+
random_id = SecureRandom.hex(3)
|
25
|
+
@id = id ? "#{id}-#{random_id}" : random_id
|
28
26
|
end
|
29
27
|
|
30
28
|
def publish
|
31
|
-
|
32
|
-
|
29
|
+
propono_config.logger.info "Propono [#{id}]: Publishing #{message} to #{topic_name}"
|
30
|
+
async ? publish_asyncronously : publish_syncronously
|
33
31
|
end
|
34
32
|
|
35
33
|
private
|
36
34
|
|
37
|
-
def
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
def publish_via_sns_asyncronously
|
42
|
-
Thread.new { publish_via_sns_syncronously }
|
35
|
+
def publish_asyncronously
|
36
|
+
Thread.new { publish_syncronously }
|
43
37
|
end
|
44
38
|
|
45
|
-
def
|
39
|
+
def publish_syncronously
|
46
40
|
begin
|
47
|
-
topic =
|
41
|
+
topic = aws_client.create_topic(topic_name)
|
48
42
|
rescue => e
|
49
|
-
|
43
|
+
propono_config.logger.error "Propono [#{id}]: Failed to get or create topic #{topic_name}: #{e}"
|
50
44
|
raise
|
51
45
|
end
|
52
46
|
|
53
47
|
begin
|
54
|
-
|
48
|
+
aws_client.publish_to_sns(topic, body)
|
55
49
|
rescue => e
|
56
|
-
|
50
|
+
propono_config.logger.error "Propono [#{id}]: Failed to send via sns: #{e}"
|
57
51
|
raise
|
58
52
|
end
|
59
53
|
end
|
60
54
|
|
61
|
-
def publish_via_udp
|
62
|
-
payload = body.merge(topic: topic_id).to_json
|
63
|
-
UDPSocket.new.send(payload, 0, Propono.config.udp_host, Propono.config.udp_port)
|
64
|
-
rescue => e
|
65
|
-
Propono.config.logger.error "Propono [#{id}]: Failed to send : #{e}"
|
66
|
-
end
|
67
|
-
|
68
|
-
def publish_via_tcp
|
69
|
-
payload = body.merge(topic: topic_id).to_json
|
70
|
-
|
71
|
-
socket = TCPSocket.new(Propono.config.tcp_host, Propono.config.tcp_port)
|
72
|
-
socket.write payload
|
73
|
-
socket.close
|
74
|
-
rescue => e
|
75
|
-
Propono.config.logger.error "Propono [#{id}]: Failed to send : #{e}"
|
76
|
-
end
|
77
|
-
|
78
55
|
def body
|
79
56
|
{
|
80
57
|
id: id,
|
@@ -1,127 +1,124 @@
|
|
1
1
|
module Propono
|
2
2
|
|
3
3
|
class QueueListener
|
4
|
-
|
5
|
-
|
6
|
-
def self.listen(topic_id, &message_processor)
|
7
|
-
new(topic_id, &message_processor).listen
|
4
|
+
def self.listen(*args, &message_processor)
|
5
|
+
new(*args, &message_processor).listen
|
8
6
|
end
|
9
7
|
|
10
|
-
def self.drain(
|
11
|
-
new(
|
8
|
+
def self.drain(*args, &message_processor)
|
9
|
+
new(*args, &message_processor).drain
|
12
10
|
end
|
13
11
|
|
14
|
-
|
15
|
-
|
12
|
+
attr_reader :aws_client, :propono_config, :topic_name, :message_processor
|
13
|
+
def initialize(aws_client, propono_config, topic_name, &message_processor)
|
14
|
+
@aws_client = aws_client
|
15
|
+
@propono_config = propono_config
|
16
|
+
@topic_name = topic_name
|
16
17
|
@message_processor = message_processor
|
17
18
|
end
|
18
19
|
|
19
20
|
def listen
|
20
|
-
raise ProponoError.new("
|
21
|
+
raise ProponoError.new("topic_name is nil") unless topic_name
|
21
22
|
loop do
|
22
|
-
|
23
|
-
sleep 10
|
24
|
-
end
|
23
|
+
read_messages
|
25
24
|
end
|
26
25
|
end
|
27
26
|
|
28
27
|
def drain
|
29
|
-
raise ProponoError.new("
|
30
|
-
while
|
31
|
-
|
32
|
-
end
|
28
|
+
raise ProponoError.new("topic_name is nil") unless topic_name
|
29
|
+
true while read_messages_from_queue(main_queue, 10, long_poll: false)
|
30
|
+
true while read_messages_from_queue(slow_queue, 10, long_poll: false)
|
33
31
|
end
|
34
32
|
|
35
33
|
private
|
36
34
|
|
37
35
|
def read_messages
|
38
|
-
read_messages_from_queue(
|
36
|
+
read_messages_from_queue(main_queue, propono_config.num_messages_per_poll) ||
|
37
|
+
read_messages_from_queue(slow_queue, 1)
|
39
38
|
end
|
40
39
|
|
41
|
-
def read_messages_from_queue(
|
42
|
-
|
43
|
-
messages = response.body['Message']
|
40
|
+
def read_messages_from_queue(queue, num_messages, long_poll: true)
|
41
|
+
messages = aws_client.read_from_sqs(queue, num_messages, long_poll: long_poll)
|
44
42
|
if messages.empty?
|
45
43
|
false
|
46
44
|
else
|
47
|
-
messages.each { |msg| process_raw_message(msg,
|
45
|
+
messages.each { |msg| process_raw_message(msg, queue) }
|
46
|
+
true
|
48
47
|
end
|
49
|
-
rescue
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
Propono.config.logger.error $!
|
56
|
-
Propono.config.logger.error $!.backtrace
|
48
|
+
rescue => e #Aws::Errors => e
|
49
|
+
propono_config.logger.error "Unexpected error reading from queue #{queue.url}"
|
50
|
+
propono_config.logger.error e.class.name
|
51
|
+
propono_config.logger.error e.message
|
52
|
+
propono_config.logger.error e.backtrace
|
53
|
+
false
|
57
54
|
end
|
58
55
|
|
59
56
|
# The calls to delete_message are deliberately duplicated so
|
60
57
|
# as to ensure the message is only deleted if the preceeding line
|
61
58
|
# has completed succesfully. We do *not* want to ensure that the
|
62
59
|
# message is deleted regardless of what happens in this method.
|
63
|
-
def process_raw_message(raw_sqs_message,
|
64
|
-
sqs_message = parse(raw_sqs_message,
|
65
|
-
unless sqs_message
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
60
|
+
def process_raw_message(raw_sqs_message, queue)
|
61
|
+
sqs_message = parse(raw_sqs_message, queue)
|
62
|
+
return unless sqs_message
|
63
|
+
|
64
|
+
propono_config.logger.info "Propono [#{sqs_message.context[:id]}]: Received from sqs."
|
65
|
+
handle(sqs_message)
|
66
|
+
aws_client.delete_from_sqs(queue, sqs_message.receipt_handle)
|
70
67
|
end
|
71
68
|
|
72
|
-
def parse(raw_sqs_message,
|
69
|
+
def parse(raw_sqs_message, queue)
|
73
70
|
SqsMessage.new(raw_sqs_message)
|
74
71
|
rescue
|
75
|
-
|
72
|
+
propono_config.logger.error "Error parsing message, moving to corrupt queue", $!, $!.backtrace
|
76
73
|
move_to_corrupt_queue(raw_sqs_message)
|
77
|
-
|
74
|
+
aws_client.delete_from_sqs(queue, raw_sqs_message.receipt_handle)
|
78
75
|
nil
|
79
76
|
end
|
80
77
|
|
81
78
|
def handle(sqs_message)
|
82
79
|
process_message(sqs_message)
|
83
80
|
rescue => e
|
84
|
-
|
81
|
+
propono_config.logger.error("Failed to handle message #{e.message} #{e.backtrace}")
|
85
82
|
requeue_message_on_failure(sqs_message, e)
|
86
83
|
end
|
87
84
|
|
88
85
|
def process_message(sqs_message)
|
89
|
-
|
86
|
+
return false unless message_processor
|
87
|
+
message_processor.call(sqs_message.message, sqs_message.context)
|
90
88
|
end
|
91
89
|
|
92
90
|
def move_to_corrupt_queue(raw_sqs_message)
|
93
|
-
|
91
|
+
aws_client.send_to_sqs(corrupt_queue, raw_sqs_message.body)
|
94
92
|
end
|
95
93
|
|
96
94
|
def requeue_message_on_failure(sqs_message, exception)
|
97
|
-
next_queue = (sqs_message.failure_count <
|
98
|
-
|
99
|
-
|
95
|
+
next_queue = (sqs_message.failure_count < propono_config.max_retries) ? main_queue : failed_queue
|
96
|
+
propono_config.logger.error "Error proessing message, moving to queue: #{next_queue}"
|
97
|
+
aws_client.send_to_sqs(next_queue, sqs_message.to_json_with_exception(exception))
|
100
98
|
end
|
101
99
|
|
102
|
-
def delete_message(raw_sqs_message,
|
103
|
-
|
100
|
+
def delete_message(raw_sqs_message, queue)
|
101
|
+
aws_client.delete_from_sqs(queue, raw_sqs_message.receipt_handle)
|
104
102
|
end
|
105
103
|
|
106
|
-
def
|
107
|
-
@
|
104
|
+
def main_queue
|
105
|
+
@main_queue ||= subscription.queue
|
108
106
|
end
|
109
107
|
|
110
|
-
def
|
111
|
-
@
|
108
|
+
def failed_queue
|
109
|
+
@failed_queue ||= subscription.failed_queue
|
112
110
|
end
|
113
111
|
|
114
|
-
def
|
115
|
-
@
|
112
|
+
def corrupt_queue
|
113
|
+
@corrupt_queue ||= subscription.corrupt_queue
|
116
114
|
end
|
117
115
|
|
118
|
-
def
|
119
|
-
@
|
116
|
+
def slow_queue
|
117
|
+
@slow_queue ||= subscription.slow_queue
|
120
118
|
end
|
121
119
|
|
122
120
|
def subscription
|
123
|
-
|
121
|
+
QueueSubscription.create(aws_client, propono_config, topic_name)
|
124
122
|
end
|
125
|
-
|
126
123
|
end
|
127
124
|
end
|