event_people 1.1.0 → 1.2.1
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/.event_people.yml +5 -5
- data/Gemfile.lock +1 -1
- data/README.md +59 -0
- data/lib/event_people/broker/base.rb +3 -3
- data/lib/event_people/broker/context.rb +8 -0
- data/lib/event_people/broker/rabbit/queue.rb +43 -11
- data/lib/event_people/broker/rabbit/rabbit_context.rb +47 -5
- data/lib/event_people/broker/rabbit/retry_manager.rb +25 -0
- data/lib/event_people/broker/rabbit.rb +2 -2
- data/lib/event_people/config.rb +12 -0
- data/lib/event_people/event.rb +7 -2
- data/lib/event_people/listener.rb +9 -4
- data/lib/event_people/version.rb +1 -1
- data/lib/event_people.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c7f60b5a8806b69e26b0f66ea3a547e92200f460df4f30a2df90eed2fa08641d
|
|
4
|
+
data.tar.gz: 343c7a4e19f4a0194e552b507f3d000a1fd723faf374a35faee8961527c1809f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dbd234e3c4df60f769feb130c05b8d96421677e8e297704b5620f41749ba3a507bfae2d22af9c020612d5fbb2b1f426bc427b8e71f476235de68a1fb806e1e38
|
|
7
|
+
data.tar.gz: 791f1ee04535ed6eef1d3fd9cb5771da399b336b946d9b4fef7f46b43d362781c6698a26aafac727620ef792f93a2f8fab6f2e59f3460655073c8a2937ab8600
|
data/.event_people.yml
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
spec_version: "1.1.
|
|
2
|
-
implementation_version: "1.1
|
|
1
|
+
spec_version: "1.1.1"
|
|
2
|
+
implementation_version: "1.2.1"
|
|
3
3
|
language: ruby
|
|
4
4
|
package: "event_people (RubyGems)"
|
|
5
5
|
status: stable
|
|
@@ -19,9 +19,6 @@ implemented:
|
|
|
19
19
|
- RabbitContext
|
|
20
20
|
- Topic
|
|
21
21
|
- Queue
|
|
22
|
-
|
|
23
|
-
# Spec components not yet implemented (pending in spec too)
|
|
24
|
-
pending:
|
|
25
22
|
- RetryManager
|
|
26
23
|
- "Event.retryCount"
|
|
27
24
|
- "Event.incrementRetryCount"
|
|
@@ -36,6 +33,9 @@ pending:
|
|
|
36
33
|
- "RabbitContext.isLastRetry"
|
|
37
34
|
- "RabbitContext.dlqName"
|
|
38
35
|
|
|
36
|
+
# Spec components not yet implemented (pending in spec too)
|
|
37
|
+
pending: []
|
|
38
|
+
|
|
39
39
|
# Structural or naming departures from the spec
|
|
40
40
|
# (Ruby module-qualified class names are an accepted adaptation, not a deviation)
|
|
41
41
|
deviations: []
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -220,6 +220,65 @@ EventPeople::Daemon.start
|
|
|
220
220
|
```
|
|
221
221
|
[See more details](https://github.com/pin-people/event_people_ruby/blob/master/examples/daemon.rb)
|
|
222
222
|
|
|
223
|
+
## Retry and Dead Letter Queue (DLQ)
|
|
224
|
+
|
|
225
|
+
### Environment variables
|
|
226
|
+
|
|
227
|
+
| Variable | Description | Default |
|
|
228
|
+
|---|---|---|
|
|
229
|
+
| `RABBIT_EVENT_PEOPLE_MAX_RETRIES` | Max retry attempts before dead-lettering | `3` |
|
|
230
|
+
| `RABBIT_EVENT_PEOPLE_RETRY_TTL_MS` | Base delay in ms for retry backoff | `1000` |
|
|
231
|
+
|
|
232
|
+
### How it works
|
|
233
|
+
|
|
234
|
+
On `context.fail`:
|
|
235
|
+
- If retries remain → message published to `{queue}_retry` with exponential backoff delay, then acked
|
|
236
|
+
- If retries exhausted → nacked to DLQ via RabbitMQ DLX
|
|
237
|
+
|
|
238
|
+
On `context.reject` → nacked directly to DLQ (no retries)
|
|
239
|
+
|
|
240
|
+
**Delay strategies:**
|
|
241
|
+
- `exponential` (default): `min(initialDelay × 5^retry_count, 600000)` ms
|
|
242
|
+
- `fixed`: constant `initialDelay` ms
|
|
243
|
+
|
|
244
|
+
### Queue topology (auto-created on subscribe)
|
|
245
|
+
|
|
246
|
+
| Queue/Exchange | Name | Purpose |
|
|
247
|
+
|---|---|---|
|
|
248
|
+
| Exchange (DLX) | `{app_name}_dlx` | Fanout, receives dead-lettered messages |
|
|
249
|
+
| DLQ | `{app_name}_dlq` | Final resting place for failed messages |
|
|
250
|
+
| Retry queue | `{queue_name}_retry` | Holds messages until backoff delay expires |
|
|
251
|
+
|
|
252
|
+
### Usage
|
|
253
|
+
|
|
254
|
+
```ruby
|
|
255
|
+
class OrderListener < EventPeople::Listeners::Base
|
|
256
|
+
bind :handle_created, 'order.service.created'
|
|
257
|
+
|
|
258
|
+
def handle_created(event)
|
|
259
|
+
puts "Attempt #{event.retry_count + 1} of #{context.max_retries}"
|
|
260
|
+
|
|
261
|
+
if invalid?(event)
|
|
262
|
+
reject # → DLQ immediately, no retries
|
|
263
|
+
return
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
process(event)
|
|
267
|
+
success
|
|
268
|
+
rescue StandardError
|
|
269
|
+
puts 'Final attempt, sending to DLQ' if context.is_last_retry
|
|
270
|
+
fail # → retry queue (or DLQ if exhausted)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Per-listener retry config (overrides env var defaults)
|
|
275
|
+
EventPeople::Listener.on('order.service.created', method(:handle),
|
|
276
|
+
max_attempts: 5,
|
|
277
|
+
delay_strategy: 'exponential')
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
> **Note:** `success!`, `fail!`, `reject!` still work but are deprecated — prefer `success`, `fail`, `reject`.
|
|
281
|
+
|
|
223
282
|
## Development
|
|
224
283
|
|
|
225
284
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
@@ -15,13 +15,13 @@ module EventPeople
|
|
|
15
15
|
raise NotImplementedError.new('Must be implemented')
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def self.consume(event_name, &block)
|
|
18
|
+
def self.consume(event_name, retry_config: {}, &block)
|
|
19
19
|
consumers[event_name] ||= begin
|
|
20
|
-
new.consume(event_name, &block)
|
|
20
|
+
new.consume(event_name, retry_config: retry_config, &block)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def consume(event_name, &block)
|
|
24
|
+
def consume(event_name, retry_config: {}, &block)
|
|
25
25
|
raise NotImplementedError.new('Must be implemented')
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -13,6 +13,14 @@ module EventPeople
|
|
|
13
13
|
raise NotImplementedError.new('Must be implemented')
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
def max_retries
|
|
17
|
+
raise NotImplementedError.new('Must be implemented')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def is_last_retry
|
|
21
|
+
raise NotImplementedError.new('Must be implemented')
|
|
22
|
+
end
|
|
23
|
+
|
|
16
24
|
def success!
|
|
17
25
|
warn '[DEPRECATED] EventPeople: `success!` is deprecated, use `success` instead. Will be removed in a future version.'
|
|
18
26
|
success
|
|
@@ -6,18 +6,21 @@ module EventPeople
|
|
|
6
6
|
@channel.prefetch(1)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def self.subscribe(channel, routing_key, &block)
|
|
10
|
-
new(channel).subscribe(routing_key, &block)
|
|
9
|
+
def self.subscribe(channel, routing_key, retry_config: {}, &block)
|
|
10
|
+
new(channel).subscribe(routing_key, retry_config: retry_config, &block)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def subscribe(routing_key, &block)
|
|
13
|
+
def subscribe(routing_key, retry_config: {}, &block)
|
|
14
14
|
base_name = routing_key.split('.')[0..2].join('.')
|
|
15
15
|
name = queue_name("#{base_name}.all")
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
declare_dlx_and_dlq
|
|
18
|
+
declare_retry_queue(name)
|
|
19
|
+
|
|
20
|
+
channel.queue(name, main_queue_options)
|
|
18
21
|
.bind(topic, routing_key: routing_key)
|
|
19
22
|
.subscribe(manual_ack: true) do |delivery_info, properties, payload|
|
|
20
|
-
callback(delivery_info, properties, payload, &block)
|
|
23
|
+
callback(delivery_info, properties, payload, name, retry_config, &block)
|
|
21
24
|
end
|
|
22
25
|
end
|
|
23
26
|
|
|
@@ -25,11 +28,37 @@ module EventPeople
|
|
|
25
28
|
|
|
26
29
|
attr_reader :channel
|
|
27
30
|
|
|
28
|
-
def
|
|
29
|
-
|
|
31
|
+
def declare_dlx_and_dlq
|
|
32
|
+
dlx_name = "#{EventPeople::Config::APP_NAME}_dlx"
|
|
33
|
+
dlq_name = "#{EventPeople::Config::APP_NAME}_dlq"
|
|
34
|
+
|
|
35
|
+
dlx = channel.fanout(dlx_name, durable: true)
|
|
36
|
+
channel.queue(dlq_name, durable: true).bind(dlx, routing_key: '')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def declare_retry_queue(main_queue_name)
|
|
40
|
+
channel.queue("#{main_queue_name}_retry", durable: true, arguments: {
|
|
41
|
+
'x-dead-letter-exchange' => '',
|
|
42
|
+
'x-dead-letter-routing-key' => main_queue_name
|
|
43
|
+
})
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def callback(delivery_info, properties, payload, queue_name, retry_config, &block)
|
|
47
|
+
event_name = delivery_info.routing_key
|
|
48
|
+
retry_count = [(properties.headers&.dig('x-event-people-retries') || 0).to_i, 0].max
|
|
49
|
+
|
|
50
|
+
event = EventPeople::Event.new(event_name, payload, 1.0, retry_count: retry_count)
|
|
30
51
|
|
|
31
|
-
|
|
32
|
-
|
|
52
|
+
context = EventPeople::Broker::Rabbit::RabbitContext.new(
|
|
53
|
+
channel,
|
|
54
|
+
delivery_info,
|
|
55
|
+
retry_count: retry_count,
|
|
56
|
+
max_retries: retry_config[:max_attempts],
|
|
57
|
+
delay_strategy: retry_config[:delay_strategy],
|
|
58
|
+
dlq_name: retry_config[:dlq_name],
|
|
59
|
+
queue_name: queue_name,
|
|
60
|
+
original_payload: payload
|
|
61
|
+
)
|
|
33
62
|
|
|
34
63
|
block.call(event, context)
|
|
35
64
|
end
|
|
@@ -38,8 +67,11 @@ module EventPeople
|
|
|
38
67
|
Rabbit::Topic.topic(channel)
|
|
39
68
|
end
|
|
40
69
|
|
|
41
|
-
def
|
|
42
|
-
{
|
|
70
|
+
def main_queue_options
|
|
71
|
+
{
|
|
72
|
+
durable: true,
|
|
73
|
+
arguments: { 'x-dead-letter-exchange' => "#{EventPeople::Config::APP_NAME}_dlx" }
|
|
74
|
+
}
|
|
43
75
|
end
|
|
44
76
|
|
|
45
77
|
def queue_name(routing_key)
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
module EventPeople
|
|
2
2
|
module Broker
|
|
3
3
|
class Rabbit::RabbitContext < EventPeople::Broker::Context
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
attr_reader :max_retries, :dlq_name
|
|
5
|
+
|
|
6
|
+
def initialize(channel, delivery_info, retry_count: 0, max_retries: nil, delay_strategy: nil, dlq_name: nil, queue_name: nil, original_payload: nil)
|
|
7
|
+
@channel = channel
|
|
8
|
+
@delivery_info = delivery_info
|
|
9
|
+
@retry_count = retry_count.to_i
|
|
10
|
+
@max_retries = (max_retries || EventPeople::Config::MAX_ATTEMPTS).to_i
|
|
11
|
+
@delay_strategy = delay_strategy || EventPeople::Config::DELAY_STRATEGY
|
|
12
|
+
@dlq_name = dlq_name || EventPeople::Config::DLQ_NAME
|
|
13
|
+
@queue_name = queue_name
|
|
14
|
+
@original_payload = original_payload
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def is_last_retry
|
|
18
|
+
@retry_count >= @max_retries - 1
|
|
7
19
|
end
|
|
8
20
|
|
|
9
21
|
def success
|
|
@@ -11,7 +23,37 @@ module EventPeople
|
|
|
11
23
|
end
|
|
12
24
|
|
|
13
25
|
def fail
|
|
14
|
-
|
|
26
|
+
retry_manager = Rabbit::RetryManager.new(@max_retries, @delay_strategy)
|
|
27
|
+
|
|
28
|
+
if retry_manager.should_retry?(@retry_count)
|
|
29
|
+
delay = retry_manager.get_next_delay(@retry_count)
|
|
30
|
+
begin
|
|
31
|
+
@channel.default_exchange.publish(
|
|
32
|
+
@original_payload,
|
|
33
|
+
routing_key: "#{@queue_name}_retry",
|
|
34
|
+
expiration: delay.to_s,
|
|
35
|
+
headers: { 'x-event-people-retries' => @retry_count + 1 }
|
|
36
|
+
)
|
|
37
|
+
rescue => e
|
|
38
|
+
# Publish failed — nack without requeue so the DLX routes to DLQ.
|
|
39
|
+
# Requeuing without incrementing x-event-people-retries would cause an infinite loop.
|
|
40
|
+
begin
|
|
41
|
+
@channel.nack(@delivery_info.delivery_tag, false, false)
|
|
42
|
+
rescue
|
|
43
|
+
# Channel may already be closed; nothing we can do.
|
|
44
|
+
end
|
|
45
|
+
raise e
|
|
46
|
+
end
|
|
47
|
+
begin
|
|
48
|
+
@channel.ack(@delivery_info.delivery_tag, false)
|
|
49
|
+
rescue
|
|
50
|
+
# Publish already succeeded; swallow ack errors. The message may be redelivered
|
|
51
|
+
# once (at-least-once), but that is safer than nacking to DLQ when a retry copy
|
|
52
|
+
# is already enqueued.
|
|
53
|
+
end
|
|
54
|
+
else
|
|
55
|
+
@channel.nack(@delivery_info.delivery_tag, false, false)
|
|
56
|
+
end
|
|
15
57
|
end
|
|
16
58
|
|
|
17
59
|
def reject
|
|
@@ -19,4 +61,4 @@ module EventPeople
|
|
|
19
61
|
end
|
|
20
62
|
end
|
|
21
63
|
end
|
|
22
|
-
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module EventPeople
|
|
2
|
+
module Broker
|
|
3
|
+
class Rabbit::RetryManager
|
|
4
|
+
INITIAL_DELAY = (ENV['RABBIT_EVENT_PEOPLE_RETRY_TTL_MS'] || 1000).to_i
|
|
5
|
+
MAX_DELAY = 600_000
|
|
6
|
+
|
|
7
|
+
def initialize(max_attempts, delay_strategy = 'exponential')
|
|
8
|
+
@max_attempts = max_attempts
|
|
9
|
+
@delay_strategy = delay_strategy
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def should_retry?(retry_count)
|
|
13
|
+
retry_count < @max_attempts
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def get_next_delay(retry_count)
|
|
17
|
+
if @delay_strategy == 'fixed'
|
|
18
|
+
INITIAL_DELAY
|
|
19
|
+
else
|
|
20
|
+
[INITIAL_DELAY * (5**retry_count), MAX_DELAY].min
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -5,8 +5,8 @@ module EventPeople
|
|
|
5
5
|
@@connection ||= session
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
def consume(event_name, &block)
|
|
9
|
-
Queue.subscribe(channel, event_name, &block)
|
|
8
|
+
def consume(event_name, retry_config: {}, &block)
|
|
9
|
+
Queue.subscribe(channel, event_name, retry_config: retry_config, &block)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def produce(events)
|
data/lib/event_people/config.rb
CHANGED
|
@@ -6,8 +6,20 @@ module EventPeople
|
|
|
6
6
|
URL = ENV['RABBIT_URL']
|
|
7
7
|
FULL_URL = "#{ENV['RABBIT_URL']}/#{ENV['RABBIT_EVENT_PEOPLE_VHOST']}"
|
|
8
8
|
|
|
9
|
+
MAX_ATTEMPTS = (ENV['RABBIT_EVENT_PEOPLE_MAX_RETRIES'] || 3).to_i
|
|
10
|
+
DELAY_STRATEGY = 'exponential'
|
|
11
|
+
DLQ_NAME = "#{ENV['RABBIT_EVENT_PEOPLE_APP_NAME']}_dlq"
|
|
12
|
+
|
|
9
13
|
def self.broker
|
|
10
14
|
EventPeople::Broker::Rabbit
|
|
11
15
|
end
|
|
16
|
+
|
|
17
|
+
def self.get_retry_config
|
|
18
|
+
{
|
|
19
|
+
max_attempts: MAX_ATTEMPTS,
|
|
20
|
+
delay_strategy: DELAY_STRATEGY,
|
|
21
|
+
dlq_name: DLQ_NAME
|
|
22
|
+
}
|
|
23
|
+
end
|
|
12
24
|
end
|
|
13
25
|
end
|
data/lib/event_people/event.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
module EventPeople
|
|
2
2
|
class Event
|
|
3
|
-
attr_reader :name, :headers, :body, :schema_version
|
|
3
|
+
attr_reader :name, :headers, :body, :schema_version, :retry_count
|
|
4
4
|
|
|
5
|
-
def initialize(name, body, schema_version = 1.0)
|
|
5
|
+
def initialize(name, body, schema_version = 1.0, retry_count: 0)
|
|
6
6
|
@name = name
|
|
7
7
|
@body = body.is_a?(String) ? JSON.parse(body) : body
|
|
8
8
|
@schema_version = @body&.dig('headers', 'schemaVersion') || schema_version
|
|
9
|
+
@retry_count = retry_count.to_i
|
|
9
10
|
|
|
10
11
|
if name?
|
|
11
12
|
generate_headers
|
|
@@ -15,6 +16,10 @@ module EventPeople
|
|
|
15
16
|
build_payload if @body&.key?('headers')
|
|
16
17
|
end
|
|
17
18
|
|
|
19
|
+
def increment_retry_count
|
|
20
|
+
@retry_count += 1
|
|
21
|
+
end
|
|
22
|
+
|
|
18
23
|
def payload
|
|
19
24
|
{ headers: headers, body: body }.to_json
|
|
20
25
|
end
|
|
@@ -2,16 +2,21 @@ require 'bunny'
|
|
|
2
2
|
|
|
3
3
|
module EventPeople
|
|
4
4
|
class Listener
|
|
5
|
-
def self.on(event_name, &block)
|
|
6
|
-
new.on(event_name, &block)
|
|
5
|
+
def self.on(event_name, max_attempts: nil, delay_strategy: nil, dlq_name: nil, &block)
|
|
6
|
+
new.on(event_name, max_attempts: max_attempts, delay_strategy: delay_strategy, dlq_name: dlq_name, &block)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def on(event_name, &block)
|
|
9
|
+
def on(event_name, max_attempts: nil, delay_strategy: nil, dlq_name: nil, &block)
|
|
10
10
|
raise(MissingAttributeError, 'Event name must be present') unless event_name&.size&.positive?
|
|
11
11
|
|
|
12
12
|
event_name = consumed_event_name(event_name)
|
|
13
13
|
|
|
14
|
-
EventPeople::Config.
|
|
14
|
+
retry_config = EventPeople::Config.get_retry_config
|
|
15
|
+
retry_config[:max_attempts] = max_attempts unless max_attempts.nil?
|
|
16
|
+
retry_config[:delay_strategy] = delay_strategy unless delay_strategy.nil?
|
|
17
|
+
retry_config[:dlq_name] = dlq_name unless dlq_name.nil?
|
|
18
|
+
|
|
19
|
+
EventPeople::Config.broker.consume(event_name, retry_config: retry_config, &block)
|
|
15
20
|
end
|
|
16
21
|
|
|
17
22
|
private
|
data/lib/event_people/version.rb
CHANGED
data/lib/event_people.rb
CHANGED
|
@@ -11,6 +11,7 @@ require 'event_people/broker/context'
|
|
|
11
11
|
require 'event_people/broker/rabbit'
|
|
12
12
|
require 'event_people/broker/rabbit/queue'
|
|
13
13
|
require 'event_people/broker/rabbit/rabbit_context'
|
|
14
|
+
require 'event_people/broker/rabbit/retry_manager'
|
|
14
15
|
require 'event_people/broker/rabbit/topic'
|
|
15
16
|
|
|
16
17
|
module EventPeople
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: event_people
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1
|
|
4
|
+
version: 1.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Pin People
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -109,6 +109,7 @@ files:
|
|
|
109
109
|
- lib/event_people/broker/rabbit.rb
|
|
110
110
|
- lib/event_people/broker/rabbit/queue.rb
|
|
111
111
|
- lib/event_people/broker/rabbit/rabbit_context.rb
|
|
112
|
+
- lib/event_people/broker/rabbit/retry_manager.rb
|
|
112
113
|
- lib/event_people/broker/rabbit/topic.rb
|
|
113
114
|
- lib/event_people/config.rb
|
|
114
115
|
- lib/event_people/daemon.rb
|