rabbit_feed 0.3.1

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 (145) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/Brewfile +4 -0
  5. data/DEVELOPING.md +140 -0
  6. data/Gemfile +15 -0
  7. data/Gemfile.lock +121 -0
  8. data/LICENSE.txt +9 -0
  9. data/README.md +304 -0
  10. data/Rakefile +30 -0
  11. data/bin/bundle +3 -0
  12. data/bin/rabbit_feed +11 -0
  13. data/example/non_rails_app/.rspec +1 -0
  14. data/example/non_rails_app/Gemfile +7 -0
  15. data/example/non_rails_app/Gemfile.lock +56 -0
  16. data/example/non_rails_app/Rakefile +5 -0
  17. data/example/non_rails_app/bin/benchmark +63 -0
  18. data/example/non_rails_app/bin/bundle +3 -0
  19. data/example/non_rails_app/config/rabbit_feed.yml +8 -0
  20. data/example/non_rails_app/lib/non_rails_app.rb +32 -0
  21. data/example/non_rails_app/lib/non_rails_app/event_handler.rb +10 -0
  22. data/example/non_rails_app/log/.keep +0 -0
  23. data/example/non_rails_app/spec/lib/non_rails_app/event_handler_spec.rb +14 -0
  24. data/example/non_rails_app/spec/lib/non_rails_app/event_routing_spec.rb +14 -0
  25. data/example/non_rails_app/spec/spec_helper.rb +31 -0
  26. data/example/non_rails_app/tmp/pids/.keep +0 -0
  27. data/example/rails_app/.gitignore +17 -0
  28. data/example/rails_app/.node-version +1 -0
  29. data/example/rails_app/.rspec +1 -0
  30. data/example/rails_app/Gemfile +36 -0
  31. data/example/rails_app/Gemfile.lock +173 -0
  32. data/example/rails_app/README.rdoc +28 -0
  33. data/example/rails_app/Rakefile +6 -0
  34. data/example/rails_app/app/assets/images/.keep +0 -0
  35. data/example/rails_app/app/assets/javascripts/application.js +16 -0
  36. data/example/rails_app/app/assets/javascripts/beavers.js.coffee +3 -0
  37. data/example/rails_app/app/assets/stylesheets/application.css +15 -0
  38. data/example/rails_app/app/assets/stylesheets/beavers.css.scss +3 -0
  39. data/example/rails_app/app/assets/stylesheets/scaffolds.css.scss +69 -0
  40. data/example/rails_app/app/controllers/application_controller.rb +5 -0
  41. data/example/rails_app/app/controllers/beavers_controller.rb +81 -0
  42. data/example/rails_app/app/controllers/concerns/.keep +0 -0
  43. data/example/rails_app/app/helpers/application_helper.rb +2 -0
  44. data/example/rails_app/app/helpers/beavers_helper.rb +2 -0
  45. data/example/rails_app/app/mailers/.keep +0 -0
  46. data/example/rails_app/app/models/.keep +0 -0
  47. data/example/rails_app/app/models/beaver.rb +2 -0
  48. data/example/rails_app/app/models/concerns/.keep +0 -0
  49. data/example/rails_app/app/views/beavers/_form.html.erb +21 -0
  50. data/example/rails_app/app/views/beavers/edit.html.erb +6 -0
  51. data/example/rails_app/app/views/beavers/index.html.erb +25 -0
  52. data/example/rails_app/app/views/beavers/index.json.jbuilder +4 -0
  53. data/example/rails_app/app/views/beavers/new.html.erb +5 -0
  54. data/example/rails_app/app/views/beavers/show.html.erb +9 -0
  55. data/example/rails_app/app/views/beavers/show.json.jbuilder +1 -0
  56. data/example/rails_app/app/views/layouts/application.html.erb +14 -0
  57. data/example/rails_app/bin/bundle +3 -0
  58. data/example/rails_app/bin/rails +4 -0
  59. data/example/rails_app/bin/rake +4 -0
  60. data/example/rails_app/config.ru +4 -0
  61. data/example/rails_app/config/application.rb +25 -0
  62. data/example/rails_app/config/boot.rb +4 -0
  63. data/example/rails_app/config/database.yml +22 -0
  64. data/example/rails_app/config/environment.rb +5 -0
  65. data/example/rails_app/config/environments/development.rb +83 -0
  66. data/example/rails_app/config/environments/test.rb +39 -0
  67. data/example/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  68. data/example/rails_app/config/initializers/cookies_serializer.rb +3 -0
  69. data/example/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
  70. data/example/rails_app/config/initializers/inflections.rb +16 -0
  71. data/example/rails_app/config/initializers/mime_types.rb +4 -0
  72. data/example/rails_app/config/initializers/rabbit_feed.rb +43 -0
  73. data/example/rails_app/config/initializers/session_store.rb +3 -0
  74. data/example/rails_app/config/initializers/wrap_parameters.rb +14 -0
  75. data/example/rails_app/config/locales/en.yml +23 -0
  76. data/example/rails_app/config/rabbit_feed.yml +8 -0
  77. data/example/rails_app/config/routes.rb +58 -0
  78. data/example/rails_app/config/secrets.yml +18 -0
  79. data/example/rails_app/config/unicorn.rb +4 -0
  80. data/example/rails_app/db/migrate/20140424102400_create_beavers.rb +9 -0
  81. data/example/rails_app/db/schema.rb +22 -0
  82. data/example/rails_app/db/seeds.rb +7 -0
  83. data/example/rails_app/lib/assets/.keep +0 -0
  84. data/example/rails_app/lib/event_handler.rb +7 -0
  85. data/example/rails_app/lib/tasks/.keep +0 -0
  86. data/example/rails_app/log/.keep +0 -0
  87. data/example/rails_app/public/404.html +67 -0
  88. data/example/rails_app/public/422.html +67 -0
  89. data/example/rails_app/public/500.html +66 -0
  90. data/example/rails_app/public/favicon.ico +0 -0
  91. data/example/rails_app/public/robots.txt +5 -0
  92. data/example/rails_app/spec/controllers/beavers_controller_spec.rb +32 -0
  93. data/example/rails_app/spec/event_routing_spec.rb +15 -0
  94. data/example/rails_app/spec/spec_helper.rb +51 -0
  95. data/example/rails_app/test/controllers/.keep +0 -0
  96. data/example/rails_app/test/controllers/beavers_controller_test.rb +49 -0
  97. data/example/rails_app/test/fixtures/.keep +0 -0
  98. data/example/rails_app/test/fixtures/beavers.yml +7 -0
  99. data/example/rails_app/test/helpers/.keep +0 -0
  100. data/example/rails_app/test/helpers/beavers_helper_test.rb +4 -0
  101. data/example/rails_app/test/integration/.keep +0 -0
  102. data/example/rails_app/test/mailers/.keep +0 -0
  103. data/example/rails_app/test/models/.keep +0 -0
  104. data/example/rails_app/test/models/beaver_test.rb +7 -0
  105. data/example/rails_app/test/test_helper.rb +13 -0
  106. data/example/rails_app/tmp/pids/.keep +0 -0
  107. data/example/rails_app/vendor/assets/javascripts/.keep +0 -0
  108. data/example/rails_app/vendor/assets/stylesheets/.keep +0 -0
  109. data/lib/dsl.rb +9 -0
  110. data/lib/rabbit_feed.rb +41 -0
  111. data/lib/rabbit_feed/client.rb +181 -0
  112. data/lib/rabbit_feed/configuration.rb +50 -0
  113. data/lib/rabbit_feed/connection_concern.rb +95 -0
  114. data/lib/rabbit_feed/consumer.rb +14 -0
  115. data/lib/rabbit_feed/consumer_connection.rb +108 -0
  116. data/lib/rabbit_feed/event.rb +43 -0
  117. data/lib/rabbit_feed/event_definitions.rb +98 -0
  118. data/lib/rabbit_feed/event_routing.rb +90 -0
  119. data/lib/rabbit_feed/producer.rb +47 -0
  120. data/lib/rabbit_feed/producer_connection.rb +65 -0
  121. data/lib/rabbit_feed/testing_support/rspec_matchers/publish_event.rb +90 -0
  122. data/lib/rabbit_feed/testing_support/testing_helpers.rb +16 -0
  123. data/lib/rabbit_feed/version.rb +3 -0
  124. data/logo.png +0 -0
  125. data/rabbit_feed.gemspec +35 -0
  126. data/run_benchmark +35 -0
  127. data/run_example +62 -0
  128. data/run_recovery_test +26 -0
  129. data/spec/features/connectivity.feature +13 -0
  130. data/spec/features/step_definitions/connectivity_steps.rb +96 -0
  131. data/spec/fixtures/configuration.yml +14 -0
  132. data/spec/lib/rabbit_feed/client_spec.rb +116 -0
  133. data/spec/lib/rabbit_feed/configuration_spec.rb +121 -0
  134. data/spec/lib/rabbit_feed/connection_concern_spec.rb +116 -0
  135. data/spec/lib/rabbit_feed/consumer_connection_spec.rb +85 -0
  136. data/spec/lib/rabbit_feed/event_definitions_spec.rb +139 -0
  137. data/spec/lib/rabbit_feed/event_routing_spec.rb +121 -0
  138. data/spec/lib/rabbit_feed/event_spec.rb +33 -0
  139. data/spec/lib/rabbit_feed/producer_connection_spec.rb +72 -0
  140. data/spec/lib/rabbit_feed/producer_spec.rb +57 -0
  141. data/spec/lib/rabbit_feed/testing_support/rspec_matchers/publish_event_spec.rb +60 -0
  142. data/spec/lib/rabbit_feed/testing_support/testing_helper_spec.rb +34 -0
  143. data/spec/spec_helper.rb +58 -0
  144. data/spec/support/shared_examples_for_connections.rb +40 -0
  145. metadata +305 -0
@@ -0,0 +1,47 @@
1
+ module RabbitFeed
2
+ module Producer
3
+ extend self
4
+
5
+ attr_accessor :event_definitions
6
+
7
+ def publish_event name, payload
8
+ raise (Error.new 'Unable to publish event. No event definitions set.') unless event_definitions.present?
9
+ event_definition = event_definitions[name] or raise (Error.new "definition for event: #{name} not found")
10
+ timestamp = Time.now.utc
11
+ payload = (enriched_payload payload, event_definition.version, name, timestamp)
12
+ event = Event.new event_definition.schema, payload
13
+ ProducerConnection.publish event.serialize, (options name, timestamp)
14
+ event
15
+ end
16
+
17
+ def stub!
18
+ ProducerConnection.stub(:publish)
19
+ end
20
+
21
+ private
22
+
23
+ def enriched_payload payload, version, name, timestamp
24
+ payload.merge ({
25
+ 'application' => RabbitFeed.configuration.application,
26
+ 'host' => Socket.gethostname,
27
+ 'environment' => RabbitFeed.environment,
28
+ 'created_at_utc' => timestamp.iso8601(6),
29
+ 'version' => version,
30
+ 'name' => name,
31
+ })
32
+ end
33
+
34
+ def routing_key event_name
35
+ "#{RabbitFeed.environment}.#{RabbitFeed.configuration.application}.#{event_name}"
36
+ end
37
+
38
+ def options event_name, timestamp
39
+ {
40
+ routing_key: (routing_key event_name),
41
+ type: event_name,
42
+ app_id: RabbitFeed.configuration.application,
43
+ timestamp: timestamp.to_i,
44
+ }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,65 @@
1
+ module RabbitFeed
2
+ class ProducerConnection
3
+ include ConnectionConcern
4
+
5
+ PUBLISH_OPTIONS = {
6
+ persistent: true, # Persist the message to disk
7
+ mandatory: true, # Return the message if it can't be routed to a queue
8
+ }.freeze
9
+
10
+ EXCHANGE_OPTIONS = {
11
+ type: :topic, # Allow wildcard routing keys
12
+ durable: true, # Persist across server restart
13
+ no_declare: false, # Create the exchange if it does not exist
14
+ }.freeze
15
+
16
+ attr_reader :exchange
17
+
18
+ def self.handle_returned_message return_info, content
19
+ RabbitFeed.log.error "Handling returned message on #{self.to_s} details: #{return_info}..."
20
+ RabbitFeed.exception_notify (ReturnedMessageError.new return_info)
21
+ end
22
+
23
+ def initialize channel
24
+ RabbitFeed.log.debug "Declaring exchange on #{self.to_s} (channel #{channel.id}) named: #{RabbitFeed.configuration.exchange} with options: #{exchange_options}..."
25
+ @exchange = channel.exchange RabbitFeed.configuration.exchange, exchange_options
26
+
27
+ exchange.on_return do |return_info, properties, content|
28
+ RabbitFeed::ProducerConnection.handle_returned_message return_info, content
29
+ end
30
+ end
31
+
32
+ def self.publish message, options
33
+ retry_on_closed_connection do
34
+ with_connection do |producer_connection|
35
+ retry_on_exception do
36
+ producer_connection.publish message, options
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def publish message, options
43
+ # It's critical to dup the options for the sake of retries, as bunny modifies this hash
44
+ bunny_options = (options.merge PUBLISH_OPTIONS)
45
+
46
+ RabbitFeed.log.debug "Publishing message on #{self.to_s} with options: #{options} to exchange: #{RabbitFeed.configuration.exchange}..."
47
+
48
+ exchange.publish message, bunny_options
49
+ end
50
+
51
+ private
52
+
53
+ def exchange_options
54
+ {
55
+ auto_delete: RabbitFeed.configuration.auto_delete_exchange,
56
+ }.merge EXCHANGE_OPTIONS
57
+ end
58
+
59
+ def self.connection_options
60
+ default_connection_options.merge({
61
+ threaded: false, # With threading enabled, there is a chance of losing an event during connection recovery
62
+ })
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,90 @@
1
+ module RabbitFeed
2
+ module TestingSupport
3
+ module RSpecMatchers
4
+ class PublishEvent
5
+ attr_reader :expected_event, :expected_payload, :received_events
6
+
7
+ def initialize(expected_event, expected_payload)
8
+ @expected_event = expected_event
9
+ @expected_payload = expected_payload
10
+ @received_events = []
11
+ stub_publish
12
+ end
13
+
14
+ def matches?(given_proc, negative_expectation = false)
15
+ unless given_proc.respond_to?(:call)
16
+ ::Kernel.warn "`publish_event` was called with non-proc object #{given_proc.inspect}"
17
+ return false
18
+ end
19
+
20
+ begin
21
+ given_proc.call
22
+ rescue
23
+ end
24
+
25
+ actual_event = received_events.detect do |event|
26
+ event.name == expected_event
27
+ end
28
+
29
+ received_expected_event = actual_event.present?
30
+
31
+ with_expected_payload = negative_expectation
32
+ if received_expected_event && !with_expected_payload
33
+ actual_payload = (strip_defaults_from actual_event.payload)
34
+ with_expected_payload = actual_payload == expected_payload
35
+ end
36
+
37
+ return received_expected_event && with_expected_payload
38
+ end
39
+
40
+ alias == matches?
41
+
42
+ def does_not_match?(given_proc)
43
+ !matches?(given_proc, :negative_expectation)
44
+ end
45
+
46
+ def failure_message
47
+ "expected #{expected_event} with #{expected_payload} but instead received #{received_events_message}"
48
+ end
49
+
50
+ def negative_failure_message
51
+ "expected no #{expected_event} event, but received one anyways"
52
+ end
53
+
54
+ alias failure_message_when_negated negative_failure_message
55
+
56
+ def description
57
+ "publish_event #{expected_event}"
58
+ end
59
+
60
+ private
61
+
62
+ def strip_defaults_from payload
63
+ payload.reject do |key, value|
64
+ ['application', 'host', 'environment', 'created_at_utc', 'version', 'name'].include? key
65
+ end
66
+ end
67
+
68
+ def received_events_message
69
+ if received_events.any?
70
+ received_events.map do |received_event|
71
+ "#{received_event.name} with #{strip_defaults_from received_event.payload}"
72
+ end
73
+ else
74
+ 'no events'
75
+ end
76
+ end
77
+
78
+ def stub_publish
79
+ ProducerConnection.stub(:publish) do |serialized_event, routing_key|
80
+ @received_events << (Event.deserialize serialized_event)
81
+ end
82
+ end
83
+ end
84
+
85
+ def publish_event(expected_event, expected_payload)
86
+ PublishEvent.new(expected_event, expected_payload)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,16 @@
1
+ module RabbitFeed
2
+ module TestingSupport
3
+ module TestingHelpers
4
+ def rabbit_feed_consumer
5
+ TestRabbitFeedConsumer.new
6
+ end
7
+ end
8
+
9
+ class TestRabbitFeedConsumer
10
+ def consume_event(event)
11
+ event = Event.new('no schema',event)
12
+ RabbitFeed::Consumer.event_routing.handle_event(event)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module RabbitFeed
2
+ VERSION = '0.3.1'
3
+ end
data/logo.png ADDED
Binary file
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rabbit_feed/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'rabbit_feed'
8
+ spec.version = RabbitFeed::VERSION
9
+ spec.authors = ['Simply Business']
10
+ spec.email = ['tech@simplybusiness.co.uk']
11
+ spec.description = %q{A gem allowing your application to publish messages to RabbitMQ}
12
+ spec.summary = %q{This will enable your application to publish messages to a bus to be processed by other services}
13
+ spec.homepage = 'https://github.com/simplybusiness/rabbit_feed'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ # Gem for interfacing with RabbitMq
22
+ spec.add_dependency 'bunny'
23
+ # We use some helpers from ActiveSupport
24
+ spec.add_dependency 'activesupport'
25
+ # We use validations from ActiveModel
26
+ spec.add_dependency 'activemodel'
27
+ # Provides connection pooling for the producer connections
28
+ spec.add_dependency 'connection_pool'
29
+ # Manages process pidfile
30
+ spec.add_dependency 'pidfile'
31
+ # Schema definitions and serialization for events
32
+ spec.add_dependency 'avro'
33
+ # For stubbing and custom matchers
34
+ spec.add_development_dependency 'rspec'
35
+ end
data/run_benchmark ADDED
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ echo 'Starting test of rails application...'
6
+ # Start the rails application
7
+ echo 'Starting rails application...'
8
+ pushd example/rails_app >/dev/null
9
+ nodenv local v0.10 >/dev/null
10
+ bundle exec rake db:reset RAILS_ENV=development
11
+ bundle exec unicorn -c config/unicorn.rb -E development -D
12
+ sleep 1
13
+ popd >/dev/null
14
+ echo 'Rails application started'
15
+
16
+ # Test publishing via the rails application
17
+ siege -c 10 -r 10 -q -b "http://localhost:8080/beavers POST beaver[name]=`date '+%m/%d/%y %H:%M:%S'`"
18
+ sleep 4
19
+
20
+ # Stop the rails application
21
+ echo 'Stopping rails application...'
22
+ pushd example/rails_app >/dev/null
23
+ kill `cat tmp/pids/unicorn.pid`
24
+ popd >/dev/null
25
+ echo 'Rails application stopped'
26
+ echo 'Rails application test complete'
27
+ echo ''
28
+ echo ''
29
+
30
+ # Test standalone publishing and consuming
31
+ echo 'Starting standalone publishing and consuming benchmark...'
32
+ pushd example/non_rails_app >/dev/null
33
+ bin/benchmark
34
+ popd >/dev/null
35
+ echo 'Benchmark complete'
data/run_example ADDED
@@ -0,0 +1,62 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ # Start consumer on the non-rails application
6
+ echo 'Starting non rails application consumer...'
7
+ pushd example/non_rails_app >/dev/null
8
+ bundle >/dev/null
9
+ bundle exec rake
10
+ bundle exec rabbit_feed consume --environment development --require `pwd`/lib/non_rails_app.rb --daemon --verbose
11
+ sleep 1
12
+ popd >/dev/null
13
+ echo 'Non rails application consumer started'
14
+
15
+ # Start consumer on the rails application
16
+ echo 'Starting rails application consumer...'
17
+ pushd example/rails_app >/dev/null
18
+ bundle >/dev/null
19
+ bundle exec rake db:reset
20
+ bundle exec rake db:reset RAILS_ENV=test
21
+ bundle exec rake
22
+ bundle exec rabbit_feed consume --environment development --daemon --verbose
23
+ sleep 1
24
+ popd >/dev/null
25
+ echo 'Rails application consumer started'
26
+
27
+ # Start the rails application
28
+ echo 'Starting rails application...'
29
+ pushd example/rails_app >/dev/null
30
+ nodenv local v0.10 >/dev/null
31
+ bundle exec unicorn -c config/unicorn.rb -D
32
+ sleep 1
33
+ popd >/dev/null
34
+ echo 'Rails application started'
35
+
36
+ # Trigger an event
37
+ echo 'Triggering event...'
38
+ curl -silent -H -X POST http://localhost:8080/beavers -d "beaver[name]=`date '+%m/%d/%y %H:%M:%S'`" >/dev/null
39
+ echo 'Event triggered'
40
+
41
+ sleep 3
42
+
43
+ # Stop consumer on the non-rails application
44
+ echo 'Stopping non rails application consumer...'
45
+ pushd example/non_rails_app >/dev/null
46
+ kill `cat tmp/pids/rabbit_feed.pid`
47
+ popd >/dev/null
48
+ echo 'Non rails application consumer stopped'
49
+
50
+ # Stop consumer on the rails application
51
+ echo 'Stopping rails application consumer...'
52
+ pushd example/rails_app >/dev/null
53
+ kill `cat tmp/pids/rabbit_feed.pid`
54
+ popd >/dev/null
55
+ echo 'Rails application consumer stopped'
56
+
57
+ # Stop the rails application
58
+ echo 'Stopping rails application...'
59
+ pushd example/rails_app >/dev/null
60
+ kill `cat tmp/pids/unicorn.pid`
61
+ popd >/dev/null
62
+ echo 'Rails application stopped'
data/run_recovery_test ADDED
@@ -0,0 +1,26 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ # Grant the session sudo access
6
+ sudo date
7
+
8
+ # In a separate process enable/disable the loopback interface
9
+ echo 'Starting process that will periodically disable lo0...'
10
+ sudo sh -c "while true; do ifconfig lo0 down; sleep 0.1; ifconfig lo0 up; sleep 0.5; done" &
11
+ disabling_pid=$!
12
+
13
+ # Test standalone publishing and consuming
14
+ echo 'Starting standalone publishing and consuming benchmark...'
15
+ pushd example/non_rails_app >/dev/null
16
+ bin/benchmark
17
+ popd >/dev/null
18
+ echo 'Benchmark complete'
19
+
20
+ # Kill the process that was toggling lo0 and ensure lo0 is enabled
21
+ function cleanup {
22
+ sudo kill $disabling_pid
23
+ sudo ifconfig lo0 up
24
+ echo 'Restored lo0'
25
+ }
26
+ trap cleanup EXIT
@@ -0,0 +1,13 @@
1
+ Feature:
2
+ As a developer
3
+ I want to be able to publish and consume events
4
+
5
+ Scenario: I can publish and consume events
6
+ Given I am consuming
7
+ When I publish an event
8
+ Then I receive that event
9
+
10
+ Scenario: When an event cannot be consumed it remains on the queue
11
+ Given I am consuming
12
+ When I publish an event that cannot be processed by the consumer
13
+ Then the event remains on the queue
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ step 'I am consuming' do
4
+ set_event_routing
5
+ initialize_queue
6
+ @consumer_thread = Thread.new{ RabbitFeed::Consumer.run }
7
+ end
8
+
9
+ step 'I publish an event' do
10
+ set_event_definitions
11
+ publish 'test'
12
+ end
13
+
14
+ step 'I receive that event' do
15
+ event = wait_for_event
16
+ assert_event_presence event
17
+ end
18
+
19
+ step 'I publish an event that cannot be processed by the consumer' do
20
+ set_event_definitions
21
+ publish 'test_failure'
22
+ end
23
+
24
+ step 'the event remains on the queue' do
25
+ event = nil
26
+ 2.times { event = wait_for_event }
27
+ assert_event_presence event
28
+ end
29
+
30
+ module Turnip::Steps
31
+
32
+ def initialize_queue
33
+ RabbitFeed::ProducerConnection.with_connection{|connection|}
34
+ RabbitFeed::ConsumerConnection.with_connection{|connection|}
35
+ end
36
+
37
+ def publish event_name
38
+ @event_text = "#{event_name}_#{Time.now.iso8601(6)}"
39
+ RabbitFeed::Producer.publish_event event_name, { 'field' => @event_text }
40
+ end
41
+
42
+ def assert_event_presence event
43
+ expect(event).to_not be_nil
44
+ expect(event.field).to eq @event_text
45
+ end
46
+
47
+ def wait_for_event
48
+ begin
49
+ Timeout::timeout(5.0) do
50
+ until @consumed_events.any? do
51
+ sleep 0.1
52
+ end
53
+ end
54
+ rescue Timeout::Error
55
+ end
56
+ @consumed_events.pop
57
+ end
58
+
59
+ def set_event_definitions
60
+ EventDefinitions do
61
+ define_event('test', version: '1.0.0') do
62
+ defined_as do
63
+ 'The test event'
64
+ end
65
+ payload_contains do
66
+ field('field', type: 'string', definition: 'The field')
67
+ end
68
+ end
69
+ define_event('test_failure', version: '1.0.0') do
70
+ defined_as do
71
+ 'The test failure event'
72
+ end
73
+ payload_contains do
74
+ field('field', type: 'string', definition: 'The field')
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ def set_event_routing
81
+ consumed_events = []
82
+ @consumed_events = consumed_events
83
+
84
+ EventRouting do
85
+ accept_from('rabbit_feed') do
86
+ event('test') do |event|
87
+ consumed_events << event
88
+ end
89
+ event('test_failure') do |event|
90
+ consumed_events << event
91
+ raise 'event processing failure'
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end