rabbit_feed 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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