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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +2 -9
  4. data/CHANGELOG.md +9 -0
  5. data/Gemfile +0 -2
  6. data/README.md +35 -91
  7. data/lib/propono.rb +4 -144
  8. data/lib/propono/components/aws_client.rb +78 -0
  9. data/lib/propono/components/aws_config.rb +4 -9
  10. data/lib/propono/components/client.rb +93 -0
  11. data/lib/propono/components/queue.rb +4 -6
  12. data/lib/propono/components/queue_subscription.rb +32 -22
  13. data/lib/propono/components/sqs_message.rb +3 -6
  14. data/lib/propono/components/topic.rb +6 -5
  15. data/lib/propono/configuration.rb +0 -2
  16. data/lib/propono/services/publisher.rb +21 -44
  17. data/lib/propono/services/queue_listener.rb +54 -57
  18. data/lib/propono/version.rb +1 -1
  19. data/propono.gemspec +3 -2
  20. data/test/components/aws_config_test.rb +4 -4
  21. data/test/components/client_test.rb +68 -0
  22. data/test/components/queue_subscription_test.rb +68 -70
  23. data/test/components/queue_test.rb +6 -3
  24. data/test/components/topic_test.rb +4 -2
  25. data/test/configuration_test.rb +27 -55
  26. data/test/integration/integration_test.rb +4 -7
  27. data/test/integration/slow_queue_test.rb +11 -8
  28. data/test/integration/sns_to_sqs_test.rb +17 -17
  29. data/test/services/publisher_test.rb +59 -156
  30. data/test/services/queue_listener_test.rb +96 -103
  31. data/test/test_helper.rb +21 -48
  32. metadata +26 -39
  33. data/lib/propono/components/post_subscription.rb +0 -19
  34. data/lib/propono/components/sns.rb +0 -11
  35. data/lib/propono/components/sqs.rb +0 -12
  36. data/lib/propono/services/queue_creator.rb +0 -29
  37. data/lib/propono/services/subscriber.rb +0 -12
  38. data/lib/propono/services/tcp_listener.rb +0 -48
  39. data/lib/propono/services/topic_creator.rb +0 -23
  40. data/lib/propono/services/udp_listener.rb +0 -52
  41. data/test/components/post_subscription_test.rb +0 -29
  42. data/test/components/sns_test.rb +0 -25
  43. data/test/components/sqs_test.rb +0 -26
  44. data/test/integration/tcp_to_sqs_test.rb +0 -53
  45. data/test/integration/udp_proxy_test.rb +0 -50
  46. data/test/integration/udp_to_sqs_test.rb +0 -53
  47. data/test/propono_test.rb +0 -83
  48. data/test/services/queue_creator_test.rb +0 -61
  49. data/test/services/subscriber_test.rb +0 -21
  50. data/test/services/tcp_listener_test.rb +0 -76
  51. data/test/services/topic_creator_test.rb +0 -40
  52. 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.config do |config|
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
- 200.times do |x|
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
- Propono.drain_queue(slow_topic)
15
- Propono.drain_queue(topic)
16
- Propono.subscribe_by_queue(topic)
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
- Propono.listen_to_queue(topic) do |message, context|
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
- Propono.publish(slow_topic, slow_text, async: false)
42
- Propono.publish(topic, text, async: false)
43
- flunks << "Test Timeout" unless wait_for_thread(thread)
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
- # thread.terminate
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
- Propono.drain_queue(topic)
12
- Propono.subscribe_by_queue(topic)
11
+ propono_client.drain_queue(topic)
12
+ propono_client.subscribe(topic)
13
13
 
14
14
  thread = Thread.new do
15
15
  begin
16
- Propono.listen_to_queue(topic) do |message, context|
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
- Propono.publish(topic, text)
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 = "test-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
- Propono.subscribe_by_queue(topic)
51
+ propono_client.drain_queue(topic)
52
+ propono_client.subscribe(topic)
53
53
 
54
54
  thread = Thread.new do
55
55
  begin
56
- Propono.listen_to_queue(topic) do |message, context|
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
- failure_listener = Thread.new do
66
+ failure_thread = Thread.new do
67
67
  begin
68
- Propono.listen_to_queue(topic, channel: :failed) do |message, context|
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
- failure_listener.terminate
86
+ failure_thread.terminate
85
87
  end
86
88
 
87
89
  sleep(1) # Make sure the listener has started
88
90
 
89
- Propono.publish(topic, text)
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, {}).returns(mock(publish: nil))
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
- publisher = Publisher.new('x','y', id: id)
26
- assert publisher.id =~ Regexp.new("^#{id}-[a-z0-9]{6}$")
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(:publish_via_sns)
43
- Propono.config.logger.expects(:info).with {|x| x =~ /^Propono \[abc\]: Publishing bar to foo via sns.*/}
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 test_publish_via_sns_should_call_sns_on_correct_topic_and_message
60
- topic = "topic123"
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 = Topic.new(topic_arn)
51
+ topic.stubs(arn: topic_arn)
65
52
 
66
- TopicCreator.stubs(find_or_create: topic)
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
- sns = mock()
69
- sns.expects(:publish).with(topic_arn, {id: id, message: message}.to_json)
70
- publisher = Publisher.new(topic, message)
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 test_publish_via_sns_should_accept_a_hash_for_message
77
- topic = "topic123"
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 = Topic.new(topic_arn)
84
- TopicCreator.stubs(find_or_create: topic)
72
+ topic.stubs(topic_arn: topic_arn)
85
73
 
86
- sns = mock()
87
- sns.expects(:publish).with(topic_arn, body.to_json)
88
- publisher = Publisher.new(topic, message)
89
- publisher.stubs(id: id, sns: sns)
90
- thread = publisher.send(:publish_via_sns)
91
- thread.join
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 test_publish_via_sns_should_return_future_of_the_sns_response
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(:publish_via_sns).value
100
+ assert_same :response, publisher.send(:publish_syncronously).value
109
101
  end
110
102
 
111
- def test_publish_via_sns_should_propogate_exception_on_topic_creation_error
112
- TopicCreator.stubs(:find_or_create).raises(TopicCreatorError)
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(TopicCreatorError) do
115
- publisher = Publisher.new("topic", "message")
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("topic_id", "message", async: false)
229
- publisher.expects(:publish_via_sns_syncronously).once
230
- publisher.expects(:publish_via_sns_asyncronously).never
231
- publisher.send(:publish_via_sns)
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 test_publish_is_normally_called_asyncronously
235
- publisher = Publisher.new("topic_id", "message")
236
- publisher.expects(:publish_via_sns_asyncronously)
237
- publisher.send(:publish_via_sns)
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