bunny_events 0.2.2 → 0.3.0

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