propono 0.5.6 → 0.6.0

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 (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