hermes-rb 0.7.1 → 0.7.3

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: 8f84d7c23f44dbdf7aabfa38122dd94c231c907b04d4aabe6ec444feef5ba7b2
4
- data.tar.gz: 2eaf59a2dbca4952a7eaaa7fe053bcee8c9e783235fead16034b45ceb4850668
3
+ metadata.gz: 94bc121c20cdf80f4be52db46705782fae1f33fd2e8361d2d0b0f584680f2f84
4
+ data.tar.gz: badec7fcc51dc9952988e586a25fbf3b1fafb790decd629ee10d5ab895f29ad0
5
5
  SHA512:
6
- metadata.gz: 31728fa8f53e90d0317e964c92f3b3a8bc1e879821b12f46ec0441b5027f60c6983a4afe8d473a51954894ed8221941c7d8ceed78f45650aa9a791fa70964af7
7
- data.tar.gz: 5950b3d5121580f9948c818ecdbf3d66f102ea118e74382f8e4d1943deb8fe226d492df55b9535c938ac1b1a7f06f74c73e848a0e03c27d5b0db1d4b9f4514e9
6
+ metadata.gz: 20fb54844b44a01513257e0dbaa17be96c626d50435cea0ac0773b765a153e190bc8946f7fcdc6540a7ad313ce352ef92cc31c966325fe339c1314484fefc248
7
+ data.tar.gz: 06a98ecb7d2843dabcf9719de5373e948d1b1826fae3bdb5361671497ad7d00f731e954485c0db1793fab7e369c7b308aa14b3fac3319e4ae37fa8c21661255c
@@ -16,6 +16,7 @@ jobs:
16
16
  DISTRIBUTED_TRACING_DATABASE_URI: "postgresql://postgres:postgres@127.0.0.1:5432/hermes-rb-test"
17
17
  HUTCH_URI: "amqp://guest:guest@127.0.0.1:5672"
18
18
  HUTCH_ENABLE_HTTP_API_USE: false
19
+ DD_PROFILING_NO_EXTENSION: true
19
20
  services:
20
21
  postgres:
21
22
  image: postgres:14
data/Changelog.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Master
4
4
 
5
+ ## 0.7.3
6
+
7
+ - Handle database reconnection in synchronous flow
8
+ - Improve test coverage of `Hermes::Logger::ParamsFilter` - cover regular expressions
9
+
10
+ ## 0.7.2
11
+ - Clear Hermes.origin_headers after calling event handlers
12
+
5
13
  ## 0.7.1
6
14
  - Fix Hermes::DistributedTraceRepository so that it properly applies mapper that modifies event body
7
15
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hermes-rb (0.7.1)
4
+ hermes-rb (0.7.3)
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 (7.0.3.1)
16
- activesupport (= 7.0.3.1)
17
- activerecord (7.0.3.1)
18
- activemodel (= 7.0.3.1)
19
- activesupport (= 7.0.3.1)
20
- activesupport (7.0.3.1)
15
+ activemodel (7.0.4)
16
+ activesupport (= 7.0.4)
17
+ activerecord (7.0.4)
18
+ activemodel (= 7.0.4)
19
+ activesupport (= 7.0.4)
20
+ activesupport (7.0.4)
21
21
  concurrent-ruby (~> 1.0, >= 1.0.2)
22
22
  i18n (>= 1.6, < 2)
23
23
  minitest (>= 5.1)
@@ -36,24 +36,27 @@ GEM
36
36
  ddtrace (0.45.0)
37
37
  msgpack
38
38
  diff-lcs (1.4.4)
39
- dry-container (0.10.0)
39
+ dry-container (0.11.0)
40
40
  concurrent-ruby (~> 1.0)
41
- dry-core (0.8.0)
41
+ dry-core (1.0.0)
42
42
  concurrent-ruby (~> 1.0)
43
- dry-inflector (0.3.0)
44
- dry-logic (1.2.0)
43
+ zeitwerk (~> 2.6)
44
+ dry-inflector (1.0.0)
45
+ dry-logic (1.5.0)
45
46
  concurrent-ruby (~> 1.0)
46
- dry-core (~> 0.5, >= 0.5)
47
- dry-struct (1.4.0)
48
- dry-core (~> 0.5, >= 0.5)
49
- dry-types (~> 1.5)
47
+ dry-core (~> 1.0, < 2)
48
+ zeitwerk (~> 2.6)
49
+ dry-struct (1.6.0)
50
+ dry-core (~> 1.0, < 2)
51
+ dry-types (>= 1.7, < 2)
50
52
  ice_nine (~> 0.11)
51
- dry-types (1.5.1)
53
+ zeitwerk (~> 2.6)
54
+ dry-types (1.7.0)
52
55
  concurrent-ruby (~> 1.0)
53
- dry-container (~> 0.3)
54
- dry-core (~> 0.5, >= 0.5)
55
- dry-inflector (~> 0.1, >= 0.1.2)
56
- dry-logic (~> 1.0, >= 1.0.2)
56
+ dry-core (~> 1.0, < 2)
57
+ dry-inflector (~> 1.0, < 2)
58
+ dry-logic (>= 1.4, < 2)
59
+ zeitwerk (~> 2.6)
57
60
  hutch (1.1.1)
58
61
  activesupport (>= 4.2, < 8)
59
62
  bunny (>= 2.19, < 3.0)
@@ -63,12 +66,12 @@ GEM
63
66
  concurrent-ruby (~> 1.0)
64
67
  ice_nine (0.11.2)
65
68
  json (2.6.2)
66
- minitest (5.16.2)
69
+ minitest (5.16.3)
67
70
  msgpack (1.4.2)
68
71
  multi_json (1.15.0)
69
72
  newrelic_rpm (6.15.0)
70
73
  pg (1.2.3)
71
- rack (2.2.4)
74
+ rack (3.0.1)
72
75
  rake (13.0.1)
73
76
  rbtree (0.4.5)
74
77
  request_store (1.5.1)
@@ -86,15 +89,16 @@ GEM
86
89
  diff-lcs (>= 1.2.0, < 2.0)
87
90
  rspec-support (~> 3.10.0)
88
91
  rspec-support (3.10.0)
89
- set (1.0.2)
92
+ set (1.0.3)
90
93
  sorted_set (1.0.3)
91
94
  rbtree
92
95
  set (~> 1.0)
93
96
  thor (1.2.1)
94
97
  timecop (0.9.2)
95
- tzinfo (2.0.4)
98
+ tzinfo (2.0.5)
96
99
  concurrent-ruby (~> 1.0)
97
100
  vcr (5.0.0)
101
+ zeitwerk (2.6.6)
98
102
 
99
103
  PLATFORMS
100
104
  ruby
data/README.md CHANGED
@@ -30,6 +30,7 @@ Rails.application.config.to_prepare do
30
30
  config.adapter = Rails.application.config.async_messaging_adapter
31
31
  config.application_prefix = "my_app"
32
32
  config.background_processor = HermesHandlerJob
33
+ config.database_connection_provider = ActiveRecord::Base.connection
33
34
  config.enqueue_method = :perform_async
34
35
  config.event_handler = event_handler
35
36
  config.clock = Time.zone
@@ -87,14 +88,15 @@ end
87
88
 
88
89
  If you know what you are doing, you don't necessarily have to process things in the background. As long as the class implements the expected interface, you can do anything you want.
89
90
 
90
- 5. `event_handler` - an instance of event handler/storage, just use what is shown in the example. Notice that you can also pass extra consumer config lambda that will be evaluated within the context of Hutch consumer.
91
- 6. `clock` - a clock object that is time-zone aware, implementing `now` method.
92
- 7. `configure_hutch` - a way to configure Hutch:
91
+ 5. `database_connection_provider` - an object responding to `reconnect!`. It is used during synchronous flow to ensure a valid connection. Optional.
92
+ 6. `event_handler` - an instance of event handler/storage, just use what is shown in the example. Notice that you can also pass extra consumer config lambda that will be evaluated within the context of Hutch consumer.
93
+ 7. `clock` - a clock object that is time-zone aware, implementing `now` method.
94
+ 8. `configure_hutch` - a way to configure Hutch:
93
95
  - `uri` - the URI for RabbitMQ, required.
94
96
  - `force_publisher_confirms` - defaults to `true`
95
97
  - `enable_http_api_use` - defaults to `false`
96
98
  - `tracer` - defaults to `Hermes::Tracers::Datadog` if you use Datadog, `Hutch::Tracers::NewRelic` for NewRelic and `Hutch::Tracers::NullTracer` if you use neither Datadog, nor NewRelic. Check APM section for more details if you want to provide a custom tracer.
97
- 8. `event_handler.handle_events` - that's how you declare events and their handlers. The event handler is an object that responds to `call` method and takes `event` as an argument. All events should ideally be subclasses of `Hermes::BaseEvent`
99
+ 9. `event_handler.handle_events` - that's how you declare events and their handlers. The event handler is an object that responds to `call` method and takes `event` as an argument. All events should ideally be subclasses of `Hermes::BaseEvent`
98
100
 
99
101
  This class inherits from `Dry::Struct`, so getting familiar with [dry-struct gem](https://dry-rb.org/gems/dry-struct/) would be beneficial. Here is an example event:
100
102
 
@@ -122,9 +124,9 @@ To avoid unexpected problems, don't use restricted names for attribtes such as `
122
124
 
123
125
  You can also specify whether the event should be processed asynchronously using `background_processor` (default behavior) or synchronously. If you want the event to be processed synchronously, e.g. when doing RPC, use `async: false` option.
124
126
 
125
- 9. `rpc_call_timeout` - a timeout for RPC calls, defaults to 10 seconds. Can be also customized per instance of RPC Client (covered later). Optional.
127
+ 10. `rpc_call_timeout` - a timeout for RPC calls, defaults to 10 seconds. Can be also customized per instance of RPC Client (covered later). Optional.
126
128
 
127
- 10. `instrumenter` - instrumenter object responding to `instrument` method taking one string argument, one optional hash argument and a block.
129
+ 11. `instrumenter` - instrumenter object responding to `instrument` method taking one string argument, one optional hash argument and a block.
128
130
 
129
131
  For example:
130
132
 
@@ -144,21 +146,21 @@ end
144
146
 
145
147
  If you don't care about it, you can leave it empty.
146
148
 
147
- 11. `distributed_tracing_database_uri` - If you want to enable distributed tracing, specify Postgres database URI. Optional.
149
+ 12. `distributed_tracing_database_uri` - If you want to enable distributed tracing, specify Postgres database URI. Optional.
148
150
 
149
- 12. `distributed_tracing_database_table` - Table name for storing traces, by default it's `hermes_distributed_traces`. Optional.
151
+ 13. `distributed_tracing_database_table` - Table name for storing traces, by default it's `hermes_distributed_traces`. Optional.
150
152
 
151
- 13. `distributes_tracing_mapper` - an object responding to `call` method taking one argument (a hash of attributes) which must return a hash as well. This hash will be used for assigning attributes when creating `Hermes::DistributedTrace`. It defaults to `Hermes::DistributedTrace::Mapper`, which uses `logger_params_filter` to remove sensitive info (this config option is covered below). You can either provide a custom mapper or pass a custom params filter, for example: `Hermes::DistributedTrace::Mapper.new(params_filter: custom_params_filter)`
153
+ 14. `distributes_tracing_mapper` - an object responding to `call` method taking one argument (a hash of attributes) which must return a hash as well. This hash will be used for assigning attributes when creating `Hermes::DistributedTrace`. It defaults to `Hermes::DistributedTrace::Mapper`, which uses `logger_params_filter` to remove sensitive info (this config option is covered below). You can either provide a custom mapper or pass a custom params filter, for example: `Hermes::DistributedTrace::Mapper.new(params_filter: custom_params_filter)`
152
154
 
153
- 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.
155
+ 15. `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.
154
156
 
155
- 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.
157
+ 16. `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.
156
158
 
157
- 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.
159
+ 17. `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.
158
160
 
159
- 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])`.
161
+ 18. `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])`.
160
162
 
161
- 18. `logger_params_filter` - a service used as params filter for logger, to make sure no sensitive data will be logged. It defaults to `Hermes::Logger::ParamsFilter` which already performs some filtering but it might not be enough in your case. If you are not satisfied with the defaults, you have 2 options, which are especially simple in Rails apps:
163
+ 19. `logger_params_filter` - a service used as params filter for logger, to make sure no sensitive data will be logged. It defaults to `Hermes::Logger::ParamsFilter` which already performs some filtering but it might not be enough in your case. If you are not satisfied with the defaults, you have 2 options, which are especially simple in Rails apps:
162
164
  - provide custom array of sensitive attributes and still use a default filter: `Hermes::Logger::ParamsFilter.new(sensitive_keywords: Rails.application.config.filter_parameters)`.
163
165
  - provide custom filter object, which responds to `call` method and takes 2 arguments: attribute name and its value and performs mutation by using `gsub!` (don't worry, the entire body is cloned before passing it to the filter, so nothing unexpected will happen). This is compatible with the interface of `Rails.application.config.filter_parameters` when you use a custom filter there. In such case, you can do something like this: `Rails.application.config.filter_parameters = [Proc.new { |k, v| do_something_custom_here(k, v) }]` and then just assign `Rails.application.config.filter_parameters.first` in the Hermes config.
164
166
  ## RPC
@@ -4,7 +4,7 @@ module Hermes
4
4
  :background_processor, :enqueue_method, :event_handler, :rpc_call_timeout,
5
5
  :instrumenter, :distributed_tracing_database_uri, :distributed_tracing_database_table,
6
6
  :distributes_tracing_mapper, :database_error_handler, :error_notification_service, :producer_error_handler,
7
- :producer_error_handler_job_class, :producer_retryable, :logger_params_filter, :tracer
7
+ :producer_error_handler_job_class, :producer_retryable, :logger_params_filter, :tracer, :database_connection_provider
8
8
 
9
9
  def configure_hutch
10
10
  yield hutch
@@ -25,6 +25,7 @@ module Hermes
25
25
  config.background_processor.public_send(config.enqueue_method, event_class.to_s, body, headers)
26
26
  logger.log_enqueued(event_class, body, headers, config.clock.now)
27
27
  else
28
+ ensure_database_connection!
28
29
  result = event_processor.call(event_class.to_s, body, headers)
29
30
  event = result.event
30
31
  response = result.response
@@ -58,6 +59,10 @@ module Hermes
58
59
  def event_processor
59
60
  Hermes::DependenciesContainer["event_processor"]
60
61
  end
62
+
63
+ def ensure_database_connection!
64
+ config.database_connection_provider.reconnect! if config.database_connection_provider
65
+ end
61
66
  end
62
67
 
63
68
  register_consumer(consumer_name, consumer)
@@ -19,12 +19,13 @@ module Hermes
19
19
 
20
20
  def call(event_class, body, headers)
21
21
  event = Object.const_get(event_class).from_body_and_headers(body, headers)
22
- Hermes.origin_headers = headers
23
22
 
24
- instrumenter.instrument("Hermes.EventProcessor.#{event_class}") do
25
- response = infer_handler(event_class).call(event)
26
- distributed_trace_repository.create(event)
27
- ProcessingResult.new(event, response)
23
+ Hermes.with_origin_headers(headers) do
24
+ instrumenter.instrument("Hermes.EventProcessor.#{event_class}") do
25
+ response = infer_handler(event_class).call(event)
26
+ distributed_trace_repository.create(event)
27
+ ProcessingResult.new(event, response)
28
+ end
28
29
  end
29
30
  end
30
31
 
@@ -1,5 +1,5 @@
1
1
  module Hermes
2
2
  module Rb
3
- VERSION = "0.7.1"
3
+ VERSION = "0.7.3"
4
4
  end
5
5
  end
data/lib/hermes.rb CHANGED
@@ -50,6 +50,16 @@ module Hermes
50
50
  def self.origin_headers=(headers)
51
51
  DependenciesContainer["global_store"][ORIGIN_HEADERS_KEY] = headers.to_h
52
52
  end
53
+
54
+ def self.clear_origin_headers
55
+ DependenciesContainer["global_store"].delete(ORIGIN_HEADERS_KEY)
56
+ end
57
+
58
+ def self.with_origin_headers(headers)
59
+ self.origin_headers = headers
60
+
61
+ yield.tap { clear_origin_headers }
62
+ end
53
63
  end
54
64
 
55
65
  require "hermes/distributed_trace"
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.7.1
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karol Galanciak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-19 00:00:00.000000000 Z
11
+ date: 2022-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-struct