bunny_events 0.2.2 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f56ddc8106ddffb47e4a21f83c06104ab87591db3c05ca12ffc877d6997560c
4
- data.tar.gz: daaddd4f9ae0581e40625e2ffd9146e61f9a1177cf068167974bf190f6ccd7f8
3
+ metadata.gz: 985592caa9bd8cc75584a5b75fd9867a46ed0335dbf5f40e488ceac4e1f1cf77
4
+ data.tar.gz: 349a76a616f41608a04f90cc33b5d5ed470712844347ef4797e110c5d138b576
5
5
  SHA512:
6
- metadata.gz: a51e2605065ccc01876aa5b0b5d6c9aa0d8c3a44ceb1ceece1a68d62986017aed50cdf26f8798cb7ee9a9bf143f7ad8ffbb0f5d8d7e56948c7b22f1a4f9d0b11
7
- data.tar.gz: d8b7b89407ee3c87e8af7fd1446284ec6f320467d4cadf72f1a022bc2c491f344a9c8215ac523005a47f3774e318a1160214e09210be5b13e45823051cb4954a
6
+ metadata.gz: 0c48c7c19a3862fa90f21282db47273328e9355066dcb405bfa63c1b10ea3d3bd0595c6daee5a17cf44cfcda8d0c31b66354121348ec05c0682ec22765327416
7
+ data.tar.gz: 1c2b972049aa3e951bce82a13cdffde5a501525cfeeb8b031959dbecd03f24817a09ab4069581d52a269836f3ff5105e5b42623b09257e2390b1f3f3424b4232
data/Gemfile CHANGED
@@ -2,8 +2,8 @@ source "https://rubygems.org"
2
2
 
3
3
  git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
- # Specify your gem's dependencies in message_queue_event.gemspec
6
5
  gemspec
7
6
 
8
7
  gem "bunny", ">= 2.14.0"
9
- gem 'bunny-mock'
8
+ gem 'bunny-mock'
9
+ gem 'coveralls', require: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bunny_events (0.1.1)
4
+ bunny_events (0.2.2)
5
5
  bunny (>= 2.14.0)
6
6
 
7
7
  GEM
@@ -12,7 +12,15 @@ GEM
12
12
  amq-protocol (~> 2.3, >= 2.3.0)
13
13
  bunny-mock (1.7.0)
14
14
  bunny (>= 1.7)
15
+ coveralls (0.8.23)
16
+ json (>= 1.8, < 3)
17
+ simplecov (~> 0.16.1)
18
+ term-ansicolor (~> 1.3)
19
+ thor (>= 0.19.4, < 2.0)
20
+ tins (~> 1.6)
15
21
  diff-lcs (1.3)
22
+ docile (1.3.2)
23
+ json (2.2.0)
16
24
  rake (10.5.0)
17
25
  rspec (3.8.0)
18
26
  rspec-core (~> 3.8.0)
@@ -27,6 +35,15 @@ GEM
27
35
  diff-lcs (>= 1.2.0, < 2.0)
28
36
  rspec-support (~> 3.8.0)
29
37
  rspec-support (3.8.2)
38
+ simplecov (0.16.1)
39
+ docile (~> 1.1)
40
+ json (>= 1.8, < 3)
41
+ simplecov-html (~> 0.10.0)
42
+ simplecov-html (0.10.2)
43
+ term-ansicolor (1.7.1)
44
+ tins (~> 1.0)
45
+ thor (0.20.3)
46
+ tins (1.21.1)
30
47
 
31
48
  PLATFORMS
32
49
  ruby
@@ -36,6 +53,7 @@ DEPENDENCIES
36
53
  bunny (>= 2.14.0)
37
54
  bunny-mock
38
55
  bunny_events!
56
+ coveralls
39
57
  rake (~> 10.0)
40
58
  rspec (~> 3.0)
41
59
 
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Bunny Events
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/bunny_events.svg)](https://badge.fury.io/rb/bunny_events)
3
+ [![Gem Version](https://badge.fury.io/rb/bunny_events.svg)](https://badge.fury.io/rb/bunny_events) [![Build Status](https://travis-ci.org/Nexus-Mods/bunny_events.svg?branch=master)](https://travis-ci.org/Nexus-Mods/bunny_events) [![Coverage Status](https://coveralls.io/repos/github/Nexus-Mods/bunny_events/badge.svg?branch=master)](https://coveralls.io/github/Nexus-Mods/bunny_events?branch=master)
4
4
 
5
5
  A simple wrapper gem to aid with producing events to a message queue, using Bunny, in a standardized and uniform way across multiple microservices.
6
6
 
7
- Rather than usin Bunny directly, this gem allows an application to define "Event Definitions" which can be defined and published
7
+ Rather than using Bunny directly, this gem allows an application to define "Event Definitions" which can be defined and published
8
8
  in a modular way. This ensures that when you are producing a message, your application logic shouldn't care about how the
9
9
  message is produced (E.g. your controller shouldn't care or know anything about what exchange to publish a message to, only the BunnyEvent
10
10
  that has been defined cares)
@@ -14,6 +14,7 @@ Current Features and limitation:
14
14
  - Allows a bunny connection to initialise the system
15
15
  - Allows the definition of abstract events to be used application-wide
16
16
  - Customization of exchange and queue options when producing an event
17
+ - By default, only initialises the exchange and queues on the first publish. This can be overriden with `opts[:always_create_when_publishing]`
17
18
 
18
19
  ## Installation
19
20
 
@@ -30,6 +31,52 @@ And then execute:
30
31
  Or install it yourself as:
31
32
 
32
33
  $ gem install bunny_events
34
+
35
+ ### Rails Installation
36
+ To initialise the system with Rails, create a new intiailizer:
37
+
38
+ ```ruby
39
+ # config/initializers/bunny-events.rb
40
+ if !Rails.env.test?
41
+ $BUNNY_EVENTS = BunnyEvents.new
42
+ $BUNNY_EVENTS.init Bunny.new("amqp://rabbitmq:rabbitmq@rabbit1:5672").start
43
+ end
44
+ ```
45
+
46
+ Events can then be created in app/events:
47
+
48
+ ```ruby
49
+ require 'bunny_event'
50
+
51
+ class MyTestEvent
52
+ include BunnyEvent
53
+
54
+ # define the event options for queueing this event. Each event type can have different options.
55
+ event_options :exchange => "test_exchange",
56
+ :exchange_opts => {
57
+ :type => :fanout
58
+ }
59
+
60
+ # We can define what the message payload looks like here.
61
+ def initialize(msg)
62
+ @message = "My test message is #{msg}"
63
+ end
64
+ end
65
+ ```
66
+
67
+ ### Rails Testing
68
+
69
+ To use Bunny Events in tests, you can initialize a new instance of the system before every test (or just a single test) with BunnyMock
70
+
71
+ ```ruby
72
+ before(:each) do
73
+ @mock = BunnyMock.new.start
74
+ $BUNNY_EVENTS = BunnyEvents.new
75
+ $BUNNY_EVENTS.init @mock
76
+ end
77
+ ```
78
+
79
+ Note: This requires the `bunny-mock` gem to be installed in your test environment
33
80
 
34
81
  ## Usage
35
82
 
@@ -38,12 +85,24 @@ Or install it yourself as:
38
85
  To produce an event to the message queue, we must first define an event. In `app/events/my_test_event.rb`
39
86
 
40
87
  ```ruby
88
+ require 'bunny_event'
41
89
  class MyTestEvent
42
90
  include BunnyEvent
43
91
 
44
92
  # define the event options for queueing this event. Each event type can have different options.
45
93
  event_options :exchange => "test_exchange",
46
- :exchange_type => :fanout
94
+ :exchange_opts => {
95
+ :type => :fanout
96
+ },
97
+ :queues =>
98
+ {
99
+ :some_queue => {
100
+ :opts => {
101
+ :durable => true
102
+ },
103
+ :routing_key => ""
104
+ }
105
+ }
47
106
 
48
107
  # We can define what the message payload looks like here.
49
108
  def initialize(msg)
@@ -79,15 +138,37 @@ Publishing the event requires the use of the BunnyEvents class
79
138
  event = MyTestEvent.new "This is a test event"
80
139
 
81
140
  # Use the BunnyEvents system to publish this event
82
- BunnyEvents.publish event
141
+ bunny_events = BunnyEvents.new
142
+ bunny_events.init Bunny.new("amqp://rabbitmq:rabbitmq@rabbit1:5672").start
143
+ bunny_events.publish event
83
144
  ```
84
145
 
85
- ### Full example with initialisation
146
+ When publishing, a custom routing key can also be used
86
147
 
87
148
  ```ruby
149
+ bunny_events.publish event, "some_routing_key"
150
+ ```
151
+
152
+ ### Configuration
153
+
154
+ When defining an event, many options can be set via the event_options class method.
88
155
 
156
+ - `exchange` - Name of the exchange this event will publish it's messages to
157
+ - `exchange_opts` - Bunny-specific options for creating an exchange. See http://rubybunny.info/articles/exchanges.html for more information.
158
+ - `queues` - A hash of queues to be created and bound to the exchange. Each key consists of the name of the queue and the value is another hash, with the following options:
159
+ - `opts` - Bunny-specific options fo creating a queue
160
+ - `routing_key` - Key used for binding this queue to the exchange
161
+ - `ignore_bind` - Can be used to override the binding. Defaults to `false`. If true, will not bind this queue to the exchange. Is useful when utilising the default exchange.
162
+ - `always_create_when_publishing` - Overrides the queue/exchange creation process to run every time a message is processed. Default: `false`
163
+ - `routing_key` - The default routing key used for all messages pushed for this event. Can be changed when publishing a message E.g. ```bunny_events.publish event, "custom_routing_key"```
164
+
165
+ ### Full example with initialisation
166
+
167
+ ```ruby
168
+ require 'bunny_event'
89
169
  # This is done once as part of the configuration step, usually in a rails initializer, or at the start of your application
90
- BunnyEvents.init Bunny.new("amqp://rabbitmq:rabbitmq@rabbit1:5672").start
170
+ bunny_events = BunnyEvents.new
171
+ bunny_events.init Bunny.new("amqp://rabbitmq:rabbitmq@rabbit1:5672").start
91
172
 
92
173
  # Event definitions are defined in classes, in rails, we generally use app/messages
93
174
  class MyTestEvent
@@ -116,7 +197,7 @@ end
116
197
 
117
198
  # When we want to create a new instance of an event, we create and publish the object
118
199
  event = MyTestEvent.new "test"
119
- BunnyEvents.publish event
200
+ bunny_events.publish event
120
201
  ```
121
202
 
122
203
  ## Development
@@ -127,7 +208,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
127
208
 
128
209
  ## Contributing
129
210
 
130
- Bug reports and pull requests are welcome on GitHub at https://github.com/Nexus-Mods/message_queue_event.
211
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Nexus-Mods/bunny_events
131
212
 
132
213
  ## License
133
214
 
data/bin/example CHANGED
@@ -17,7 +17,7 @@ class DummyEvent
17
17
 
18
18
  event_options :exchange => "test_exchange",
19
19
  :exchange_opts => {
20
- :type => :fanout
20
+ :type => :direct
21
21
  },
22
22
  :queues =>
23
23
  {
@@ -29,6 +29,7 @@ class DummyEvent
29
29
  }
30
30
  }
31
31
 
32
+
32
33
  def initialize(msg)
33
34
  @message = "My test message is #{msg}"
34
35
  end
@@ -36,7 +37,24 @@ class DummyEvent
36
37
  end
37
38
 
38
39
  p "Publishing event"
40
+
39
41
  bunny_events = BunnyEvents.new
40
- bunny_events.init Bunny.new("amqp://rabbitmq:rabbitmq@localhost:5672").start
42
+ bunny = Bunny.new("amqp://rabbitmq:rabbitmq@localhost:5672").start
43
+ bunny_events.init bunny
44
+
45
+ bunny_events.publish DummyEvent.new "test"
46
+
47
+ p "deleting exchane"
48
+ p bunny.exchange_exists? "test_exchange"
49
+
50
+ x = bunny_events.channels["DummyEvent"].exchange "test_exchange"
51
+ x.delete
52
+
53
+ p "Does exchange exist?"
54
+ p bunny.exchange_exists? "test_exchange"
55
+
56
+ bunny_events.publish DummyEvent.new "test"
57
+
58
+ p bunny.exchange_exists? "test_exchange"
41
59
 
42
- bunny_events.publish DummyEvent.new "test"
60
+ p "end"
@@ -40,4 +40,5 @@ Gem::Specification.new do |spec|
40
40
  spec.add_development_dependency "bundler", "~> 1.17"
41
41
  spec.add_development_dependency "rake", "~> 10.0"
42
42
  spec.add_development_dependency "rspec", "~> 3.0"
43
+ spec.add_development_dependency "bunny-mock"
43
44
  end
data/lib/bunny_event.rb CHANGED
@@ -29,4 +29,5 @@ end
29
29
  module Exceptions
30
30
  class InvalidBunnyConnection < StandardError; end
31
31
  class InvalidBunnyEvent < StandardError; end
32
+ class InvalidExchange < StandardError; end
32
33
  end
@@ -1,3 +1,3 @@
1
1
  module BunnyEvent
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/bunny_events.rb CHANGED
@@ -4,6 +4,10 @@ class BunnyEvents
4
4
 
5
5
  attr_accessor :channels, :bunny_connection
6
6
 
7
+ # Keeps track of which events have been intiailized by this BunnyEvents worker. Used to ensure that the queue and
8
+ # exchange creation is only performed once.
9
+ attr_accessor :initialized_events
10
+
7
11
  @@defaults = {
8
12
  :exchange => "",
9
13
  :exchange_type => :direct,
@@ -27,6 +31,8 @@ class BunnyEvents
27
31
 
28
32
  @channels = {}
29
33
 
34
+ @initialized_exchanges = {}
35
+
30
36
  @bunny_connection = bunny_connection
31
37
 
32
38
  end
@@ -36,14 +42,14 @@ class BunnyEvents
36
42
  end
37
43
 
38
44
  # Public message. message should be an instance of BaseMessage (or a class with BaseMessage included)
39
- def publish(message)
45
+ def publish(message, routing_key = nil)
40
46
 
41
47
  unless message.class.included_modules.include?(BunnyEvent)
42
48
  raise Exceptions::InvalidBunnyEvent.new
43
49
  end
44
50
 
45
51
  unless connected?
46
- throw "Not connected"
52
+ raise Exceptions::InvalidBunnyConnection.new
47
53
  end
48
54
 
49
55
  # get the options defined by the message queue event class
@@ -56,28 +62,48 @@ class BunnyEvents
56
62
 
57
63
  channel = @channels[message.class.name]
58
64
 
59
- # If the event was sent with an exchange name, create and submit this to the exchange, otherwise, just use the default exchange
60
- if !opts[:exchange].nil? && !opts[:exchange].empty?
61
- x = channel.exchange(opts[:exchange], opts[:exchange_opts] || {})
62
- else
63
- x = channel.default_exchange
64
- end
65
+ # Ensure that the exchange, queue and binding creation is only performed once
66
+ if (!@initialized_exchanges.key?(message.class.name)) || opts[:always_create_when_publishing]
67
+ # If the event was sent with an exchange name, create and submit this to the exchange, otherwise, just use the default exchange
68
+ if !opts[:exchange].nil? && !opts[:exchange].empty?
69
+ x = channel.exchange(opts[:exchange], opts[:exchange_opts] || {})
70
+ else
71
+ x = channel.default_exchange
72
+ end
73
+ # if the event was sent with queue definitions, ensure to create the bindings
74
+ if !opts[:queues].nil?
75
+ handle_queue_definitions channel, x, opts[:queues]
76
+ end
65
77
 
66
- # if the event was sent with queue definitions, ensure to create the bindings
67
- if !opts[:queues].nil?
68
- handle_queue_definitions channel, x, opts[:queues]
78
+ # ensure this event's creation params are not processed again
79
+ @initialized_exchanges[message.class.name] ||= x
69
80
  end
70
81
 
71
- x.publish message.message, :routing_key => opts[:routing_key]
82
+ x ||= @initialized_exchanges[message.class.name]
72
83
 
84
+ # ensure exchange is not null
85
+ if x.nil? || !@bunny_connection.exchange_exists?(opts[:exchange])
86
+ raise Exceptions::InvalidExchange.new
73
87
  end
74
88
 
89
+ # publish message along with the optional routing key
90
+ x.publish message.message, :routing_key => routing_key || opts[:routing_key]
91
+ end
92
+
75
93
  private
76
94
  def handle_queue_definitions (channel, exchange, queues)
77
95
  queues.each do |q, opts|
78
96
  # Create this queue and bind, if the binding options are present
79
97
  queue = channel.queue q.to_s, opts[:opts] || {}
80
- queue.bind exchange, :key => opts[:routing_key] || ""
98
+
99
+ # if ignore bind isn't set, set to nil
100
+ ignore_bind = opts[:ignore_bind] || false
101
+
102
+ # if we aren't ignoring the binding for this queue, check if it's already bound. We also shouldn't bind directly
103
+ # to the default queue
104
+ if !ignore_bind && !queue.bound_to?(exchange) && exchange.name != ""
105
+ queue.bind exchange, :key => opts[:routing_key] || ""
106
+ end
81
107
  end
82
108
  end
83
109
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bunny_events
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dean Lovett
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-02 00:00:00.000000000 Z
11
+ date: 2019-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bunny-mock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  description: This gem allows the use of "Messages" to be defined and published very
70
84
  easily, without your models/controllers having to worry about how messages are produced.
71
85
  Supports AMQP
@@ -86,10 +100,10 @@ files:
86
100
  - bin/console
87
101
  - bin/example
88
102
  - bin/setup
103
+ - bunny_events.gemspec
89
104
  - lib/bunny_event.rb
90
105
  - lib/bunny_events.rb
91
106
  - lib/bunny_events/version.rb
92
- - message_queue_event.gemspec
93
107
  homepage: https://www.nexusmods.com
94
108
  licenses:
95
109
  - MIT