eventboss 1.3.2 → 1.5.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: eaa1906368e8751476a4df0ae1f274a8008735de72191a34867881b50b19492b
4
- data.tar.gz: 20bfe9695bc682e801b5b6760b92b9d575d0f323218b4286196aaff6f702d30f
3
+ metadata.gz: 7d59c3796789baa9e13a8a2079b026909b2d37f426edeeed8936b83a1dfe97df
4
+ data.tar.gz: 2af186a964a87844ec33a5a625c21b847fe1c7782583bf760c30aa6037de592c
5
5
  SHA512:
6
- metadata.gz: a1e03452ce05f49cd5cbc09875467145d41c9fe8e6239941f874394a9895c617a2a2843daa479833a498d8ccbed6e6ac64b85ca3dab8dc73f42e2f980ba99468
7
- data.tar.gz: 6c8b23c2ace8d611e3a79f98dcf15a11a97dbba537a46ee97df970730ad0107eef117547697cdebbd2e4ab97404dd99dff388f6ccbfbccfcd9b5fdad9b68d5ae
6
+ metadata.gz: 8ff2e6aeaeb07d80a8e27a7609071a557ee2db659afa109035bbc7495f143e9bf9e504a48ac0358326583bab6ec1f670c241a2b35649c90b7adc2497396f7533
7
+ data.tar.gz: 514290d9f45c66124c433a33dd4f169719bec4d1a6141e1fe734c228e4363068199ab48962820cedbaff9299d30abeda497b3f31270ce4669bb2958b39e312b2
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [1.4.0] - 2020-04-18
8
+
9
+ - Introduce server middlewares (#31)
10
+
7
11
  ## [1.1.0] - 2019-07-16
8
12
 
9
13
  ### Added
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- eventboss (1.3.2)
4
+ eventboss (1.5.0)
5
5
  aws-sdk-sns (>= 1.1.0)
6
6
  aws-sdk-sqs (>= 1.3.0)
7
7
  dotenv (~> 2.1, >= 2.1.1)
@@ -9,25 +9,25 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- aws-eventstream (1.0.3)
13
- aws-partitions (1.269.0)
14
- aws-sdk-core (3.89.1)
15
- aws-eventstream (~> 1.0, >= 1.0.2)
12
+ aws-eventstream (1.1.0)
13
+ aws-partitions (1.374.0)
14
+ aws-sdk-core (3.107.0)
15
+ aws-eventstream (~> 1, >= 1.0.2)
16
16
  aws-partitions (~> 1, >= 1.239.0)
17
17
  aws-sigv4 (~> 1.1)
18
18
  jmespath (~> 1.0)
19
- aws-sdk-sns (1.21.0)
20
- aws-sdk-core (~> 3, >= 3.71.0)
19
+ aws-sdk-sns (1.28.0)
20
+ aws-sdk-core (~> 3, >= 3.99.0)
21
21
  aws-sigv4 (~> 1.1)
22
- aws-sdk-sqs (1.23.1)
23
- aws-sdk-core (~> 3, >= 3.71.0)
22
+ aws-sdk-sqs (1.33.0)
23
+ aws-sdk-core (~> 3, >= 3.99.0)
24
24
  aws-sigv4 (~> 1.1)
25
- aws-sigv4 (1.1.0)
26
- aws-eventstream (~> 1.0, >= 1.0.2)
25
+ aws-sigv4 (1.2.2)
26
+ aws-eventstream (~> 1, >= 1.0.2)
27
27
  diff-lcs (1.3)
28
- dotenv (2.7.5)
28
+ dotenv (2.7.6)
29
29
  jmespath (1.4.0)
30
- rake (12.3.1)
30
+ rake (13.0.1)
31
31
  rspec (3.7.0)
32
32
  rspec-core (~> 3.7.0)
33
33
  rspec-expectations (~> 3.7.0)
data/README.md CHANGED
@@ -151,20 +151,52 @@ Eventboss.configure do |config|
151
151
  end
152
152
  ```
153
153
 
154
- ## Development mode
154
+ ### Middlewares
155
+
156
+ Server middlewares intercept the execution of your `Listeners`. You can use to extract and run common functions on every message received.
157
+
158
+ Define a middleware in the following way:
159
+
160
+ ```ruby
161
+ class LogMiddleware < Eventboss::Middleware::Base
162
+ def call(_work)
163
+ yield
164
+ logger.debug 'finished with success'
165
+ rescue StandardError => _error
166
+ logger.error 'finished with error'
167
+ raise
168
+ end
169
+
170
+ private
171
+
172
+ def logger
173
+ @logger ||= @options.fetch(:logger)
174
+ end
175
+ end
176
+ ```
177
+
178
+ And configure your logger as such:
179
+
180
+ ```ruby
181
+ Eventboss.configure do |config|
182
+ config.server_middleware.add LogMiddleware, logger: Logger.new
183
+ end
184
+ ```
185
+
186
+ ## Development mode
155
187
 
156
188
  In the _development mode_ you don't need to create the infrastructure required by the application - Eventboss will take care of this.
157
189
 
158
190
  It works on AWS and [localstack](https://github.com/localstack/localstack).
159
191
 
160
- Following resources are created:
192
+ Following resources are created:
161
193
  * SNS topics - created when application starts and when message is published
162
194
  * SQS queues (with SendMessage policy) - created when application starts
163
195
  * subscriptions for topics and queues - created when application starts
164
196
 
165
197
  Just enable it via environment variable...
166
198
  ```
167
- EVENTBUS_DEVELOPMENT_MODE=true
199
+ EVENTBOSS_DEVELOPMENT_MODE=true
168
200
  ```
169
201
  use fixed account ID for localstack setup...
170
202
  ```
@@ -206,4 +238,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/AirHel
206
238
  ## License
207
239
 
208
240
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
209
-
@@ -13,6 +13,7 @@ require 'eventboss/logging'
13
13
  require 'eventboss/safe_thread'
14
14
  require 'eventboss/launcher'
15
15
  require 'eventboss/long_poller'
16
+ require 'eventboss/middleware'
16
17
  require 'eventboss/unit_of_work'
17
18
  require 'eventboss/worker'
18
19
  require 'eventboss/fetcher'
@@ -34,6 +34,7 @@ module Eventboss
34
34
  defined_or_default('error_handlers') do
35
35
  [ErrorHandlers::Logger.new].tap do |handlers|
36
36
  handlers << ErrorHandlers::DbConnectionDropHandler.new if defined?(::ActiveRecord::StatementInvalid)
37
+ handlers << ErrorHandlers::DbConnectionNotEstablishedHandler.new if defined?(::ActiveRecord::ConnectionNotEstablished)
37
38
  end
38
39
  end
39
40
  end
@@ -118,6 +119,10 @@ module Eventboss
118
119
  end
119
120
  end
120
121
 
122
+ def server_middleware
123
+ @server_middleware ||= Middleware::Chain.new
124
+ end
125
+
121
126
  private
122
127
 
123
128
  def defined_or_default(variable_name)
@@ -0,0 +1,11 @@
1
+ module Eventboss
2
+ module ErrorHandlers
3
+ class DbConnectionNotEstablishedHandler
4
+ def call(exception, _context = {})
5
+ if exception.class == ::ActiveRecord::ConnectionNotEstablished
6
+ ::ActiveRecord::Base.connection.reconnect!
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Eventboss
2
+ module ErrorHandlers
3
+ class Rollbar
4
+ def call(exception, context = {})
5
+ eventboss_context = { component: 'eventboss' }
6
+ eventboss_context[:action] = context[:processor].class.to_s if context[:processor]
7
+ ::Rollbar.error(exception, eventboss_context.merge(context))
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,5 @@
1
1
  require 'eventboss/error_handlers/logger'
2
2
  require 'eventboss/error_handlers/airbrake'
3
+ require 'eventboss/error_handlers/rollbar'
3
4
  require 'eventboss/error_handlers/db_connection_drop_handler'
5
+ require 'eventboss/error_handlers/db_connection_not_established_handler'
@@ -0,0 +1,57 @@
1
+ module Eventboss
2
+ module Middleware
3
+ class Chain
4
+ attr_reader :entries
5
+
6
+ def initialize
7
+ @entries = []
8
+ end
9
+
10
+ def add(klass, options = {})
11
+ @entries << Entry.new(klass, options)
12
+ end
13
+
14
+ def invoke(*args)
15
+ chain = @entries.map(&:build).reverse!
16
+
17
+ invoke_lambda = lambda do
18
+ if (mid = chain.pop)
19
+ mid.call(*args, &invoke_lambda)
20
+ else
21
+ yield
22
+ end
23
+ end
24
+ invoke_lambda.call
25
+ end
26
+
27
+ def clear
28
+ @entries.clear
29
+ end
30
+ end
31
+
32
+ class Base
33
+ attr_reader :options
34
+
35
+ def initialize(options)
36
+ @options = options
37
+ end
38
+
39
+ def call
40
+ raise 'Not implemented'
41
+ end
42
+ end
43
+
44
+ class Entry
45
+ attr_reader :klass, :options
46
+
47
+ def initialize(klass, options)
48
+ @klass = klass
49
+ @options = options
50
+ end
51
+
52
+ def build
53
+ @klass.new(options)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -2,8 +2,9 @@ class Eventboss::Railtie < Rails::Railtie
2
2
  rake_tasks do
3
3
  load 'tasks/eventboss.rake'
4
4
 
5
- # Load rails environment before executing reload.
5
+ # Load rails environment before executing reload and purge.
6
6
  # It makes sure to load configuration file.
7
7
  task 'eventboss:deadletter:reload': :environment
8
+ task 'eventboss:deadletter:purge': :environment
8
9
  end
9
10
  end
@@ -1,3 +1,3 @@
1
1
  module Eventboss
2
- VERSION = "1.3.2"
2
+ VERSION = "1.5.0"
3
3
  end
@@ -20,7 +20,7 @@ module Eventboss
20
20
 
21
21
  def run
22
22
  while (work = @bus.pop)
23
- work.run
23
+ run_work(work)
24
24
  end
25
25
  @launcher.worker_stopped(self)
26
26
  rescue Eventboss::Shutdown
@@ -32,6 +32,12 @@ module Eventboss
32
32
  @launcher.worker_stopped(self, restart: true)
33
33
  end
34
34
 
35
+ def run_work(work)
36
+ server_middleware.invoke(work) do
37
+ work.run
38
+ end
39
+ end
40
+
35
41
  def terminate(wait = false)
36
42
  stop_token
37
43
  return unless @thread
@@ -51,5 +57,9 @@ module Eventboss
51
57
  def stop_token
52
58
  @bus << nil
53
59
  end
60
+
61
+ def server_middleware
62
+ Eventboss.configuration.server_middleware
63
+ end
54
64
  end
55
65
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= event_name.camelize %>Listener
4
+ include Eventboss::Listener
5
+
6
+ eventboss_options event_name: '<%= event_name %>'<%= source_app ? ", source_app: '#{ source_app }'" : "" %>
7
+
8
+ def receive(payload)
9
+ Rails.logger.tagged(jid) { Rails.logger.info("payload: #{ payload }") }
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Creates the Eventboss listener scaffold
4
+ #
5
+ # @example Invocation from terminal
6
+ # rails generate eventboss:listener get_well air-helper
7
+ #
8
+ module Eventboss
9
+ class ListenerGenerator < Rails::Generators::Base
10
+ source_root File.expand_path(__dir__)
11
+
12
+ argument :event_name, required: true
13
+ argument :source_app, required: false
14
+
15
+ desc 'Creates the Eventboss listener scaffold'
16
+ def create_listener_scaffold
17
+ template 'eventboss_listener.rb.erb', "app/listeners/#{ event_name }_listener.rb"
18
+ end
19
+ end
20
+ end
@@ -7,7 +7,7 @@ namespace :eventboss do
7
7
  source_app = args[:source_app]
8
8
  event_name = args[:event_name]
9
9
 
10
- # Zero means, fetch all messages
10
+ # Zero means: fetch all messages
11
11
  max_messages = args[:max_messages].to_i
12
12
 
13
13
  # Ensure we don't fetch more than 10 messages from SQS
@@ -15,13 +15,8 @@ namespace :eventboss do
15
15
 
16
16
  abort "[#{task.name}] At least event name should be passed as argument" unless event_name
17
17
 
18
- queue_name = [
19
- Eventboss.configuration.eventboss_app_name,
20
- Eventboss.configuration.sns_sqs_name_infix,
21
- source_app,
22
- event_name,
23
- Eventboss.env
24
- ].compact.join('-')
18
+ queue_name = compose_queue_name(source_app, event_name)
19
+
25
20
  puts "[#{task.name}] Reloading #{queue_name}-deadletter (max: #{ max_messages }, batch: #{ batch_size })"
26
21
  queue = Eventboss::Queue.new("#{queue_name}-deadletter")
27
22
  send_queue = Eventboss::Queue.new(queue_name)
@@ -38,7 +33,6 @@ namespace :eventboss do
38
33
  break if messages.count.zero?
39
34
 
40
35
  messages.each do |message|
41
- puts "[#{task.name}] Publishing message: #{message.body}"
42
36
  client.send_message(queue_url: send_queue.url, message_body: message.body)
43
37
  fetcher.delete(queue, message)
44
38
 
@@ -49,5 +43,51 @@ namespace :eventboss do
49
43
  break if max_messages > 0 && total >= max_messages
50
44
  end
51
45
  end
46
+
47
+ desc 'Purge deadletter queue'
48
+ task :purge, [:event_name, :source_app, :max_messages] do |task, args|
49
+ source_app = args[:source_app]
50
+ event_name = args[:event_name]
51
+
52
+ # Zero means: fetch all messages
53
+ max_messages = args[:max_messages].to_i
54
+
55
+ # Ensure we don't fetch more than 10 messages from SQS
56
+ batch_size = max_messages == 0 ? 10 : [10, max_messages].min
57
+
58
+ abort "[#{task.name}] At least event name should be passed as argument" unless event_name
59
+
60
+ queue_name = compose_queue_name(source_app, event_name)
61
+
62
+ puts "[#{task.name}] Purging #{queue_name}-deadletter (max: #{ max_messages }, batch: #{ batch_size })"
63
+ queue = Eventboss::Queue.new("#{queue_name}-deadletter")
64
+ puts "[#{task.name}] #{queue.url}"
65
+
66
+ fetcher = Eventboss::Fetcher.new(Eventboss.configuration)
67
+ total = 0
68
+ loop do
69
+ messages = fetcher.fetch(queue, batch_size)
70
+ break if messages.count.zero?
71
+
72
+ messages.each do |message|
73
+ fetcher.delete(queue, message)
74
+
75
+ total += 1
76
+ break if max_messages > 0 && total >= max_messages
77
+ end
78
+
79
+ break if max_messages > 0 && total >= max_messages
80
+ end
81
+ end
82
+
83
+ def compose_queue_name(source_app, event_name)
84
+ [
85
+ Eventboss.configuration.eventboss_app_name,
86
+ Eventboss.configuration.sns_sqs_name_infix,
87
+ source_app,
88
+ event_name,
89
+ Eventboss.env
90
+ ].compact.join('-')
91
+ end
52
92
  end
53
93
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eventboss
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - AirHelp
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-03 00:00:00.000000000 Z
11
+ date: 2021-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-sqs
@@ -126,7 +126,9 @@ files:
126
126
  - lib/eventboss/development_mode.rb
127
127
  - lib/eventboss/error_handlers/airbrake.rb
128
128
  - lib/eventboss/error_handlers/db_connection_drop_handler.rb
129
+ - lib/eventboss/error_handlers/db_connection_not_established_handler.rb
129
130
  - lib/eventboss/error_handlers/logger.rb
131
+ - lib/eventboss/error_handlers/rollbar.rb
130
132
  - lib/eventboss/extensions.rb
131
133
  - lib/eventboss/fetcher.rb
132
134
  - lib/eventboss/instrumentation.rb
@@ -134,6 +136,7 @@ files:
134
136
  - lib/eventboss/listener.rb
135
137
  - lib/eventboss/logging.rb
136
138
  - lib/eventboss/long_poller.rb
139
+ - lib/eventboss/middleware.rb
137
140
  - lib/eventboss/publisher.rb
138
141
  - lib/eventboss/queue.rb
139
142
  - lib/eventboss/queue_listener.rb
@@ -147,12 +150,14 @@ files:
147
150
  - lib/eventboss/unit_of_work.rb
148
151
  - lib/eventboss/version.rb
149
152
  - lib/eventboss/worker.rb
153
+ - lib/generators/eventboss/listener/eventboss_listener.rb.erb
154
+ - lib/generators/eventboss/listener/listener_generator.rb
150
155
  - lib/tasks/eventboss.rake
151
156
  homepage: https://github.com/AirHelp/eventboss
152
157
  licenses:
153
158
  - MIT
154
159
  metadata: {}
155
- post_install_message:
160
+ post_install_message:
156
161
  rdoc_options: []
157
162
  require_paths:
158
163
  - lib
@@ -167,8 +172,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
172
  - !ruby/object:Gem::Version
168
173
  version: '0'
169
174
  requirements: []
170
- rubygems_version: 3.0.3
171
- signing_key:
175
+ rubygems_version: 3.1.4
176
+ signing_key:
172
177
  specification_version: 4
173
178
  summary: Eventboss Ruby Client.
174
179
  test_files: []