ears 0.11.2 → 0.13.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 +4 -4
- data/.rspec +1 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +7 -7
- data/Gemfile.lock +10 -3
- data/README.md +73 -5
- data/Rakefile +12 -2
- data/lib/ears/consumer.rb +50 -0
- data/lib/ears/middlewares/max_retries.rb +1 -0
- data/lib/ears/setup.rb +26 -0
- data/lib/ears/version.rb +1 -1
- data/lib/ears.rb +6 -4
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba8ffc55e16ec7c7f0b7e3327b25aaf287feba34cc527d93d40d5b59bb4a1976
|
|
4
|
+
data.tar.gz: cacc33604f6299450735d16a376d583ffea86f27cc04e6108eab92473ae2ac50
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aa791974d982def87dfff26bc03819e5cd9c12d25440a055a3c9ce3bb5ebf8c6b36d00f31f93b3b37d5f0702ce4d5831e47f86e24abea9efde01b6d40e8f9482
|
|
7
|
+
data.tar.gz: df472e7514f6308e4436f0e475ea0dbcbf1e5e3219d87a3bc7adddb9ea74ee198088f9d565db61925cad3865f24fa25d6d1ff9db7b85bc84122fb0d934c1dbac
|
data/.rspec
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.13.0 (2023-11-07)
|
|
4
|
+
|
|
5
|
+
- Allow adding multiple routing keys to the consumer configuration, configure method within consumer will only accept `routing_keys` array instead of `routing_key` string
|
|
6
|
+
|
|
7
|
+
## 0.12.0 (2023-10-26)
|
|
8
|
+
|
|
9
|
+
- add new interface to setup consumers including their exchange, queue and binding the queue to the exchange via routing key via `Ears.setup_consumers` and `configure(queue:, exchange:,routing_key:, ...)` for Ears::Consumers subclasses
|
|
10
|
+
|
|
3
11
|
## 0.11.2 (2023-10-25)
|
|
4
12
|
|
|
5
13
|
- Add documentation generation via yard
|
data/Gemfile
CHANGED
|
@@ -2,13 +2,13 @@ source 'https://rubygems.org'
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
group :
|
|
6
|
-
gem 'prettier'
|
|
5
|
+
group :test do
|
|
6
|
+
gem 'prettier', require: false
|
|
7
7
|
gem 'rake'
|
|
8
|
-
gem 'redcarpet'
|
|
9
8
|
gem 'rspec'
|
|
10
|
-
gem 'rubocop'
|
|
11
|
-
gem 'rubocop-rake'
|
|
12
|
-
gem 'rubocop-rspec'
|
|
13
|
-
gem '
|
|
9
|
+
gem 'rubocop', require: false
|
|
10
|
+
gem 'rubocop-rake', require: false
|
|
11
|
+
gem 'rubocop-rspec', require: false
|
|
12
|
+
gem 'simplecov'
|
|
13
|
+
gem 'yard', require: false
|
|
14
14
|
end
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
ears (0.
|
|
4
|
+
ears (0.13.0)
|
|
5
5
|
bunny (~> 2.22.0)
|
|
6
6
|
multi_json
|
|
7
7
|
|
|
@@ -15,6 +15,7 @@ GEM
|
|
|
15
15
|
amq-protocol (~> 2.3, >= 2.3.1)
|
|
16
16
|
sorted_set (~> 1, >= 1.0.2)
|
|
17
17
|
diff-lcs (1.5.0)
|
|
18
|
+
docile (1.4.0)
|
|
18
19
|
haml (6.1.2)
|
|
19
20
|
temple (>= 0.8.2)
|
|
20
21
|
thor
|
|
@@ -36,7 +37,6 @@ GEM
|
|
|
36
37
|
rake (13.0.6)
|
|
37
38
|
rbs (3.1.3)
|
|
38
39
|
rbtree (0.4.6)
|
|
39
|
-
redcarpet (3.6.0)
|
|
40
40
|
regexp_parser (2.8.1)
|
|
41
41
|
rexml (3.2.6)
|
|
42
42
|
rspec (3.12.0)
|
|
@@ -78,6 +78,12 @@ GEM
|
|
|
78
78
|
rubocop-factory_bot (~> 2.22)
|
|
79
79
|
ruby-progressbar (1.13.0)
|
|
80
80
|
set (1.0.3)
|
|
81
|
+
simplecov (0.22.0)
|
|
82
|
+
docile (~> 1.1)
|
|
83
|
+
simplecov-html (~> 0.11)
|
|
84
|
+
simplecov_json_formatter (~> 0.1)
|
|
85
|
+
simplecov-html (0.12.3)
|
|
86
|
+
simplecov_json_formatter (0.1.4)
|
|
81
87
|
sorted_set (1.0.3)
|
|
82
88
|
rbtree
|
|
83
89
|
set (~> 1.0)
|
|
@@ -101,6 +107,7 @@ PLATFORMS
|
|
|
101
107
|
arm64-darwin-20
|
|
102
108
|
arm64-darwin-21
|
|
103
109
|
arm64-darwin-22
|
|
110
|
+
ruby
|
|
104
111
|
x86_64-darwin-20
|
|
105
112
|
x86_64-darwin-21
|
|
106
113
|
x86_64-darwin-22
|
|
@@ -110,11 +117,11 @@ DEPENDENCIES
|
|
|
110
117
|
ears!
|
|
111
118
|
prettier
|
|
112
119
|
rake
|
|
113
|
-
redcarpet
|
|
114
120
|
rspec
|
|
115
121
|
rubocop
|
|
116
122
|
rubocop-rake
|
|
117
123
|
rubocop-rspec
|
|
124
|
+
simplecov
|
|
118
125
|
yard
|
|
119
126
|
|
|
120
127
|
BUNDLED WITH
|
data/README.md
CHANGED
|
@@ -39,7 +39,39 @@ end
|
|
|
39
39
|
|
|
40
40
|
_Note_: `connection_name` is a mandatory setting!
|
|
41
41
|
|
|
42
|
-
Next, define your exchanges, queues, and consumers
|
|
42
|
+
Next, you can define your exchanges, queues, and consumers in 2 ways:
|
|
43
|
+
|
|
44
|
+
#### 1. consumer specific configuration method (recommended)
|
|
45
|
+
|
|
46
|
+
1. Pass your consumer classes to `Ears.setup`:
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
Ears.setup do
|
|
50
|
+
Ears.setup_consumers(Consumer1, Consumer2, ...)
|
|
51
|
+
end
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
2. Implement your consumers by subclassing `Ears::Consumer`. and call the configure method.
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
class Consumer1 < Ears::Consumer
|
|
58
|
+
configure(
|
|
59
|
+
queue: 'queue_name',
|
|
60
|
+
exchange: 'exchange',
|
|
61
|
+
routing_keys: %w[routing_key1 routing_key2],
|
|
62
|
+
retry_queue: true, # optional configuration, defaults to false, Adds a retry queue
|
|
63
|
+
error_queue: true, # optional configuration, defaults to false, Adds an error queue
|
|
64
|
+
)
|
|
65
|
+
def work(delivery_info, metadata, payload)
|
|
66
|
+
message = JSON.parse(payload)
|
|
67
|
+
do_stuff(message)
|
|
68
|
+
|
|
69
|
+
ack
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### 2. Generic configuration method
|
|
43
75
|
|
|
44
76
|
```ruby
|
|
45
77
|
Ears.setup do
|
|
@@ -57,7 +89,7 @@ Ears.setup do
|
|
|
57
89
|
end
|
|
58
90
|
```
|
|
59
91
|
|
|
60
|
-
Finally, you need to implement `MyConsumer` by subclassing `Ears::Consumer`.
|
|
92
|
+
Finally, you need to implement `MyConsumer` by subclassing `Ears::Consumer`. and call the configure method.
|
|
61
93
|
|
|
62
94
|
```ruby
|
|
63
95
|
class MyConsumer < Ears::Consumer
|
|
@@ -70,7 +102,9 @@ class MyConsumer < Ears::Consumer
|
|
|
70
102
|
end
|
|
71
103
|
```
|
|
72
104
|
|
|
73
|
-
|
|
105
|
+
### Run your consumers
|
|
106
|
+
|
|
107
|
+
Note: Be prepared that unhandled errors will be reraised. So, take care of cleanup work.
|
|
74
108
|
|
|
75
109
|
```ruby
|
|
76
110
|
begin
|
|
@@ -165,7 +199,24 @@ end
|
|
|
165
199
|
|
|
166
200
|
### Implementing a retrying queue
|
|
167
201
|
|
|
168
|
-
Sometimes you want to automatically retry processing a message, in case it just failed due to temporary problems. In that case, you can set the `retry_queue` and `retry_delay` parameters when creating the queue.
|
|
202
|
+
Sometimes you want to automatically retry processing a message, in case it just failed due to temporary problems. In that case, you can set the `retry_queue` and `retry_delay` parameters when creating the queue OR pass it to the configure method in your consumer.
|
|
203
|
+
|
|
204
|
+
```ruby
|
|
205
|
+
class MyConsumer < Ears::Consumer
|
|
206
|
+
configure(
|
|
207
|
+
queue: 'queue_name',
|
|
208
|
+
exchange: 'exchange',
|
|
209
|
+
routing_keys: %w[routing_key1 routing_key2],
|
|
210
|
+
retry_queue: true,
|
|
211
|
+
)
|
|
212
|
+
def work(delivery_info, metadata, payload)
|
|
213
|
+
message = JSON.parse(payload)
|
|
214
|
+
do_stuff(message)
|
|
215
|
+
|
|
216
|
+
ack
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
```
|
|
169
220
|
|
|
170
221
|
```ruby
|
|
171
222
|
my_queue =
|
|
@@ -178,7 +229,24 @@ This will happen indefinitely, so if you want to bail out of this cycle at some
|
|
|
178
229
|
|
|
179
230
|
### Implementing an error queue
|
|
180
231
|
|
|
181
|
-
You can set the `error_queue` parameter to automatically create an error queue.
|
|
232
|
+
You can set the `error_queue` parameter to automatically create an error queue, or add it to the configure method in your consumer.
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
class MyConsumer < Ears::Consumer
|
|
236
|
+
configure(
|
|
237
|
+
queue: 'queue_name',
|
|
238
|
+
exchange: 'exchange',
|
|
239
|
+
routing_keys: %w[routing_key1 routing_key2],
|
|
240
|
+
error_queue: true,
|
|
241
|
+
)
|
|
242
|
+
def work(delivery_info, metadata, payload)
|
|
243
|
+
message = JSON.parse(payload)
|
|
244
|
+
do_stuff(message)
|
|
245
|
+
|
|
246
|
+
ack
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
```
|
|
182
250
|
|
|
183
251
|
```ruby
|
|
184
252
|
my_queue =
|
data/Rakefile
CHANGED
|
@@ -2,13 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
require 'rake/clean'
|
|
4
4
|
require 'bundler/gem_tasks'
|
|
5
|
+
require 'rubocop'
|
|
6
|
+
require 'rubocop/rake_task'
|
|
5
7
|
require 'rspec/core/rake_task'
|
|
6
8
|
require 'yard'
|
|
7
9
|
|
|
8
10
|
CLEAN << '.yardoc'
|
|
9
|
-
CLOBBER << 'doc'
|
|
11
|
+
CLOBBER << 'doc' << 'coverage'
|
|
10
12
|
|
|
11
13
|
RSpec::Core::RakeTask.new(:spec)
|
|
12
14
|
YARD::Rake::YardocTask.new { |t| t.stats_options = %w[--list-undoc] }
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
|
17
|
+
task.formatters = ['simple']
|
|
18
|
+
task.fail_on_error = true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
desc 'Run Prettier'
|
|
22
|
+
task(:prettier) { sh 'npm run lint' }
|
|
23
|
+
|
|
24
|
+
task default: %i[spec rubocop prettier]
|
data/lib/ears/consumer.rb
CHANGED
|
@@ -27,6 +27,29 @@ module Ears
|
|
|
27
27
|
middlewares << middleware.new(opts)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
# Configures the consumer, setting queue, exchange and other options to be used by
|
|
31
|
+
# the add_consumer method.
|
|
32
|
+
#
|
|
33
|
+
# @param [Hash] opts The options to configure the consumer with.
|
|
34
|
+
# @option opts [String] :queue The name of the queue to consume from.
|
|
35
|
+
# @option opts [String] :exchange The name of the exchange the queue should be bound to.
|
|
36
|
+
# @option opts [Array] :routing_keys The routing keys used for the queue binding.
|
|
37
|
+
# @option opts [Boolean] :durable_queue (true) Whether the queue should be durable.
|
|
38
|
+
# @option opts [Boolean] :retry_queue (false) Whether a retry queue should be provided.
|
|
39
|
+
# @option opts [Integer] :retry_delay (5000) The delay in milliseconds before retrying a message.
|
|
40
|
+
# @option opts [Boolean] :error_queue (false) Whether an error queue should be provided.
|
|
41
|
+
# @option opts [Boolean] :durable_exchange (true) Whether the exchange should be durable.
|
|
42
|
+
# @option opts [Symbol] :exchange_type (:topic) The type of exchange to use.
|
|
43
|
+
# @option opts [Integer] :threads (1) The number of threads to use for this consumer.
|
|
44
|
+
def self.configure(opts = {})
|
|
45
|
+
self.queue = opts.fetch(:queue)
|
|
46
|
+
self.exchange = opts.fetch(:exchange)
|
|
47
|
+
self.routing_keys = opts.fetch(:routing_keys)
|
|
48
|
+
self.queue_options = queue_options_from(opts: opts)
|
|
49
|
+
self.durable_exchange = opts.fetch(:durable_exchange, true)
|
|
50
|
+
self.exchange_type = opts.fetch(:exchange_type, :topic)
|
|
51
|
+
end
|
|
52
|
+
|
|
30
53
|
# The method that is called when a message from the queue is received.
|
|
31
54
|
# Keep in mind that the parameters received can be altered by middlewares!
|
|
32
55
|
#
|
|
@@ -101,5 +124,32 @@ module Ears
|
|
|
101
124
|
raise InvalidReturnError, result
|
|
102
125
|
end
|
|
103
126
|
end
|
|
127
|
+
|
|
128
|
+
class << self
|
|
129
|
+
attr_reader :queue,
|
|
130
|
+
:exchange,
|
|
131
|
+
:routing_keys,
|
|
132
|
+
:queue_options,
|
|
133
|
+
:durable_exchange,
|
|
134
|
+
:exchange_type
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
def queue_options_from(opts:)
|
|
139
|
+
{
|
|
140
|
+
durable: opts.fetch(:durable_queue, true),
|
|
141
|
+
retry_queue: opts.fetch(:retry_queue, false),
|
|
142
|
+
retry_delay: opts.fetch(:retry_delay, 5000),
|
|
143
|
+
error_queue: opts.fetch(:error_queue, false),
|
|
144
|
+
}
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
attr_writer :queue,
|
|
148
|
+
:exchange,
|
|
149
|
+
:routing_keys,
|
|
150
|
+
:queue_options,
|
|
151
|
+
:durable_exchange,
|
|
152
|
+
:exchange_type
|
|
153
|
+
end
|
|
104
154
|
end
|
|
105
155
|
end
|
data/lib/ears/setup.rb
CHANGED
|
@@ -58,8 +58,34 @@ module Ears
|
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
# Sets up consumers, including bindings to exchanges and queues.
|
|
62
|
+
#
|
|
63
|
+
# @param [Array<Class<Ears::Consumer>>] consumer_classes An array of subclasses of {Ears::Consumer} that call {Ears::Consumer#configure} in their class definition.
|
|
64
|
+
def setup_consumers(*consumer_classes)
|
|
65
|
+
consumer_classes.each { |consumer_class| setup_consumer(consumer_class) }
|
|
66
|
+
end
|
|
67
|
+
|
|
61
68
|
private
|
|
62
69
|
|
|
70
|
+
def setup_consumer(consumer_class)
|
|
71
|
+
exchange =
|
|
72
|
+
exchange(
|
|
73
|
+
consumer_class.exchange,
|
|
74
|
+
consumer_class.exchange_type,
|
|
75
|
+
durable: consumer_class.durable_exchange,
|
|
76
|
+
)
|
|
77
|
+
configured_queue =
|
|
78
|
+
queue(consumer_class.queue, consumer_class.queue_options)
|
|
79
|
+
bind_queue_to_routing_keys(consumer_class, exchange, configured_queue)
|
|
80
|
+
consumer(configured_queue, consumer_class)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def bind_queue_to_routing_keys(consumer_class, exchange, configured_queue)
|
|
84
|
+
consumer_class.routing_keys.each do |routing_key|
|
|
85
|
+
configured_queue.bind(exchange, routing_key: routing_key)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
63
89
|
def queue_options(bunny_opts, retry_arguments)
|
|
64
90
|
return bunny_opts unless retry_arguments
|
|
65
91
|
|
data/lib/ears/version.rb
CHANGED
data/lib/ears.rb
CHANGED
|
@@ -8,7 +8,6 @@ require 'ears/version'
|
|
|
8
8
|
module Ears
|
|
9
9
|
class << self
|
|
10
10
|
# The global configuration for Ears.
|
|
11
|
-
#
|
|
12
11
|
# @return [Ears::Configuration]
|
|
13
12
|
def configuration
|
|
14
13
|
@configuration ||= Ears::Configuration.new
|
|
@@ -48,6 +47,11 @@ module Ears
|
|
|
48
47
|
Ears::Setup.new.instance_eval(&block)
|
|
49
48
|
end
|
|
50
49
|
|
|
50
|
+
# Quick setup your consumers (including exchanges and queues).
|
|
51
|
+
def setup_consumers(*consumer_classes)
|
|
52
|
+
Ears::Setup.new.setup_consumers(*consumer_classes)
|
|
53
|
+
end
|
|
54
|
+
|
|
51
55
|
# Blocks the calling thread until +SIGTERM+ or +SIGINT+ is received.
|
|
52
56
|
# Used to keep the process alive while processing messages.
|
|
53
57
|
def run!
|
|
@@ -74,9 +78,7 @@ module Ears
|
|
|
74
78
|
|
|
75
79
|
# Used internally for testing.
|
|
76
80
|
def reset!
|
|
77
|
-
@connection = nil
|
|
78
|
-
@configuration = nil
|
|
79
|
-
Thread.current[:ears_channel] = nil
|
|
81
|
+
@configuration = @connection = Thread.current[:ears_channel] = nil
|
|
80
82
|
end
|
|
81
83
|
|
|
82
84
|
private
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ears
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- InVision AG
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-11-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bunny
|