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
@@ -2,23 +2,20 @@ require File.expand_path('../../test_helper', __FILE__)
|
|
2
2
|
|
3
3
|
module Propono
|
4
4
|
class IntegrationTest < Minitest::Test
|
5
|
-
def setup
|
6
|
-
super
|
7
|
-
Fog.unmock!
|
8
5
|
|
6
|
+
def propono_client
|
9
7
|
config_file = YAML.load_file( File.expand_path('../../config.yml', __FILE__))
|
10
|
-
Propono.
|
8
|
+
@propono_client ||= Propono::Client.new do |config|
|
11
9
|
config.access_key = config_file['access_key']
|
12
10
|
config.secret_key = config_file['secret_key']
|
13
11
|
config.queue_region = config_file['queue_region']
|
14
12
|
config.application_name = config_file['application_name']
|
15
|
-
config.udp_host = "localhost"
|
16
13
|
end
|
17
14
|
end
|
18
15
|
|
19
16
|
# Wait a max of 20secs before failing the test
|
20
|
-
def wait_for_thread(thread)
|
21
|
-
|
17
|
+
def wait_for_thread(thread, secs = 20)
|
18
|
+
(secs * 10).times do |x|
|
22
19
|
return true unless thread.alive?
|
23
20
|
sleep(0.1)
|
24
21
|
end
|
@@ -11,16 +11,18 @@ module Propono
|
|
11
11
|
message_received = false
|
12
12
|
slow_message_received = false
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
propono_client.drain_queue(topic)
|
15
|
+
propono_client.drain_queue(slow_topic)
|
16
|
+
|
17
|
+
propono_client.subscribe(topic)
|
17
18
|
|
18
19
|
thread = Thread.new do
|
19
20
|
begin
|
20
|
-
|
21
|
+
propono_client.listen(topic) do |message, context|
|
21
22
|
flunks << "Wrong message" unless (message == text || message == slow_text)
|
22
23
|
message_received = true if message == text
|
23
24
|
slow_message_received = true if message == slow_text
|
25
|
+
thread.terminate if message_received && slow_message_received
|
24
26
|
end
|
25
27
|
rescue => e
|
26
28
|
flunks << e.message
|
@@ -38,12 +40,13 @@ module Propono
|
|
38
40
|
|
39
41
|
sleep(1) # Make sure the listener has started
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
propono_client.publish(slow_topic, slow_text)
|
44
|
+
propono_client.publish(topic, text)
|
45
|
+
|
46
|
+
flunks << "Test Timeout" unless wait_for_thread(thread, 60)
|
44
47
|
flunk(flunks.join("\n")) unless flunks.empty?
|
45
48
|
ensure
|
46
|
-
|
49
|
+
thread.terminate if thread
|
47
50
|
end
|
48
51
|
end
|
49
52
|
end
|
@@ -8,15 +8,16 @@ module Propono
|
|
8
8
|
flunks = []
|
9
9
|
message_received = false
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
propono_client.drain_queue(topic)
|
12
|
+
propono_client.subscribe(topic)
|
13
13
|
|
14
14
|
thread = Thread.new do
|
15
15
|
begin
|
16
|
-
|
16
|
+
propono_client.listen(topic) do |message, context|
|
17
17
|
flunks << "Wrong message" unless message == text
|
18
18
|
flunks << "Wrong id" unless context[:id] =~ Regexp.new("[a-z0-9]{6}")
|
19
19
|
message_received = true
|
20
|
+
thread.terminate
|
20
21
|
end
|
21
22
|
rescue => e
|
22
23
|
flunks << e.message
|
@@ -33,27 +34,26 @@ module Propono
|
|
33
34
|
|
34
35
|
sleep(1) # Make sure the listener has started
|
35
36
|
|
36
|
-
|
37
|
+
propono_client.publish(topic, text)
|
37
38
|
flunks << "Test Timeout" unless wait_for_thread(thread)
|
38
39
|
flunk(flunks.join("\n")) unless flunks.empty?
|
39
40
|
ensure
|
40
|
-
thread.terminate
|
41
|
+
thread.terminate if thread
|
41
42
|
end
|
42
43
|
|
43
44
|
=begin
|
44
|
-
|
45
|
-
|
46
45
|
def test_failed_messge_is_transferred_to_failed_channel
|
47
|
-
topic = "
|
46
|
+
topic = "propono-tests-sns-to-sqs-topic-failed"
|
48
47
|
text = "This is my message #{DateTime.now} #{rand()}"
|
49
48
|
flunks = []
|
50
49
|
message_received = false
|
51
50
|
|
52
|
-
|
51
|
+
propono_client.drain_queue(topic)
|
52
|
+
propono_client.subscribe(topic)
|
53
53
|
|
54
54
|
thread = Thread.new do
|
55
55
|
begin
|
56
|
-
|
56
|
+
propono_client.listen(topic) do |message, context|
|
57
57
|
raise StandardError.new 'BOOM'
|
58
58
|
end
|
59
59
|
rescue => e
|
@@ -63,12 +63,13 @@ module Propono
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
-
|
66
|
+
failure_thread = Thread.new do
|
67
67
|
begin
|
68
|
-
|
68
|
+
propono_client.listen(topic, channel: :failed) do |message, context|
|
69
69
|
flunks << "Wrong message" unless message == text
|
70
70
|
flunks << "Wrong id" unless context[:id] =~ Regexp.new("[a-z0-9]{6}")
|
71
71
|
message_received = true
|
72
|
+
failure_thread.terminate
|
72
73
|
end
|
73
74
|
rescue => e
|
74
75
|
flunks << e.message
|
@@ -79,21 +80,20 @@ module Propono
|
|
79
80
|
|
80
81
|
Thread.new do
|
81
82
|
sleep(1) while !message_received
|
83
|
+
p "Message received"
|
82
84
|
sleep(5) # Make sure all the message deletion clear up in the thread has happened
|
83
85
|
thread.terminate
|
84
|
-
|
86
|
+
failure_thread.terminate
|
85
87
|
end
|
86
88
|
|
87
89
|
sleep(1) # Make sure the listener has started
|
88
90
|
|
89
|
-
|
91
|
+
propono_client.publish(topic, text)
|
90
92
|
flunks << "Test Timeout" unless wait_for_thread(thread)
|
91
93
|
flunk(flunks.join("\n")) unless flunks.empty?
|
92
94
|
ensure
|
93
|
-
thread.terminate
|
95
|
+
thread.terminate if thread
|
94
96
|
end
|
95
|
-
|
96
97
|
=end
|
97
|
-
|
98
98
|
end
|
99
99
|
end
|
@@ -4,94 +4,87 @@ module Propono
|
|
4
4
|
class PublisherTest < Minitest::Test
|
5
5
|
|
6
6
|
def test_initialization
|
7
|
-
publisher = Publisher.new('topic', 'message')
|
7
|
+
publisher = Publisher.new(aws_client, propono_config, 'topic', 'message')
|
8
8
|
refute publisher.nil?
|
9
9
|
end
|
10
10
|
|
11
11
|
def test_self_publish_calls_new
|
12
12
|
topic = "topic123"
|
13
13
|
message = "message123"
|
14
|
-
Publisher.expects(:new).with(topic, message
|
15
|
-
Publisher.publish(topic, message)
|
14
|
+
Publisher.expects(:new).with(aws_client, topic, message).returns(mock(publish: nil))
|
15
|
+
Publisher.publish(aws_client, topic, message)
|
16
16
|
end
|
17
17
|
|
18
18
|
def test_initializer_generates_an_id
|
19
|
-
publisher = Publisher.new('x','y')
|
19
|
+
publisher = Publisher.new(aws_client, propono_config, 'x','y')
|
20
20
|
assert publisher.instance_variable_get(:@id)
|
21
21
|
end
|
22
22
|
|
23
23
|
def test_initializer_concats_an_id
|
24
24
|
id = "q1w2e3"
|
25
|
-
|
26
|
-
|
25
|
+
hex = "313abd"
|
26
|
+
SecureRandom.expects(:hex).with(3).returns(hex)
|
27
|
+
publisher = Publisher.new(aws_client, propono_config, 'x','y', id: id)
|
28
|
+
assert_equal "#{id}-#{hex}", publisher.id
|
27
29
|
end
|
28
30
|
|
29
31
|
def test_self_publish_calls_publish
|
30
32
|
Publisher.any_instance.expects(:publish)
|
31
|
-
Publisher.publish("topic", "message")
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_protocol_should_be_sns_by_default
|
35
|
-
publisher = Publisher.new('topic', 'message')
|
36
|
-
assert_equal :sns, publisher.protocol
|
33
|
+
Publisher.publish(aws_client, propono_config, "topic", "message")
|
37
34
|
end
|
38
35
|
|
39
36
|
def test_publish_logs
|
40
|
-
publisher = Publisher.new("foo", "bar")
|
37
|
+
publisher = Publisher.new(aws_client, propono_config, "foo", "bar")
|
41
38
|
publisher.instance_variable_set(:@id, 'abc')
|
42
|
-
publisher.stubs(:
|
43
|
-
|
44
|
-
publisher.send(:publish)
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_publish_proxies_to_sns
|
48
|
-
publisher = Publisher.new('topic', 'message')
|
49
|
-
publisher.expects(:publish_via_sns)
|
50
|
-
publisher.publish
|
51
|
-
end
|
52
|
-
|
53
|
-
def test_publish_proxies_to_udp
|
54
|
-
publisher = Publisher.new('topic', 'message', protocol: :udp)
|
55
|
-
publisher.expects(:publish_via_udp)
|
39
|
+
publisher.stubs(:publish_syncronously)
|
40
|
+
propono_config.logger.expects(:info).with {|x| x =~ /^Propono \[abc\]: Publishing bar to foo.*/}
|
56
41
|
publisher.publish
|
57
42
|
end
|
58
43
|
|
59
|
-
def
|
60
|
-
|
44
|
+
def test_publish_should_call_sns_on_correct_topic_and_message
|
45
|
+
topic_name = "topic123"
|
61
46
|
id = "f123"
|
62
47
|
message = "message123"
|
48
|
+
|
49
|
+
topic = mock
|
63
50
|
topic_arn = "arn123"
|
64
|
-
topic
|
51
|
+
topic.stubs(arn: topic_arn)
|
65
52
|
|
66
|
-
|
53
|
+
aws_client.expects(:create_topic).with(topic_name).returns(topic)
|
54
|
+
aws_client.expects(:publish_to_sns).with(
|
55
|
+
topic,
|
56
|
+
{id: id, message: message}
|
57
|
+
)
|
67
58
|
|
68
|
-
|
69
|
-
|
70
|
-
publisher
|
71
|
-
publisher.stubs(id: id, sns: sns)
|
72
|
-
thread = publisher.send(:publish_via_sns)
|
73
|
-
thread.join
|
59
|
+
publisher = Publisher.new(aws_client, propono_config, topic_name, message)
|
60
|
+
publisher.stubs(id: id)
|
61
|
+
publisher.publish
|
74
62
|
end
|
75
63
|
|
76
|
-
def
|
77
|
-
|
64
|
+
def test_publish_should_accept_a_hash_for_message
|
65
|
+
topic_name = "topic123"
|
78
66
|
id = "foobar123"
|
79
67
|
message = {something: ['some', 123, true]}
|
80
68
|
body = {id: id, message: message}
|
81
69
|
|
70
|
+
topic = mock
|
82
71
|
topic_arn = "arn123"
|
83
|
-
topic
|
84
|
-
TopicCreator.stubs(find_or_create: topic)
|
72
|
+
topic.stubs(topic_arn: topic_arn)
|
85
73
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
74
|
+
topic = mock
|
75
|
+
topic_arn = "arn123"
|
76
|
+
topic.stubs(arn: topic_arn)
|
77
|
+
|
78
|
+
aws_client.expects(:create_topic).with(topic_name).returns(topic)
|
79
|
+
aws_client.expects(:publish_to_sns).with(topic, body)
|
80
|
+
|
81
|
+
publisher = Publisher.new(aws_client, propono_config, topic_name, message)
|
82
|
+
publisher.stubs(id: id)
|
83
|
+
publisher.publish
|
92
84
|
end
|
93
85
|
|
94
|
-
def
|
86
|
+
def test_publish_async_should_return_future_of_the_sns_response
|
87
|
+
skip "Rebuild this maybe"
|
95
88
|
topic = "topic123"
|
96
89
|
id = "foobar123"
|
97
90
|
message = "message123"
|
@@ -99,142 +92,52 @@ module Propono
|
|
99
92
|
|
100
93
|
topic_arn = "arn123"
|
101
94
|
topic = Topic.new(topic_arn)
|
102
|
-
TopicCreator.stubs(find_or_create: topic)
|
103
95
|
|
104
96
|
sns = mock()
|
105
97
|
sns.expects(:publish).with(topic_arn, body.to_json).returns(:response)
|
106
|
-
publisher = Publisher.new(topic, message)
|
98
|
+
publisher = Publisher.new(aws_client, propono_config, topic, message, async: true)
|
107
99
|
publisher.stubs(id: id, sns: sns)
|
108
|
-
assert_same :response, publisher.send(:
|
100
|
+
assert_same :response, publisher.send(:publish_syncronously).value
|
109
101
|
end
|
110
102
|
|
111
|
-
def
|
112
|
-
|
103
|
+
def test_publish_should_propogate_exception_on_topic_creation_error
|
104
|
+
aws_client.expects(:create_topic).raises(RuntimeError)
|
105
|
+
publisher = Publisher.new(aws_client, propono_config, "topic", "message")
|
113
106
|
|
114
|
-
assert_raises(
|
115
|
-
publisher
|
116
|
-
thread = publisher.send(:publish_via_sns)
|
117
|
-
thread.join
|
107
|
+
assert_raises(RuntimeError) do
|
108
|
+
publisher.publish
|
118
109
|
end
|
119
110
|
end
|
120
111
|
|
121
|
-
def test_publish_via_sns_creates_a_topic
|
122
|
-
topic_id = "Malcs_topic_id"
|
123
|
-
topic_arn = "Malcs_topic_arn"
|
124
|
-
topic = Topic.new(topic_arn)
|
125
|
-
|
126
|
-
TopicCreator.expects(:find_or_create).with(topic_id).returns(topic)
|
127
|
-
|
128
|
-
sns = mock()
|
129
|
-
sns.stubs(:publish)
|
130
|
-
publisher = Publisher.new(topic_id, "Foobar")
|
131
|
-
publisher.stubs(sns: sns)
|
132
|
-
|
133
|
-
thread = publisher.send(:publish_via_sns)
|
134
|
-
thread.join
|
135
|
-
end
|
136
|
-
|
137
|
-
def test_udp_uses_correct_message_host_and_port
|
138
|
-
host = "http://meducation.net"
|
139
|
-
port = 1234
|
140
|
-
Propono.config.udp_host = host
|
141
|
-
Propono.config.udp_port = port
|
142
|
-
topic_id = "my-fav-topic"
|
143
|
-
|
144
|
-
id = "foobar123"
|
145
|
-
message = "cat dog mouse"
|
146
|
-
payload = {id: id, message: message, topic: topic_id}.to_json
|
147
|
-
UDPSocket.any_instance.expects(:send).with(payload, 0, host, port)
|
148
|
-
|
149
|
-
publisher = Publisher.new(topic_id, message)
|
150
|
-
publisher.stubs(id: id)
|
151
|
-
publisher.send(:publish_via_udp)
|
152
|
-
end
|
153
|
-
|
154
|
-
def test_exception_from_udpsocket_caught_and_logged
|
155
|
-
host = "http://meducation.net"
|
156
|
-
port = 1234
|
157
|
-
Propono.config.udp_host = host
|
158
|
-
Propono.config.udp_port = port
|
159
|
-
|
160
|
-
publisher = Publisher.new("topic_id", "message")
|
161
|
-
publisher.stubs(id: '123asd')
|
162
|
-
Propono.config.logger.expects(:error).with() {|x| x =~ /^Propono \[123asd\]: Failed to send : getaddrinfo:.*/}
|
163
|
-
publisher.send(:publish_via_udp)
|
164
|
-
end
|
165
|
-
|
166
112
|
def test_publish_should_raise_exception_if_topic_is_nil
|
167
113
|
assert_raises(PublisherError, "Topic is nil") do
|
168
|
-
Publisher.publish(nil, "foobar")
|
114
|
+
Publisher.publish(aws_client, propono_config, nil, "foobar")
|
169
115
|
end
|
170
116
|
end
|
171
117
|
|
172
|
-
def test_tcp_uses_correct_message
|
173
|
-
Propono.config.tcp_host = "http://meducation.net"
|
174
|
-
Propono.config.tcp_port = 1234
|
175
|
-
topic_id = "my-fav-topic"
|
176
|
-
id = "qweqw2312"
|
177
|
-
message = "foobar"
|
178
|
-
payload = {id: id, message: message, topic: topic_id}.to_json
|
179
|
-
|
180
|
-
socket = mock()
|
181
|
-
socket.expects(:write).with(payload)
|
182
|
-
socket.expects(:close)
|
183
|
-
TCPSocket.stubs(new: socket)
|
184
|
-
|
185
|
-
publisher = Publisher.new(topic_id, message)
|
186
|
-
publisher.stubs(id: id)
|
187
|
-
publisher.send(:publish_via_tcp)
|
188
|
-
end
|
189
|
-
|
190
|
-
def test_tcp_uses_correct_message_host_and_port
|
191
|
-
host = "http://meducation.net"
|
192
|
-
port = 1234
|
193
|
-
Propono.config.tcp_host = host
|
194
|
-
Propono.config.tcp_port = port
|
195
|
-
topic_id = "my-fav-topic"
|
196
|
-
message = "foobar"
|
197
|
-
TCPSocket.expects(:new).with(host, port)
|
198
|
-
|
199
|
-
publisher = Publisher.new(topic_id, message)
|
200
|
-
publisher.send(:publish_via_tcp)
|
201
|
-
end
|
202
|
-
|
203
|
-
def test_exception_from_tcpsocket_caught_and_logged
|
204
|
-
host = "http://meducation.net"
|
205
|
-
port = 1234
|
206
|
-
Propono.config.tcp_host = host
|
207
|
-
Propono.config.tcp_port = port
|
208
|
-
|
209
|
-
publisher = Publisher.new("topic_id", "message")
|
210
|
-
publisher.stubs(id: '123asd')
|
211
|
-
Propono.config.logger.expects(:error).with() {|x| x =~ /^Propono \[123asd\]: Failed to send : getaddrinfo:.*/}
|
212
|
-
publisher.send(:publish_via_tcp)
|
213
|
-
end
|
214
|
-
|
215
118
|
def test_publish_should_raise_exception_if_topic_is_nil
|
216
119
|
assert_raises(PublisherError, "Topic is nil") do
|
217
|
-
Publisher.publish(nil, "foobar")
|
120
|
+
Publisher.publish(aws_client, propono_config, nil, "foobar")
|
218
121
|
end
|
219
122
|
end
|
220
123
|
|
221
124
|
def test_publish_should_raise_exception_if_message_is_nil
|
222
125
|
assert_raises(PublisherError, "Message is nil") do
|
223
|
-
Publisher.publish("foobar", nil)
|
126
|
+
Publisher.publish(aws_client, propono_config, "foobar", nil)
|
224
127
|
end
|
225
128
|
end
|
226
129
|
|
227
130
|
def test_publish_can_be_called_syncronously
|
228
|
-
publisher = Publisher.new("
|
229
|
-
publisher.expects(:
|
230
|
-
publisher.expects(:
|
231
|
-
publisher.
|
131
|
+
publisher = Publisher.new(aws_client, propono_config, "topic_name", "message", async: true)
|
132
|
+
publisher.expects(:publish_syncronously).never
|
133
|
+
publisher.expects(:publish_asyncronously).once
|
134
|
+
publisher.publish
|
232
135
|
end
|
233
136
|
|
234
|
-
def
|
235
|
-
publisher = Publisher.new("
|
236
|
-
publisher.expects(:
|
237
|
-
publisher.
|
137
|
+
def test_publish_is_normally_called_syncronously
|
138
|
+
publisher = Publisher.new(aws_client, propono_config, "topic_name", "message")
|
139
|
+
publisher.expects(:publish_syncronously)
|
140
|
+
publisher.publish
|
238
141
|
end
|
239
142
|
end
|
240
143
|
end
|