propono 0.5.6 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -1
  4. data/CONTRIBUTING.md +10 -7
  5. data/README.md +102 -28
  6. data/Rakefile +10 -0
  7. data/lib/propono/components/queue_subscription.rb +1 -5
  8. data/lib/propono/components/sns.rb +3 -7
  9. data/lib/propono/components/sqs.rb +3 -7
  10. data/lib/propono/configuration.rb +4 -10
  11. data/lib/propono/logger.rb +19 -0
  12. data/lib/propono/propono_error.rb +7 -0
  13. data/lib/propono/services/publisher.rb +5 -8
  14. data/lib/propono/services/queue_creator.rb +1 -1
  15. data/lib/propono/services/queue_listener.rb +9 -10
  16. data/lib/propono/services/topic_creator.rb +1 -1
  17. data/lib/propono/services/udp_listener.rb +12 -14
  18. data/lib/propono/version.rb +1 -1
  19. data/lib/propono.rb +95 -11
  20. data/propono.gemspec +1 -0
  21. data/test/{post_subscription_test.rb → components/post_subscription_test.rb} +1 -1
  22. data/test/{queue_subscription_test.rb → components/queue_subscription_test.rb} +3 -3
  23. data/test/{queue_test.rb → components/queue_test.rb} +1 -1
  24. data/test/{sns_test.rb → components/sns_test.rb} +4 -10
  25. data/test/{sqs_test.rb → components/sqs_test.rb} +4 -10
  26. data/test/{topic_test.rb → components/topic_test.rb} +1 -1
  27. data/test/config.yml.example +4 -0
  28. data/test/configuration_test.rb +25 -22
  29. data/test/integration/integration_test.rb +31 -0
  30. data/test/integration/sns_to_sqs_test.rb +21 -0
  31. data/test/integration/udp_proxy_test.rb +27 -0
  32. data/test/integration/udp_to_sqs_test.rb +30 -0
  33. data/test/logger_test.rb +35 -0
  34. data/test/propono_test.rb +32 -11
  35. data/test/{publisher_test.rb → services/publisher_test.rb} +22 -9
  36. data/test/{queue_creator_test.rb → services/queue_creator_test.rb} +1 -1
  37. data/test/services/queue_listener_test.rb +90 -0
  38. data/test/{subscriber_test.rb → services/subscriber_test.rb} +1 -1
  39. data/test/{topic_creator_test.rb → services/topic_creator_test.rb} +1 -1
  40. data/test/{udp_listener.rb → services/udp_listener_test.rb} +23 -14
  41. data/test/test_helper.rb +10 -29
  42. metadata +55 -26
  43. data/test/queue_listener_test.rb +0 -119
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OTg5ZWEwODk0YTc2YWVmNDA4NTAxMDMwMjM2M2ZhNWI0NGFjMmFjMg==
4
+ ZGRiZTQ4MGVmZDFmM2IzZTFjYjY4MDZkZTVlMjRkMzMyZmJjMGI1MQ==
5
5
  data.tar.gz: !binary |-
6
- NjhlZjgyNDhlMTNmYWI2ODdjZTc5OTcyNmZlMzdiYmQ2M2NmZmVjMg==
6
+ NWYzZDE2YzEwMzk1YzJhZWIxY2QxNjE1NGU0NWViZDRkN2ZkNDk4YQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YTlmNzBhNGQ0NGM3OTMyMzZmMmRiYWVkNTZjMTRjZDRhM2MwY2VkZjdhZGZl
10
- ODU0MDJlNDk4MjE2YmQ4MTA4ZmRmOTEwNGFlZjJlZDE4OWIyOGZmYzlkODhl
11
- NGE5YzY0NTg5YThkZTM1NjQ0MjRjNTQ3NTViZjY4YzMzOTQ5YjE=
9
+ MWNiNzQxOWE3YzY5YjVjMjhkNzYzYmI1ODRiYzU4ZDI1YThlMjE5YmE4ZGUy
10
+ NDUwZmY1NDE2ZGJjODNmZjE1Yzg1OWY1YzhjM2QyOTVmMDI2M2FlZmY0OGY4
11
+ ODI2NzRlN2RmYTkzMTg0ZjljMWM3Y2ZjYThmZGNjOGM2NTJjY2M=
12
12
  data.tar.gz: !binary |-
13
- OWEyZWZjNDRjYzdjNTExYTk5NzI1M2U0NmI3OTdiYmI3ZGU0MmFiOThmZGVj
14
- MmNlODQyZDNiMWFhZDQwNjljOGEwZjJiOWIzZGY5Njc2Y2JkZDY0NDc0ODE0
15
- NWM1N2E0YWQzOWFlY2U5N2QwNTg4MmJkZmZlMDliYzQyYWM5NGM=
13
+ NzM4MjUwMzAzM2I5M2EyNjkxZDIyZjYzOGY5YmViYzJlODEwMjQwODNlZTdk
14
+ NjJjOTRjMjNjNDNmZTVjNWFlMDc2ZGU1ODVhNjI1YjgxMDMzNzllMDNkOGE2
15
+ ZTM0YTIzMTExNzMwYTA0NDNlNzUxMTJiNzNmY2IyMTc1NWYxYzg=
data/.gitignore CHANGED
@@ -14,5 +14,6 @@ rdoc
14
14
  spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
+ test/config.yml
17
18
  tmp
18
19
  *.swp
data/.travis.yml CHANGED
@@ -2,7 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 2.0.0
4
4
  script:
5
- - rake test
5
+ - bundle exec rake test:local
6
6
  addons:
7
7
  code_climate:
8
8
  repo_token: 88dd239bc2e0010742a42a4e0234b4decd19b46d0e9d3408d8b1fe0f96dd8fc1
data/CONTRIBUTING.md CHANGED
@@ -9,19 +9,22 @@ Please file issues on the [GitHub issues list](https://github.com/meducation/pro
9
9
 
10
10
  If you want a feature implemented, the best way to get it done is to submit a pull request that implements it. Please make sure it has tests.
11
11
 
12
- You can run the tests with
12
+ To get the implementation tests to run, you'll need to create a `test/config.yml` file. There's an example to get you started.
13
+
14
+ You can run the tests with:
15
+
13
16
  ```
14
- rake test
17
+ bundle exec rake test
15
18
  ```
16
19
 
17
20
  If you've not contributed to a repository before - this is the accepted pattern to use:
18
21
 
19
- 1. Fork it
22
+ 1. Fork it (big button on Github at the top right)
20
23
  2. Create your feature branch (`git checkout -b my-new-feature`)
21
- 3. Commit your changes (`git commit -am 'Add some feature'`)
22
- 4. Push to the branch (`git push origin my-new-feature`)
23
- 5. Create new Pull Request
24
+ 3. Make your changes (please add tests!)
25
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
26
+ 5. Push to the branch (`git push origin my-new-feature`)
27
+ 6. Create new Pull Request on Github
24
28
 
25
29
  Thank you again!
26
30
  :heart: :sparkling_heart: :heart:
27
-
data/README.md CHANGED
@@ -4,54 +4,128 @@
4
4
  [![Dependencies](https://gemnasium.com/meducation/propono.png?travis)](https://gemnasium.com/meducation/propono)
5
5
  [![Code Climate](https://codeclimate.com/github/meducation/propono.png)](https://codeclimate.com/github/meducation/propono)
6
6
 
7
+ Propono is a [pub/sub](http://en.wikipedia.org/wiki/Publish-subscribe_pattern) gem built on top of Amazon Web Services (AWS). It uses Simple Notification Service (SNS) and Simple Queue Service (SQS) to seamlessly pass messages throughout your infrastructure.
8
+
9
+ It's beautifully simple to use.
10
+
11
+ ```ruby
12
+ # On Machine A
13
+ Propono.listen_to_queue('some-topic') do |message|
14
+ puts "I just received: #{message}"
15
+ end
16
+
17
+ # On Machine B
18
+ Propono.publish('some-topic', "The Best Message Ever")
19
+
20
+ # Output on Machine A a second later.
21
+ # - "I just recieved The Best Message Ever"
22
+ ```
23
+
7
24
  ## Installation
8
25
 
9
26
  Add this line to your application's Gemfile:
10
27
 
11
28
  gem 'propono'
12
29
 
13
- If you want to use the latest version from Github, you can do:
30
+ And then execute:
31
+
32
+ $ bundle install
14
33
 
15
- gem 'propono', github: "meducation/propono"
34
+ ## Usage
16
35
 
17
- And then execute:
36
+ The first thing to do is setup some configuration keys for Propono. It's best to do this in an initializer, or at the start of your application.
37
+
38
+ ```ruby
39
+ Propono.config.access_key = "access-key" # From AWS
40
+ Propono.config.secret_key = "secret-key" # From AWS
41
+ Propono.config.queue_region = "queue-region" # From AWS
42
+ ```
43
+
44
+ You can then start publishing messages easily from anywhere in your codebase.
45
+
46
+ ```ruby
47
+ Propono.publish('some-topic', "Some string")
48
+ Propono.publish('some-topic', {some: ['hash', 'or', 'array']})
49
+ ```
50
+
51
+ Listening for messages is easy too. Just tell Propono what your application is called and start listening. You'll get a block yieleded for each message.
52
+
53
+ ```ruby
54
+ Propono.config.application_name = "application-name" # Something unique to this app.
55
+ Propono.listen_to_queue('some-topic') do |message|
56
+ # ... Do something interesting with the message
57
+ end
58
+ ```
59
+ In the background, Propono is automatically setting up a queue using SQS, a notification system using SNS, and glueing them all together for you. But you don't have to worry about any of that.
60
+
61
+ ### Using UDP for messages
18
62
 
19
- $ bundle
63
+ If you want almost-zero performance impact, and don't mind the occasional message getting lost, you can use UDP. We use this for things like our live dashboard where we don't mind losing a piece of activity here and there, but any perforamnce impact on our Meducation itself is bad news.
20
64
 
21
- This script demonstrates usage:
65
+ To send messages this way, you need to set up a little extra config:
22
66
 
23
67
  ```ruby
24
- require 'propono'
25
-
26
- class Toy
27
- def play
28
- configure
29
- make_fun_stuff_happen
30
- end
31
-
32
- private
33
- def make_fun_stuff_happen
34
- Propono.publish("jez-test-topic", "A test message")
35
- Propono.subscribe_by_queue("jez-test-topic")
36
- Propono.subscribe_by_post("jez-test-topic", 'http://example.com/endpoint')
37
- end
38
-
39
- def configure
40
- Propono.config.access_key = '...'
41
- Propono.config.secret_key = '...'
42
- Propono.config.queue_region = 'eu-west-1'
43
- Propono.config.application_name = '...'
44
- end
68
+ Propono.config.udp_host = "some.host.running.a.propono.listener"
69
+ Propono.config.udp_port = 12543
70
+ ```
71
+
72
+ You then simply pass the `:udp` protocol into `publish`
73
+
74
+ ```ruby
75
+ Propono.publish('some-topic', message, protocol: :udp)
76
+ ```
77
+
78
+ You'll now need another application running Propono to listen to the UDP feed. You can use the same machine or a different one, just make sure the port config is the same in both applications, and you're good to go.
79
+
80
+ ```ruby
81
+ Propono.listen_to_udp do |topic, message|
82
+ Propono.publish(topic, message) # Proxy the message to SNS
45
83
  end
84
+ ```
85
+
86
+ This proxying of UDP to SQS is used so often that there's a simple shortcut. Just run this on the machine receiving the UDP packets.
87
+
88
+ ```ruby
89
+ Propono.proxy_udp()
90
+ ```
91
+
92
+ ### Configuration
93
+
94
+ The following configuration settings are available:
46
95
 
47
- Toy.new.play
48
96
  ```
97
+ Propono.config do |config|
98
+ config.access_key = "An AWS access key"
99
+ config.secret_key = "A AWS secret key"
100
+ config.queue_region = "An AWS queue region"
101
+ config.application_name = "A name unique in your network"
102
+ config.udp_host = "The host of a machine used for UDP proxying"
103
+ config.udp_port = "The host of a machine used for UDP proxying"
104
+ config.logger = "A logger such as Log4r or Rails.logger"
105
+ end
106
+ ```
107
+
108
+ The can all also be setting using the `Propono.config.access_key = "..."` syntax.
109
+
110
+ ### Is it any good?
111
+
112
+ [Yes.](http://news.ycombinator.com/item?id=3067434)
49
113
 
50
114
  ## Contributing
51
115
 
52
116
  Firstly, thank you!! :heart::sparkling_heart::heart:
53
117
 
54
- Please read our [contributing guide](https://github.com/meducation/propono/tree/master/CONTRIBUTING.md) for information on how to get stuck in.
118
+ We'd love to have you involved. Please read our [contributing guide](https://github.com/meducation/propono/tree/master/CONTRIBUTING.md) for information on how to get stuck in.
119
+
120
+ ### Contributors
121
+
122
+ This project is managed by the [Meducation team](http://company.meducation.net/about#team).
123
+
124
+ These individuals have come up with the ideas and written the code that made this possible:
125
+
126
+ - [Jeremy Walker](http://github.com/iHID)
127
+ - [Malcom Landon](http://github.com/malcyL)
128
+ - [Rob Styles](http://github.com/mmmmmrob)
55
129
 
56
130
  ## Licence
57
131
 
data/Rakefile CHANGED
@@ -1,8 +1,18 @@
1
1
  require "bundler/gem_tasks"
2
2
  require 'rake/testtask'
3
+ require 'yard'
4
+
5
+ YARD::Rake::YardocTask.new do |t|
6
+ end
3
7
 
4
8
  Rake::TestTask.new do |t|
5
9
  t.pattern = "test/**/*_test.rb"
6
10
  end
7
11
 
12
+ namespace :test do
13
+ Rake::TestTask.new(:local) do |t|
14
+ t.pattern = "test/{components/,services/,}*_test.rb"
15
+ end
16
+ end
17
+
8
18
  task default: :test
@@ -24,15 +24,11 @@ module Propono
24
24
  end
25
25
 
26
26
  def queue_name
27
- @queue_name ||= "#{config.application_name.gsub(" ", "_")}-#{@topic_id}"
27
+ @queue_name ||= "#{Propono.config.application_name.gsub(" ", "_")}-#{@topic_id}"
28
28
  end
29
29
 
30
30
  private
31
31
 
32
- def config
33
- Configuration.instance
34
- end
35
-
36
32
  def generate_policy
37
33
  <<-EOS
38
34
  {
@@ -6,14 +6,10 @@ module Propono
6
6
 
7
7
  def sns
8
8
  @sns ||= Fog::AWS::SNS.new(
9
- :aws_access_key_id => config.access_key,
10
- :aws_secret_access_key => config.secret_key,
11
- :region => config.queue_region
9
+ :aws_access_key_id => Propono.config.access_key,
10
+ :aws_secret_access_key => Propono.config.secret_key,
11
+ :region => Propono.config.queue_region
12
12
  )
13
13
  end
14
-
15
- def config
16
- Configuration.instance
17
- end
18
14
  end
19
15
  end
@@ -6,15 +6,11 @@ module Propono
6
6
 
7
7
  def sqs
8
8
  @sqs ||= Fog::AWS::SQS.new(
9
- :aws_access_key_id => config.access_key,
10
- :aws_secret_access_key => config.secret_key,
11
- :region => config.queue_region
9
+ :aws_access_key_id => Propono.config.access_key,
10
+ :aws_secret_access_key => Propono.config.secret_key,
11
+ :region => Propono.config.queue_region
12
12
  )
13
13
  end
14
-
15
- def config
16
- Configuration.instance
17
- end
18
14
  end
19
15
  end
20
16
 
@@ -1,12 +1,9 @@
1
- require 'singleton'
2
-
3
1
  module Propono
4
2
 
5
- class ConfigurationError < Exception
3
+ class ProponoConfigurationError < ProponoError
6
4
  end
7
5
 
8
6
  class Configuration
9
- include Singleton
10
7
 
11
8
  SETTINGS = [
12
9
  :access_key, :secret_key, :queue_region,
@@ -17,7 +14,7 @@ module Propono
17
14
  attr_writer *SETTINGS
18
15
 
19
16
  def initialize
20
- self.logger = $stderr
17
+ self.logger = Propono::Logger.new
21
18
  end
22
19
 
23
20
  SETTINGS.each do |setting|
@@ -29,11 +26,8 @@ module Propono
29
26
  private
30
27
 
31
28
  def get_or_raise(setting)
32
- if val = instance_variable_get("@#{setting.to_s}")
33
- val
34
- else
35
- raise ConfigurationError.new("Configuration for #{setting} is not set")
36
- end
29
+ instance_variable_get("@#{setting.to_s}") ||
30
+ raise(ProponoConfigurationError.new("Configuration for #{setting} is not set"))
37
31
  end
38
32
  end
39
33
  end
@@ -0,0 +1,19 @@
1
+ module Propono
2
+ class Logger
3
+
4
+ StdLevels = %W{debug info warn}
5
+ ErrorLevels = %W{error fatal}
6
+
7
+ StdLevels.each do |level|
8
+ define_method level do |*args|
9
+ $stdout.puts *args
10
+ end
11
+ end
12
+
13
+ ErrorLevels.each do |level|
14
+ define_method level do |*args|
15
+ $stderr.puts *args
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ module Propono
2
+
3
+ # The exception from which all other exceptions in this library derive.
4
+ class ProponoError < StandardError
5
+ end
6
+
7
+ end
@@ -1,5 +1,5 @@
1
1
  module Propono
2
- class PublisherError < Exception
2
+ class PublisherError < ProponoError
3
3
  end
4
4
 
5
5
  class Publisher
@@ -28,18 +28,15 @@ module Propono
28
28
 
29
29
  def publish_via_sns
30
30
  topic = TopicCreator.find_or_create(topic_id)
31
- sns.publish(topic.arn, message)
31
+ msg = message.is_a?(String) ? message : message.to_json
32
+ sns.publish(topic.arn, msg)
32
33
  end
33
34
 
34
35
  def publish_via_udp
35
36
  payload = {topic: topic_id, message: message}.to_json
36
- UDPSocket.new.send(payload, 0, config.udp_host, config.udp_port)
37
+ UDPSocket.new.send(payload, 0, Propono.config.udp_host, Propono.config.udp_port)
37
38
  rescue SocketError => e
38
- config.logger.puts "Udp2sqs failed to send : #{e}"
39
- end
40
-
41
- def config
42
- Configuration.instance
39
+ Propono.config.logger.error "Propono failed to send : #{e}"
43
40
  end
44
41
  end
45
42
  end
@@ -1,5 +1,5 @@
1
1
  module Propono
2
- class QueueCreatorError < Exception
2
+ class QueueCreatorError < ProponoError
3
3
  end
4
4
 
5
5
  class QueueCreator
@@ -23,24 +23,23 @@ module Propono
23
23
  private
24
24
 
25
25
  def read_messages
26
- response = sqs.receive_message( queue_url, options = { 'MaxNumberOfMessages' => 10 } )
26
+ #response = sqs.receive_message( queue_url, options = { 'MaxNumberOfMessages' => 10 } )
27
+ response = sqs.receive_message( queue_url, {'MaxNumberOfMessages' => 10} )
27
28
  messages = response.body['Message']
28
29
  if messages.empty?
29
30
  false
30
31
  else
31
- process_messages(messages)
32
+ messages.each { |msg| process_sqs_message(msg) }
32
33
  end
33
34
  rescue
34
- config.logger.puts "Unexpected error reading from queue #{queue_url}"
35
- config.logger.puts $!
35
+ Propono.config.logger.error "Unexpected error reading from queue #{queue_url}"
36
+ Propono.config.logger.error $!
36
37
  end
37
38
 
38
- def process_messages(messages)
39
- messages.each do |message|
40
- @message_processor.call(message)
41
- sqs.delete_message(queue_url, message['ReceiptHandle'])
42
- end
43
- true
39
+ def process_sqs_message(sqs_message)
40
+ message = JSON.parse(sqs_message["Body"])["Message"]
41
+ @message_processor.call(message)
42
+ sqs.delete_message(queue_url, sqs_message['ReceiptHandle'])
44
43
  end
45
44
 
46
45
  def queue_url
@@ -1,5 +1,5 @@
1
1
  module Propono
2
- class TopicCreatorError < Exception
2
+ class TopicCreatorError < ProponoError
3
3
  end
4
4
 
5
5
  class TopicCreator
@@ -1,17 +1,15 @@
1
1
  module Propono
2
- class UdpListenerError < StandardError
2
+ class UdpListenerError < ProponoError
3
3
  end
4
4
 
5
5
  class UdpListener
6
6
 
7
- def self.listen(host, port, &processor)
8
- new(host, port, &processor).listen
7
+ def self.listen(&processor)
8
+ new(&processor).listen
9
9
  end
10
10
 
11
- def initialize(host, port, &processor)
11
+ def initialize(&processor)
12
12
  raise UdpListenerError.new("Please provide a block to call for each message") unless block_given?
13
- @host = host
14
- @port = port
15
13
  @processor = processor
16
14
  end
17
15
 
@@ -22,22 +20,22 @@ module Propono
22
20
  private
23
21
 
24
22
  def receive_and_process
25
- text = socket.recvfrom(1024)[0]
26
- Thread.new { @processor.call(text) }
23
+ udp_data = socket.recvfrom(1024)[0]
24
+ Thread.new { process_udp_data(udp_data) }
25
+ end
26
+
27
+ def process_udp_data(udp_data)
28
+ json = JSON.parse(udp_data)
29
+ @processor.call(json['topic'], json['message'])
27
30
  end
28
31
 
29
32
  def socket
30
33
  @socket ||= begin
31
34
  socket = UDPSocket.new
32
- socket.bind(@host, @port)
35
+ socket.bind(Propono.config.udp_host, Propono.config.udp_port)
33
36
  socket
34
37
  end
35
38
  end
36
-
37
- def config
38
- Configuration.instance
39
- end
40
-
41
39
  end
42
40
  end
43
41
 
@@ -1,3 +1,3 @@
1
1
  module Propono
2
- VERSION = "0.5.6"
2
+ VERSION = "0.6.0"
3
3
  end
data/lib/propono.rb CHANGED
@@ -1,5 +1,12 @@
1
+ # Propono
2
+ #
3
+ # Propono is a pub/sub gem built on top of Amazon Web Services (AWS). It uses Simple Notification Service (SNS) and Simple Queue Service (SQS) to seamlessly pass messages throughout your infrastructure.
4
+
1
5
  require "propono/version"
6
+ require 'propono/propono_error'
7
+ require 'propono/logger'
2
8
  require 'propono/configuration'
9
+
3
10
  require 'propono/components/sns'
4
11
  require 'propono/components/sqs'
5
12
  require "propono/components/queue"
@@ -14,28 +21,105 @@ require "propono/services/subscriber"
14
21
  require "propono/services/topic_creator"
15
22
  require "propono/services/udp_listener"
16
23
 
24
+ # Propono is a pub/sub gem built on top of Amazon Web Services (AWS).
25
+ # It uses Simple Notification Service (SNS) and Simple Queue Service (SQS)
26
+ # to seamlessly pass messages throughout your infrastructure.
17
27
  module Propono
28
+
29
+ # Propono configuration settings.
30
+ #
31
+ # Settings should be set in an initializer or using some
32
+ # other method that insures they are set before any
33
+ # Propono code is used. They can be set as followed:
34
+ #
35
+ # Propono.config.access_key = "my-access-key"
36
+ #
37
+ # The following settings are allowed:
38
+ #
39
+ # * <tt>:access_key</tt> - The AWS access key
40
+ # * <tt>:secret_key</tt> - The AWS secret key
41
+ # * <tt>:queue_region</tt> - The AWS region
42
+ # * <tt>:application_name</tt> - The name of the application Propono
43
+ # is included in.
44
+ # * <tt>:udp_host</tt> - If using UDP, the host to send to.
45
+ # * <tt>:udp_port</tt> - If using UDP, the port to send to.
46
+ # * <tt>:logger</tt> - A logger object that responds to puts.
18
47
  def self.config
19
- Configuration.instance
48
+ @config ||= Configuration.new
49
+ if block_given?
50
+ yield @config
51
+ else
52
+ @config
53
+ end
54
+ end
55
+
56
+ # Publishes a new message into the Propono pub/sub network.
57
+ #
58
+ # This requires a topic and a message. By default this pushes
59
+ # out AWS SNS. The method optionally takes a :protocol key in
60
+ # options, which can be set to :udp for non-guaranteed but very
61
+ # fast delivery.
62
+ #
63
+ # @param [String] topic The name of the topic to publish to.
64
+ # @param [String] message The message to post.
65
+ # @param [Hash] options
66
+ # * protocol: :udp
67
+ def self.publish(topic, message, options = {})
68
+ Publisher.publish(topic, message, options)
20
69
  end
21
70
 
22
- def self.publish(*args)
23
- Publisher.publish(*args)
71
+ # Creates a new SNS-SQS subscription on the specified topic.
72
+ #
73
+ # This is implicitly called by {#listen_to_queue}.
74
+ #
75
+ # @param [String] topic The name of the topic to subscribe to.
76
+ def self.subscribe_by_queue(topic)
77
+ Subscriber.subscribe_by_queue(topic)
24
78
  end
25
79
 
26
- def self.subscribe_by_queue(*args)
27
- Subscriber.subscribe_by_queue(*args)
80
+ # Creates a new SNS-POST subscription on the specified topic.
81
+ #
82
+ # The POST currently needs confirming before the subscription
83
+ # can be published to.
84
+ #
85
+ # @param [String] topic The name of the topic to subscribe to.
86
+ def self.subscribe_by_post(topic, endpoint)
87
+ Subscriber.subscribe_by_post(topic, endpoint)
28
88
  end
29
89
 
30
- def self.subscribe_by_post(*args)
31
- Subscriber.subscribe_by_post(*args)
90
+ # Listens on a queue and yields for each message
91
+ #
92
+ # Calling this will enter a queue-listening loop that
93
+ # yields the message_processor for each messages.
94
+ #
95
+ # This method will automatically create a subscription if
96
+ # one does not exist, so there is no need to call
97
+ # <tt>subscribe_by_queue</tt> in addition.
98
+ #
99
+ # @param [String] topic The topic to subscribe to.
100
+ # @param &message_processor The block to yield for each message.
101
+ def self.listen_to_queue(topic, &message_processor)
102
+ QueueListener.listen(topic, &message_processor)
32
103
  end
33
104
 
34
- def self.listen_to_queue(*args, &block)
35
- QueueListener.listen(*args, &block)
105
+ # Listens for UDP messages and yields for each.
106
+ #
107
+ # Calling this will enter a queue-listening loop that
108
+ # yields the message_processor for each UDP message received.
109
+ #
110
+ # @param &message_processor The block to yield for each message.
111
+ # Is called with <tt>|topic, message|</tt>.
112
+ def self.listen_to_udp(&message_processor)
113
+ UdpListener.listen(&message_processor)
36
114
  end
37
115
 
38
- def self.listen_to_udp(*args, &block)
39
- UdpListener.listen(*args, &block)
116
+ # Listens for UDP messages and passes them onto the queue.
117
+ #
118
+ # This method uses #listen_to_udp and #publish to proxy
119
+ # messages from UDP onto the queue.
120
+ def self.proxy_udp
121
+ Propono.listen_to_udp do |topic, message|
122
+ Propono.publish(topic, message)
123
+ end
40
124
  end
41
125
  end
data/propono.gemspec CHANGED
@@ -23,5 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
24
  spec.add_development_dependency "rake"
25
25
  spec.add_development_dependency "mocha"
26
+ spec.add_development_dependency "yard"
26
27
  spec.add_development_dependency "minitest", "~> 5.0.8"
27
28
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path('../test_helper', __FILE__)
1
+ require File.expand_path('../../test_helper', __FILE__)
2
2
 
3
3
  module Propono
4
4
  class PostSubscriptionTest < Minitest::Test