hermes-rb 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog.md +3 -0
- data/Gemfile.lock +16 -18
- data/README.md +40 -2
- data/lib/hermes.rb +5 -0
- data/lib/hermes/b_3_propagation_model_headers.rb +20 -4
- data/lib/hermes/configuration.rb +21 -2
- data/lib/hermes/dependencies_container.rb +12 -0
- data/lib/hermes/event_producer.rb +8 -4
- data/lib/hermes/producer_error_handler.rb +4 -0
- data/lib/hermes/producer_error_handler/null_handler.rb +9 -0
- data/lib/hermes/producer_error_handler/safe_handler.rb +21 -0
- data/lib/hermes/publisher_factory.rb +0 -1
- data/lib/hermes/rb/version.rb +1 -1
- data/lib/hermes/retryable.rb +27 -0
- data/lib/hermes/retryable_event_producer.rb +24 -0
- data/lib/hermes/trace_context.rb +2 -2
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 104554076c3b4ad46491c12d842e3580fdf8c96ba36eefbfc2f4c66a5ba5f208
|
4
|
+
data.tar.gz: a5f1754803e51907feda1164ff25c048731037f4cd75f2a6eaf4db68668b6647
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aea75486bab7ba279b788dc48ea465f3ecb96c7281d9b6cc9bc29443c738ba779fe0951f6d0a8028211cce4f64520556f085cab73aee7ba98bac01af9dc5a973
|
7
|
+
data.tar.gz: 10b79dce9ad5c116d6ccb31a6102b1e3732a2b0a73e328b5ef37b421e5407cc8a5cc240e6b68c11b7fd26bd2c06acb579a610ba3708d83515d5c17dc48207f50
|
data/Changelog.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
hermes-rb (0.
|
4
|
+
hermes-rb (0.2.0)
|
5
5
|
activerecord (>= 5)
|
6
6
|
activesupport (>= 5)
|
7
7
|
dry-container (~> 0)
|
@@ -12,12 +12,12 @@ PATH
|
|
12
12
|
GEM
|
13
13
|
remote: https://rubygems.org/
|
14
14
|
specs:
|
15
|
-
activemodel (6.1.
|
16
|
-
activesupport (= 6.1.
|
17
|
-
activerecord (6.1.
|
18
|
-
activemodel (= 6.1.
|
19
|
-
activesupport (= 6.1.
|
20
|
-
activesupport (6.1.
|
15
|
+
activemodel (6.1.1)
|
16
|
+
activesupport (= 6.1.1)
|
17
|
+
activerecord (6.1.1)
|
18
|
+
activemodel (= 6.1.1)
|
19
|
+
activesupport (= 6.1.1)
|
20
|
+
activesupport (6.1.1)
|
21
21
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
22
22
|
i18n (>= 1.6, < 2)
|
23
23
|
minitest (>= 5.1)
|
@@ -30,21 +30,19 @@ GEM
|
|
30
30
|
json
|
31
31
|
concurrent-ruby (1.1.7)
|
32
32
|
diff-lcs (1.4.4)
|
33
|
-
dry-configurable (0.
|
33
|
+
dry-configurable (0.12.0)
|
34
34
|
concurrent-ruby (~> 1.0)
|
35
|
-
dry-core (~> 0.
|
36
|
-
dry-equalizer (~> 0.2)
|
35
|
+
dry-core (~> 0.5, >= 0.5.0)
|
37
36
|
dry-container (0.7.2)
|
38
37
|
concurrent-ruby (~> 1.0)
|
39
38
|
dry-configurable (~> 0.1, >= 0.1.3)
|
40
|
-
dry-core (0.
|
39
|
+
dry-core (0.5.0)
|
41
40
|
concurrent-ruby (~> 1.0)
|
42
41
|
dry-equalizer (0.3.0)
|
43
42
|
dry-inflector (0.2.0)
|
44
|
-
dry-logic (1.0
|
43
|
+
dry-logic (1.1.0)
|
45
44
|
concurrent-ruby (~> 1.0)
|
46
|
-
dry-core (~> 0.
|
47
|
-
dry-equalizer (~> 0.2)
|
45
|
+
dry-core (~> 0.5, >= 0.5)
|
48
46
|
dry-struct (1.3.0)
|
49
47
|
dry-core (~> 0.4, >= 0.4.4)
|
50
48
|
dry-equalizer (~> 0.3)
|
@@ -62,11 +60,11 @@ GEM
|
|
62
60
|
bunny (>= 2.15, < 2.16)
|
63
61
|
carrot-top (~> 0.0.7)
|
64
62
|
multi_json (~> 1.14)
|
65
|
-
i18n (1.8.
|
63
|
+
i18n (1.8.7)
|
66
64
|
concurrent-ruby (~> 1.0)
|
67
65
|
ice_nine (0.11.2)
|
68
|
-
json (2.
|
69
|
-
minitest (5.14.
|
66
|
+
json (2.5.1)
|
67
|
+
minitest (5.14.3)
|
70
68
|
multi_json (1.15.0)
|
71
69
|
pg (1.2.3)
|
72
70
|
rack (2.2.3)
|
@@ -87,7 +85,7 @@ GEM
|
|
87
85
|
rspec-support (~> 3.10.0)
|
88
86
|
rspec-support (3.10.0)
|
89
87
|
timecop (0.9.2)
|
90
|
-
tzinfo (2.0.
|
88
|
+
tzinfo (2.0.4)
|
91
89
|
concurrent-ruby (~> 1.0)
|
92
90
|
vcr (5.0.0)
|
93
91
|
zeitwerk (2.4.2)
|
data/README.md
CHANGED
@@ -136,10 +136,14 @@ If you don't care about it, you can leave it empty.
|
|
136
136
|
|
137
137
|
13. `distributes_tracing_mapper` - an object responding to `call` method taking one argument (a hash of attributes) that has to return a hash as well. This hash will be used for assigning attributes when creating `Hermes::DistributedTrace`. The default mapper just returns the original hash. You can use it if you want to remove, for example, some sensitive info from the event's body. Optional.
|
138
138
|
|
139
|
-
14. `error_notification_service` - an object responding to `capture_exception` method taking one argument (error).
|
139
|
+
14. `error_notification_service` - an object responding to `capture_exception` method taking one argument (error). Its interface is based on `Raven` from [Sentry Raven](https://github.com/getsentry/sentry-ruby/tree/master/sentry-raven). By default `Hermes::NullErrorNotificationService` is used, which does nothing. Optional.
|
140
140
|
|
141
141
|
15. `database_error_handler` - `an object responding to `call` method taking one argument (error). Used when storing distributed traces. By default it uses `Hermes::DatabaseErrorHandler` which depends on `error_notification_service`, so in most cases, you will probably want to just configure `error_notification_service`. Optional.
|
142
142
|
|
143
|
+
16. `enable_safe_producer` - a method requiring a job class implementing `enqueue` method that will be responsible for retrying delivery of the event later in case it fails. Check `Safe Event Producer` section for more details.
|
144
|
+
|
145
|
+
17. `producer_retryable` - used when `safe_producer` was enabled via (`enable_safe_producer`). By default, it is a method retrying delivery 3 times rescuing from `StandardError` each time. The object responsible for this behavior by default is: `Hermes::Retryable.new(times: 3, errors: [StandardError])`.
|
146
|
+
|
143
147
|
## RPC
|
144
148
|
|
145
149
|
If you want to handle RPC call, you need to add `rpc: true` flag. Keep in mind that RPC requires a synchronous processing and response, so you also need to set `async: false`. The routing key and correlation ID will be resolved based on the message that is published by the client. The payload that is sent back will be what event handler reutrns, so it might be a good idea to just return a hash so that you can operate on JSON easily.
|
@@ -226,6 +230,40 @@ It is highly recommended to use a shared database for storing traces. It's not i
|
|
226
230
|
|
227
231
|
Since distributed tracing is a secondary feature, all exceptions coming from the database are rescued. It is highly recommended to provide `error_notification_service` to be notified about these errors. If you are not happy with that behavior and you would prefer to have errors raised, you can implement your own `database_error_handler` where you can re-raise the exception.
|
228
232
|
|
233
|
+
## Safe Event Producer
|
234
|
+
|
235
|
+
Most likely in your production environment you are going to have a high availability setup with more than one node, probably at least 3. This might seem like there is very little chance that something will go wrong when publishing an event to RabbitMQ and even if it happens, it will be so rare that you will handle any exceptions manually. However, operations like updating Erlang will most likely require a downtime, which will mean that you might have a lot of errors during that period. Not to mention other potential issues, even without scheduled downtime, like the entire cluster being down for random reason or timeouts.
|
236
|
+
|
237
|
+
In that case, it might be a good idea to have some automated way of dealing with this kind of issues. For that purpose, you can enable a `Safe Event Producer` - by default, it's going to try publishing event 3 times, rescuing twice from `StandardError`, and if it fails after a 3rd time, it's going to use `error_notification_service` to deliver info about the error that ahppened and is going to call `enqueue` method on a specified object.
|
238
|
+
|
239
|
+
To take advantage of this feature, apply the following logic in the initializer
|
240
|
+
|
241
|
+
``` rb
|
242
|
+
Hermes.configure do |config|
|
243
|
+
config.clock = clock
|
244
|
+
config.error_notification_service = Raven
|
245
|
+
config.enable_safe_producer(HermesRecoveryJob)
|
246
|
+
end
|
247
|
+
```
|
248
|
+
|
249
|
+
`HermesRecoveryJob` is expected to implement `enqueue` method taking 3 arguments: `event_class_name`, `event_body` and `headers`. What happens in `enqueue` method is up to you. You can, for example, schedule publishing the message in 5 minutes from now. However, the job should call `Hermes::RetryableEventProducer.publish(event_class, event_body, headers)` to properly handle the delivery retry flow. Here is an example job class using Sidekiq:
|
250
|
+
|
251
|
+
``` rb
|
252
|
+
class HermesRecoveryJob
|
253
|
+
include Sidekiq::Worker
|
254
|
+
|
255
|
+
sidekiq_options queue: :hermes_recovery
|
256
|
+
|
257
|
+
def self.enqueue(event_class, event_body, origin_headers)
|
258
|
+
perform_at(5.minutes.from_now, event_class, event_body, origin_headers)
|
259
|
+
end
|
260
|
+
|
261
|
+
def perform(event_class, event_body, origin_headers)
|
262
|
+
Hermes::RetryableEventProducer.publish(event_class, event_body, origin_headers)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
```
|
266
|
+
|
229
267
|
## Testing
|
230
268
|
|
231
269
|
### RSpec useful stuff
|
@@ -395,7 +433,7 @@ RSpec.describe HermesHandlerJob do
|
|
395
433
|
end
|
396
434
|
```
|
397
435
|
|
398
|
-
## Deployment and managing
|
436
|
+
## Deployment and managing consumers
|
399
437
|
|
400
438
|
Hermes is just an extra layer on top of [hutch](https://github.com/gocardless/hutch), refer to Hutch's docs for more info about dealing with the workers and deployment.
|
401
439
|
|
data/lib/hermes.rb
CHANGED
@@ -18,6 +18,11 @@ require "hermes/distributed_trace_repository"
|
|
18
18
|
require "hermes/dependencies_container"
|
19
19
|
require "hermes/null_error_notification_service"
|
20
20
|
require "hermes/database_error_handler"
|
21
|
+
require "hermes/retryable"
|
22
|
+
require "hermes/retryable_event_producer"
|
23
|
+
require "hermes/producer_error_handler"
|
24
|
+
require "hermes/producer_error_handler/null_handler"
|
25
|
+
require "hermes/producer_error_handler/safe_handler"
|
21
26
|
require "active_support"
|
22
27
|
require "active_support/core_ext/string"
|
23
28
|
require "active_record"
|
@@ -3,6 +3,22 @@ module Hermes
|
|
3
3
|
attr_reader :trace_context
|
4
4
|
private :trace_context
|
5
5
|
|
6
|
+
def self.trace_id_key
|
7
|
+
"X-B3-TraceId"
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.span_id_key
|
11
|
+
"X-B3-SpanId"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.parent_span_id_key
|
15
|
+
"X-B3-ParentSpanId"
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.sampled_key
|
19
|
+
"X-B3-Sampled"
|
20
|
+
end
|
21
|
+
|
6
22
|
def initialize(trace_context)
|
7
23
|
@trace_context = trace_context
|
8
24
|
end
|
@@ -13,10 +29,10 @@ module Hermes
|
|
13
29
|
|
14
30
|
def to_h
|
15
31
|
{
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
32
|
+
self.class.trace_id_key => trace_context.trace,
|
33
|
+
self.class.parent_span_id_key => trace_context.parent_span,
|
34
|
+
self.class.span_id_key => trace_context.span,
|
35
|
+
self.class.sampled_key => ""
|
20
36
|
}
|
21
37
|
end
|
22
38
|
end
|
data/lib/hermes/configuration.rb
CHANGED
@@ -3,7 +3,8 @@ module Hermes
|
|
3
3
|
attr_accessor :adapter, :clock, :hutch, :application_prefix, :logger,
|
4
4
|
:background_processor, :enqueue_method, :event_handler, :rpc_call_timeout,
|
5
5
|
:instrumenter, :distributed_tracing_database_uri, :distributed_tracing_database_table,
|
6
|
-
:distributes_tracing_mapper, :database_error_handler, :error_notification_service
|
6
|
+
:distributes_tracing_mapper, :database_error_handler, :error_notification_service, :producer_error_handler,
|
7
|
+
:producer_error_handler_job_class, :producer_retryable
|
7
8
|
|
8
9
|
def configure_hutch
|
9
10
|
yield hutch
|
@@ -38,7 +39,7 @@ module Hermes
|
|
38
39
|
end
|
39
40
|
|
40
41
|
def distributes_tracing_mapper=(mapper)
|
41
|
-
raise ArgumentError.new("mapper must
|
42
|
+
raise ArgumentError.new("mapper must respond to :call method") if !mapper.respond_to?(:call)
|
42
43
|
@distributes_tracing_mapper = mapper
|
43
44
|
end
|
44
45
|
|
@@ -54,6 +55,24 @@ module Hermes
|
|
54
55
|
@database_error_handler || Hermes::DatabaseErrorHandler.new(error_notification_service: error_notification_service)
|
55
56
|
end
|
56
57
|
|
58
|
+
def producer_error_handler
|
59
|
+
@producer_error_handler || Hermes::ProducerErrorHandler::NullHandler
|
60
|
+
end
|
61
|
+
|
62
|
+
def producer_retryable
|
63
|
+
@producer_retryable || Hermes::Retryable.new(times: 3, errors: [StandardError])
|
64
|
+
end
|
65
|
+
|
66
|
+
def enable_safe_producer(producer_error_handler_job_class)
|
67
|
+
self.producer_error_handler_job_class = producer_error_handler_job_class
|
68
|
+
|
69
|
+
@producer_error_handler = Hermes::ProducerErrorHandler::SafeHandler.new(
|
70
|
+
job_class: producer_error_handler_job_class,
|
71
|
+
error_notifier: error_notification_service,
|
72
|
+
retryable: producer_retryable
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
57
76
|
class HutchConfig
|
58
77
|
attr_accessor :uri
|
59
78
|
end
|
@@ -64,5 +64,17 @@ module Hermes
|
|
64
64
|
def self.database_error_handler
|
65
65
|
config.database_error_handler
|
66
66
|
end
|
67
|
+
|
68
|
+
def self.producer_error_handler
|
69
|
+
config.producer_error_handler
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.producer_retryable
|
73
|
+
config.producer_retryable
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.objects_resolver
|
77
|
+
Object
|
78
|
+
end
|
67
79
|
end
|
68
80
|
end
|
@@ -2,8 +2,8 @@ module Hermes
|
|
2
2
|
class EventProducer
|
3
3
|
extend Forwardable
|
4
4
|
|
5
|
-
attr_reader :publisher, :serializer, :distributed_trace_repository, :config
|
6
|
-
private :publisher, :serializer, :distributed_trace_repository, :config
|
5
|
+
attr_reader :publisher, :serializer, :distributed_trace_repository, :producer_error_handler, :config
|
6
|
+
private :publisher, :serializer, :distributed_trace_repository, :producer_error_handler, :config
|
7
7
|
|
8
8
|
def self.publish(event, properties = {}, options = {})
|
9
9
|
build.publish(event, properties, options)
|
@@ -14,19 +14,23 @@ module Hermes
|
|
14
14
|
publisher: Hermes::DependenciesContainer["publisher"],
|
15
15
|
serializer: Hermes::DependenciesContainer["serializer"],
|
16
16
|
distributed_trace_repository: Hermes::DependenciesContainer["distributed_trace_repository"],
|
17
|
+
producer_error_handler: Hermes::DependenciesContainer["producer_error_handler"],
|
17
18
|
config: Hermes::DependenciesContainer["config"]
|
18
19
|
)
|
19
20
|
end
|
20
21
|
|
21
|
-
def initialize(publisher:, serializer:, distributed_trace_repository:, config:)
|
22
|
+
def initialize(publisher:, serializer:, distributed_trace_repository:, producer_error_handler:, config:)
|
22
23
|
@publisher = publisher
|
23
24
|
@serializer = serializer
|
24
25
|
@distributed_trace_repository = distributed_trace_repository
|
26
|
+
@producer_error_handler = producer_error_handler
|
25
27
|
@config = config
|
26
28
|
end
|
27
29
|
|
28
30
|
def publish(event, properties = {}, options = {})
|
29
|
-
|
31
|
+
producer_error_handler.call(event) do
|
32
|
+
publish_event(event, properties, options).tap { store_trace(event) }
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
private
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Hermes
|
2
|
+
module ProducerErrorHandler
|
3
|
+
class SafeHandler
|
4
|
+
attr_reader :job_class, :error_notifier, :retryable
|
5
|
+
private :job_class, :error_notifier, :retryable
|
6
|
+
|
7
|
+
def initialize(job_class:, error_notifier:, retryable:)
|
8
|
+
@job_class = job_class
|
9
|
+
@error_notifier = error_notifier
|
10
|
+
@retryable = retryable
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(event)
|
14
|
+
retryable.perform { yield }
|
15
|
+
rescue => error
|
16
|
+
error_notifier.capture_exception(error)
|
17
|
+
job_class.enqueue(event.class.name, event.as_json, event.origin_headers)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/hermes/rb/version.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Hermes
|
2
|
+
class Retryable
|
3
|
+
attr_reader :times, :errors, :before_retry
|
4
|
+
private :times, :errors, :before_retry
|
5
|
+
|
6
|
+
def initialize(times:, errors: [], before_retry: ->(_error) {})
|
7
|
+
@times = times
|
8
|
+
@errors = errors
|
9
|
+
@before_retry = before_retry
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform
|
13
|
+
executed = 0
|
14
|
+
begin
|
15
|
+
executed += 1
|
16
|
+
yield
|
17
|
+
rescue *errors => error
|
18
|
+
if executed < times
|
19
|
+
before_retry.call(error)
|
20
|
+
retry
|
21
|
+
else
|
22
|
+
raise error
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Hermes
|
2
|
+
class RetryableEventProducer
|
3
|
+
def self.publish(event_class, event_body, origin_headers)
|
4
|
+
new(
|
5
|
+
objects_resolver: Hermes::DependenciesContainer["objects_resolver"],
|
6
|
+
event_producer: Hermes::DependenciesContainer["event_producer"]
|
7
|
+
).publish(event_class, event_body, origin_headers)
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :objects_resolver, :event_producer
|
11
|
+
private :objects_resolver, :event_producer
|
12
|
+
|
13
|
+
def initialize(objects_resolver:, event_producer:)
|
14
|
+
@objects_resolver = objects_resolver
|
15
|
+
@event_producer = event_producer
|
16
|
+
end
|
17
|
+
|
18
|
+
def publish(event_class, event_body, origin_headers)
|
19
|
+
event = objects_resolver.const_get(event_class).new(event_body.deep_symbolize_keys)
|
20
|
+
event.origin_headers = origin_headers.except(Hermes::B3PropagationModelHeaders.span_id_key)
|
21
|
+
event_producer.publish(event)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/hermes/trace_context.rb
CHANGED
@@ -12,7 +12,7 @@ module Hermes
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def trace
|
15
|
-
@trace ||= origin_event_headers.fetch(
|
15
|
+
@trace ||= origin_event_headers.fetch(Hermes::B3PropagationModelHeaders.trace_id_key, SecureRandom.hex(32))
|
16
16
|
end
|
17
17
|
|
18
18
|
def span
|
@@ -20,7 +20,7 @@ module Hermes
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def parent_span
|
23
|
-
origin_event_headers.fetch(
|
23
|
+
origin_event_headers.fetch(Hermes::B3PropagationModelHeaders.span_id_key, nil)
|
24
24
|
end
|
25
25
|
|
26
26
|
def service
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hermes-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karol Galanciak
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-01-
|
11
|
+
date: 2021-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-struct
|
@@ -214,12 +214,17 @@ files:
|
|
214
214
|
- lib/hermes/logger.rb
|
215
215
|
- lib/hermes/null_error_notification_service.rb
|
216
216
|
- lib/hermes/null_instrumenter.rb
|
217
|
+
- lib/hermes/producer_error_handler.rb
|
218
|
+
- lib/hermes/producer_error_handler/null_handler.rb
|
219
|
+
- lib/hermes/producer_error_handler/safe_handler.rb
|
217
220
|
- lib/hermes/publisher.rb
|
218
221
|
- lib/hermes/publisher/hutch_adapter.rb
|
219
222
|
- lib/hermes/publisher/in_memory_adapter.rb
|
220
223
|
- lib/hermes/publisher_factory.rb
|
221
224
|
- lib/hermes/rb.rb
|
222
225
|
- lib/hermes/rb/version.rb
|
226
|
+
- lib/hermes/retryable.rb
|
227
|
+
- lib/hermes/retryable_event_producer.rb
|
223
228
|
- lib/hermes/rpc_client.rb
|
224
229
|
- lib/hermes/serializer.rb
|
225
230
|
- lib/hermes/support/matchers/publish_async_message.rb
|
@@ -247,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
247
252
|
- !ruby/object:Gem::Version
|
248
253
|
version: '0'
|
249
254
|
requirements: []
|
250
|
-
rubygems_version: 3.1.
|
255
|
+
rubygems_version: 3.1.2
|
251
256
|
signing_key:
|
252
257
|
specification_version: 4
|
253
258
|
summary: A messenger of gods, delivering them via RabbitMQ with a little help from
|