eventhub-processor2 1.28.1 → 1.29.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: 30f1770bc8368dade5070d56b70f7d178c4f2b9b411b6c8cedc76d5cee74906a
4
- data.tar.gz: 437a059f4496b259452423572dc03149dc35dd3992dadf1cf741cf153d76ac44
3
+ metadata.gz: 84f9fe3b6c2f1eca60c496eb71a647df7f9fc08f4841475cf26b65ff4fc024a6
4
+ data.tar.gz: ae79889b953ff8af2c9efbd87c396d645fe803153b20a4a56fcc952c64d40214
5
5
  SHA512:
6
- metadata.gz: e2c36a143e30f630b64756c0a26e2f3d936ef37a34be14eefac20ed105535ec9a2d7c561ec5e482e16ca0df22e484f09d14d3f5ecf202c2d472fbcc5b4588603
7
- data.tar.gz: 1e51eb0ae32377c32c2fc5372be3304a276fac5d5df9920658fb804bd8c8461b25a8a9470cccbbc3719963fdfc966e8b9b7f349d7cabb1c9943ddb60ae32cb3e
6
+ metadata.gz: cdb5378dc754624ec452602fea4eb4cefe7e50e074491d7d48f4d2ae0f7b4fa07839d31e29fecae53c4c2f5836a9010891cd9045e30af4e03e1cdef40892aa4c
7
+ data.tar.gz: 956bf56d3b193ab891c393b7fa56151b22cdfd31222c4ce66ab6f9d18d9edee860d54eca98cb68264185cf797c71257447dc773ff9006d8d31e8bc94f462e9ff
@@ -27,7 +27,7 @@ jobs:
27
27
 
28
28
  name: Ruby ${{ matrix.ruby }}
29
29
  steps:
30
- - uses: actions/checkout@v6
30
+ - uses: actions/checkout@v7
31
31
 
32
32
  - name: Set up Ruby
33
33
  uses: ruby/setup-ruby@v1
@@ -13,7 +13,7 @@ jobs:
13
13
  CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
14
14
 
15
15
  steps:
16
- - uses: actions/checkout@v6
16
+ - uses: actions/checkout@v7
17
17
 
18
18
  - name: Set up Ruby
19
19
  uses: ruby/setup-ruby@v1
@@ -41,7 +41,7 @@ jobs:
41
41
 
42
42
  steps:
43
43
  - name: Checkout current code
44
- uses: actions/checkout@v6
44
+ uses: actions/checkout@v7
45
45
  with:
46
46
  ref: main
47
47
 
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 4.0.4
1
+ ruby 4.0.6
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog of EventHub::Processor2
2
2
 
3
+ # 1.29.0 / 2026-08-26
4
+
5
+ * Docs configuration page: sensitive keys now match by substring with an extended default list (e.g. `base_url`, `api_port` are redacted automatically). Exceptions like `vhost` stay visible and can be customized via `non_sensitive_keys`, analogous to `sensitive_keys`. See README for details.
6
+ * Docs configuration page: redaction keeps hash/array structures visible and masks only the scalar values inside.
7
+ * Test coverage raised to 100% lines; removed a dead duplicate route mount in the HTTP listener.
8
+
9
+ # 1.28.2 / 2026-05-20
10
+
11
+ * Fix `CorrelationId.current` leaking across messages on the same Bunny consumer thread. `CorrelationId.with` now always saves and restores, even when called with nil/empty. Symptom in production: deadletter messages stamped with an earlier message's `execution_id`.
12
+ * Listener now also resets `correlation_id` after each message (extra safety on top of the fix above, in case some future code writes it outside of `CorrelationId.with`).
13
+ * README: clarify `correlation_id` is the AMQP **property** (envelope-level), not a custom field in the headers table. Producers must set the property; a header named `correlation_id` is invisible to the gem.
14
+
3
15
  # 1.28.1 / 2026-05-19
4
16
 
5
17
  * Fix `LoggerProxy` double-wrapping when callers pass a Hash to a logger method. Hash inputs are now merged (not nested under `:message`), so the resulting structured event has the caller's fields at the top level - restoring the behaviour that existed before `LoggerProxy` was introduced in 1.26.0, while keeping automatic thread-local injection of `correlation_id` and `execution_id`. Caller-provided values win over thread-locals via `||=`.
data/README.md CHANGED
@@ -117,6 +117,31 @@ I, [2018-02-09T15:22:35.658522 #37966] INFO -- : Listener is starting...
117
117
  I, [2018-02-09T15:22:35.699161 #37966] INFO -- : Listening to queue [example]
118
118
  ```
119
119
 
120
+ ## Concurrency Model
121
+
122
+ Processor2 runs **one consumer thread per queue** listed in `listener_queues`. Each consumer holds a Bunny worker thread with `prefetch(1)`, so it processes its messages sequentially. Multiple queues run their consumers in parallel.
123
+
124
+ | `listener_queues` | Concurrency |
125
+ |-------------------------------|------------------------------------------------|
126
+ | `["q1"]` | 1 consumer thread, sequential |
127
+ | `["q1", "q2"]` | 2 consumer threads, parallel (one per queue) |
128
+ | `["q1", "q1", "q1"]` | 3 consumer threads, all on the same queue |
129
+
130
+ To increase throughput for a single queue, either list it multiple times in `listener_queues` (each entry gets its own consumer thread) or run multiple processes. The single-process / single-consumer-per-queue model is what the gem is designed for.
131
+
132
+ Correlation context (`correlation_id`, `execution_id`) is held in thread-local storage, so concurrent consumer threads cannot interfere with each other - each message's outbound `correlation_id` is the one it received (or its body's fallback), regardless of what other threads are doing.
133
+
134
+ ### A note on `prefetch`
135
+
136
+ The AMQP `prefetch` value is **fixed at 1** and not currently exposed via configuration. Raising it would require:
137
+
138
+ - bumping Bunny's `channel.work_pool.size` in lockstep (raising `prefetch` alone only buffers messages in Bunny - it does not add parallelism);
139
+ - pooling or removing `ActorPublisher`'s single-mailbox bottleneck, otherwise N parallel consumers serialize through one publisher;
140
+ - making `handle_message` a thread-safety contract for gem users (today it is implicitly single-threaded - any `@ivar` on the processor class is safe by accident);
141
+ - making `Statistics` and any other shared state thread-safe.
142
+
143
+ These trade-offs change the gem's call-surface contract, so a configurable `prefetch` would be a minor-version feature, not a patch. For now, the supported way to scale a single queue is to list it multiple times in `listener_queues` or run multiple processes.
144
+
120
145
  ## Logging
121
146
 
122
147
  By default, Processor2 logs to both stdout (standard format) and a logstash file. For containerized environments (Docker, Kubernetes), use the `--console-log-only` option to output structured JSON logs to stdout only:
@@ -135,10 +160,21 @@ This outputs logs in JSON format suitable for log aggregation systems:
135
160
 
136
161
  Processor2 supports automatic propagation of correlation IDs for distributed tracing. While EventHub messages already contain an `execution_id` in the message body for tracing, the AMQP `correlation_id` provides an additional benefit: it's part of the message metadata (envelope), not the payload. This means it's available even when the JSON body is invalid and cannot be parsed - useful for error tracking and debugging malformed messages.
137
162
 
138
- When an incoming AMQP message includes a `correlation_id` in its metadata:
163
+ > **Important: `correlation_id` is an AMQP `property`, not a `header`.**
164
+ >
165
+ > In AMQP 0.9.1, `correlation_id` is one of the 14 standard message *properties* (top-level envelope fields, alongside `message_id`, `reply_to`, `content_type`, etc.). The *headers table* is a separate, optional dictionary inside the property block for application-defined fields. They are not interchangeable.
166
+ >
167
+ > Producers must set `correlation_id` as a property. A custom field called `correlation_id` placed inside the headers table is **invisible to this gem** and will silently fall back to the message body's `execution_id`.
168
+ >
169
+ > Concretely:
170
+ > - In Bunny: `channel.default_exchange.publish(payload, correlation_id: "...")` ✅ property
171
+ > - In Bunny: `... publish(payload, headers: { "correlation_id" => "..." })` ❌ custom header, not seen
172
+ > - In the RabbitMQ Management UI's "Publish message" form: set the value in the **Properties** section, not in the **Headers** section. When inspecting a queued message, look at "Properties → correlation_id", not at "Headers".
173
+
174
+ When an incoming AMQP message includes a `correlation_id` in its metadata (as a property):
139
175
 
140
176
  1. **Automatic logging**: All log messages during message processing will include `correlation_id` as a separate field in structured JSON output
141
- 2. **Automatic publishing**: Any messages published during processing will automatically include the same correlation_id in their AMQP headers
177
+ 2. **Automatic publishing**: Any messages published during processing will automatically include the same correlation_id as an AMQP `correlation_id` property (envelope-level, not in the headers table)
142
178
  3. **Available in args**: The correlation_id is passed to `handle_message` via `args[:correlation_id]`
143
179
  4. **Consistent execution_id**: When creating new messages, `execution_id` is automatically set to match `correlation_id`, ensuring consistent tracing across both AMQP metadata and message body
144
180
 
@@ -174,7 +210,7 @@ If no `correlation_id` is present in the AMQP metadata, the message body's `exec
174
210
  3. **Stored**: The value is stored in thread-local storage (`Thread.current`) for the duration of message processing
175
211
  4. **Passed**: The `correlation_id` is passed to `handle_message` via `args[:correlation_id]`
176
212
  5. **Logging**: The logger automatically reads from thread-local storage and includes it in JSON output
177
- 6. **Publishing**: The publisher automatically reads from thread-local storage and adds it to outgoing AMQP message headers (can be overwritten by passing `correlation_id:` explicitly)
213
+ 6. **Publishing**: The publisher automatically reads from thread-local storage and sets it as the outgoing AMQP `correlation_id` property (can be overwritten by passing `correlation_id:` explicitly)
178
214
  7. **New messages**: When creating a new `EventHub::Message`:
179
215
  - With `correlation_id` present → `execution_id` is set to match `correlation_id`
180
216
  - Without `correlation_id` → `execution_id` is set to a new UUID (default behavior)
@@ -463,7 +499,7 @@ end
463
499
 
464
500
  ### Configuration
465
501
 
466
- Displays the active configuration as an HTML table. Sensitive values (passwords, tokens, keys) are automatically redacted at any depth — keys matching the sensitive list are masked whether they appear at the top level, inside nested hashes, or inside hashes nested in arrays.
502
+ Displays the active configuration as an HTML table. Sensitive values (passwords, tokens, keys) are automatically redacted at any depth — keys matching the sensitive list are masked whether they appear at the top level, inside nested hashes, or inside hashes nested in arrays. The structure is always preserved: when a sensitive key holds a hash or array, its keys stay visible and only the scalar values inside are replaced by `***`.
467
503
 
468
504
  ```
469
505
  GET {base_path}/docs/configuration
@@ -471,7 +507,7 @@ GET {base_path}/docs/configuration
471
507
 
472
508
  **Response:** `200 OK` with HTML page
473
509
 
474
- By default, the following keys are redacted: `password`, `secret`, `token`, `api_key`, `credential`, `username`, `user`, `login`. You can customize the list by defining a `sensitive_keys` method in your processor:
510
+ Matching is by substring: a key is redacted if it *contains* one of the sensitive patterns (case-insensitive). By default, the patterns are: `password`, `secret`, `token`, `api_key`, `credential`, `user`, `login`, `host`, `port`, `database`, `instance`, `url`, `endpoint`, `scheme`. So `base_url`, `api_port`, `username`, or `userpwd` are redacted as well. `vhost` is an explicit exception and stays visible, even though it contains `host`. You can customize the list by defining a `sensitive_keys` method in your processor:
475
511
 
476
512
  ```ruby
477
513
  # Override the entire list
@@ -489,6 +525,17 @@ class MyProcessor < EventHub::Processor2
489
525
  end
490
526
  ```
491
527
 
528
+ Exceptions work the other way around: keys listed as exceptions are never redacted, even if they match a sensitive pattern. Unlike the patterns, exceptions match the whole key exactly (case-insensitive). The default is `vhost`; you can customize the list by defining a `non_sensitive_keys` method:
529
+
530
+ ```ruby
531
+ # Keep username and user visible although they match the user pattern
532
+ class MyProcessor < EventHub::Processor2
533
+ def non_sensitive_keys
534
+ EventHub::DocsRenderer::DEFAULT_NON_SENSITIVE_KEYS + %w[username user]
535
+ end
536
+ end
537
+ ```
538
+
492
539
  Or override the entire page by defining a `configuration_as_html` method:
493
540
 
494
541
  ```ruby
@@ -32,6 +32,6 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.add_development_dependency "rake", "~> 13.2"
34
34
  spec.add_development_dependency "rspec", "~> 3.13"
35
- spec.add_development_dependency "simplecov", "~> 0.21"
35
+ spec.add_development_dependency "simplecov", "~> 1.0"
36
36
  spec.add_development_dependency "standard", "~> 1.39"
37
37
  end
@@ -90,6 +90,12 @@ module EventHub
90
90
  " acknowledged")
91
91
  ensure
92
92
  ExecutionId.clear
93
+ # Belt-and-suspenders: CorrelationId.with's ensure already
94
+ # restores the prior value, but clearing here protects any
95
+ # future code path that writes CorrelationId.current outside
96
+ # of `.with` (e.g. handle_payload's fallback was the original
97
+ # leak source pre-1.28.2).
98
+ CorrelationId.clear
93
99
  end
94
100
  end
95
101
  queue.subscribe_with(consumer, block: false)
@@ -43,13 +43,12 @@ module EventHub
43
43
  end
44
44
 
45
45
  def mount_resources
46
- # Redirect base path to docs
46
+ # Redirect base path to docs. WEBrick normalizes mount points by
47
+ # stripping the trailing slash, so this single mount serves both
48
+ # "#{@base_path}" and "#{@base_path}/".
47
49
  @server.mount_proc @base_path do |req, res|
48
50
  handle_base_redirect(req, res)
49
51
  end
50
- @server.mount_proc "#{@base_path}/" do |req, res|
51
- handle_base_redirect(req, res)
52
- end
53
52
 
54
53
  # API resources
55
54
  @server.mount_proc "#{@base_path}/heartbeat" do |req, res|
@@ -16,18 +16,20 @@ module EventHub
16
16
  Thread.current[:eventhub_correlation_id] = nil
17
17
  end
18
18
 
19
- # Execute block with correlation_id set, ensures cleanup
19
+ # Execute block with correlation_id set, ensures cleanup.
20
+ #
21
+ # Always saves the prior value and restores it on exit, even when
22
+ # called with nil/empty - otherwise any value written to `current`
23
+ # inside the block (e.g. handle_payload's fallback to the message
24
+ # body's execution_id) would leak onto the consumer thread and be
25
+ # picked up by the next message's processing.
20
26
  def with(correlation_id)
21
- if correlation_id.nil? || correlation_id.to_s.empty?
27
+ old_value = current
28
+ begin
29
+ self.current = correlation_id unless correlation_id.nil? || correlation_id.to_s.empty?
22
30
  yield
23
- else
24
- old_value = current
25
- begin
26
- self.current = correlation_id
27
- yield
28
- ensure
29
- self.current = old_value
30
- end
31
+ ensure
32
+ self.current = old_value
31
33
  end
32
34
  end
33
35
  end
@@ -159,29 +159,30 @@ module EventHub
159
159
  intro + filter + config_to_html_table(config) + script
160
160
  end
161
161
 
162
- def config_to_html_table(hash, depth = 0, prefix = "")
162
+ def config_to_html_table(hash, depth = 0, prefix = "", redact: false)
163
163
  rows = hash.map do |key, value|
164
164
  full_key = prefix.empty? ? key.to_s : "#{prefix}.#{key}"
165
- if sensitive_key?(key) && !value.nil? && !(value.respond_to?(:empty?) && value.empty?)
166
- "<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td>#{redacted_html}</td></tr>"
167
- elsif depth == 0 && value.is_a?(Hash) && !value.empty?
165
+ hide = redact || sensitive_key?(key)
166
+ if depth == 0 && value.is_a?(Hash) && !value.empty?
168
167
  "<tr class=\"is-section is-section-top\"><td colspan=\"2\"><strong>#{ERB::Util.html_escape(full_key)}</strong></td></tr>\n" \
169
- "#{config_to_html_table(value, 1, full_key)}"
168
+ "#{config_to_html_table(value, 1, full_key, redact: hide)}"
170
169
  elsif value.is_a?(Hash) && value.empty?
171
170
  "<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td><span class=\"not-set\">(empty)</span></td></tr>"
172
171
  elsif value.is_a?(Hash) && value.values.all? { |v| v.is_a?(Hash) && v.empty? }
173
172
  items = value.keys.map { |k| "<li>#{ERB::Util.html_escape(k)}</li>" }.join("\n")
174
173
  "<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td><ul class=\"config-array\">#{items}</ul></td></tr>"
175
174
  elsif value.is_a?(Hash) && compact_hash?(value)
176
- "<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td>#{format_nested_value(value)}</td></tr>"
175
+ "<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td>#{format_nested_value(value, redact: hide)}</td></tr>"
177
176
  elsif value.is_a?(Hash)
178
177
  "<tr class=\"is-section\"><td colspan=\"2\"><strong>#{ERB::Util.html_escape(full_key)}</strong></td></tr>\n" \
179
- "#{config_to_html_table(value, depth + 1, full_key)}"
178
+ "#{config_to_html_table(value, depth + 1, full_key, redact: hide)}"
180
179
  elsif value.is_a?(Array)
181
- format_array_rows(full_key, key, value, depth)
180
+ format_array_rows(full_key, value, depth, redact: hide)
182
181
  else
183
182
  display_value = if value.nil? || value.to_s.strip.empty?
184
183
  "<span class=\"not-set\">(not set)</span>"
184
+ elsif hide
185
+ redacted_html
185
186
  else
186
187
  ERB::Util.html_escape(value.to_s)
187
188
  end
@@ -196,44 +197,42 @@ module EventHub
196
197
  end
197
198
  end
198
199
 
199
- def format_array_rows(full_key, key, array, _depth)
200
+ def format_array_rows(full_key, array, _depth, redact: false)
200
201
  return "<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td><span class=\"not-set\">(empty)</span></td></tr>" if array.empty?
201
202
 
202
- if sensitive_key?(key)
203
- return "<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td>#{redacted_html}</td></tr>"
204
- end
205
-
206
- inner = array.map { |item| format_array_item(item) }.join("\n")
203
+ inner = array.map { |item| format_array_item(item, redact: redact) }.join("\n")
207
204
  "<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td><ul class=\"config-array\">#{inner}</ul></td></tr>"
208
205
  end
209
206
 
210
- def format_array_item(item)
207
+ def format_array_item(item, redact: false)
211
208
  if item.is_a?(Hash)
212
209
  rows = item.map do |k, v|
213
- value = sensitive_key?(k) ? redacted_html : format_nested_value(v)
214
- "<tr><td>#{ERB::Util.html_escape(k)}</td><td>#{value}</td></tr>"
210
+ hide = redact || sensitive_key?(k)
211
+ "<tr><td>#{ERB::Util.html_escape(k)}</td><td>#{format_nested_value(v, redact: hide)}</td></tr>"
215
212
  end.join
216
213
  "<li><table class=\"table is-bordered is-narrow config-subtable\">#{rows}</table></li>"
217
214
  elsif item.is_a?(Array)
218
- inner = item.map { |i| format_array_item(i) }.join("\n")
215
+ inner = item.map { |i| format_array_item(i, redact: redact) }.join("\n")
219
216
  "<li><ul class=\"config-array\">#{inner}</ul></li>"
220
217
  else
221
- "<li>#{ERB::Util.html_escape(item.to_s)}</li>"
218
+ "<li>#{redact ? redacted_html : ERB::Util.html_escape(item.to_s)}</li>"
222
219
  end
223
220
  end
224
221
 
225
- def format_nested_value(value)
222
+ def format_nested_value(value, redact: false)
226
223
  if value.is_a?(Hash)
227
224
  rows = value.map do |k, v|
228
- inner = sensitive_key?(k) ? redacted_html : format_nested_value(v)
229
- "<tr><td>#{ERB::Util.html_escape(k)}</td><td>#{inner}</td></tr>"
225
+ hide = redact || sensitive_key?(k)
226
+ "<tr><td>#{ERB::Util.html_escape(k)}</td><td>#{format_nested_value(v, redact: hide)}</td></tr>"
230
227
  end.join
231
228
  "<table class=\"table is-bordered is-narrow config-subtable\">#{rows}</table>"
232
229
  elsif value.is_a?(Array)
233
- items = value.map { |i| format_array_item(i) }.join("\n")
230
+ items = value.map { |i| format_array_item(i, redact: redact) }.join("\n")
234
231
  "<ul class=\"config-array\">#{items}</ul>"
235
232
  elsif value.nil? || value.to_s.strip.empty?
236
233
  "<span class=\"not-set\">(not set)</span>"
234
+ elsif redact
235
+ redacted_html
237
236
  else
238
237
  ERB::Util.html_escape(value.to_s)
239
238
  end
@@ -253,15 +252,27 @@ module EventHub
253
252
  end
254
253
  end
255
254
 
256
- DEFAULT_SENSITIVE_KEYS = %w[password secret token api_key credential username user login].freeze
255
+ DEFAULT_SENSITIVE_KEYS = %w[password secret token api_key credential user login host port database instance url endpoint scheme].freeze
256
+ DEFAULT_NON_SENSITIVE_KEYS = %w[vhost].freeze
257
257
 
258
258
  def sensitive_key?(key)
259
+ normalized = key.to_s.downcase
260
+ return false if non_sensitive_keys.any? { |exception| normalized == exception.downcase }
261
+
259
262
  keys = if @processor&.class&.method_defined?(:sensitive_keys)
260
263
  @processor.sensitive_keys
261
264
  else
262
265
  DEFAULT_SENSITIVE_KEYS
263
266
  end
264
- keys.any? { |pattern| key.to_s.downcase == pattern.downcase }
267
+ keys.any? { |pattern| normalized.include?(pattern.downcase) }
268
+ end
269
+
270
+ def non_sensitive_keys
271
+ if @processor&.class&.method_defined?(:non_sensitive_keys)
272
+ @processor.non_sensitive_keys
273
+ else
274
+ DEFAULT_NON_SENSITIVE_KEYS
275
+ end
265
276
  end
266
277
 
267
278
  def markdown_to_html(markdown)
@@ -1,3 +1,3 @@
1
1
  module EventHub
2
- VERSION = "1.28.1".freeze
2
+ VERSION = "1.29.0".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eventhub-processor2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.28.1
4
+ version: 1.29.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steiner, Thomas
@@ -141,14 +141,14 @@ dependencies:
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: '0.21'
144
+ version: '1.0'
145
145
  type: :development
146
146
  prerelease: false
147
147
  version_requirements: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - "~>"
150
150
  - !ruby/object:Gem::Version
151
- version: '0.21'
151
+ version: '1.0'
152
152
  - !ruby/object:Gem::Dependency
153
153
  name: standard
154
154
  requirement: !ruby/object:Gem::Requirement
@@ -247,7 +247,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
247
247
  - !ruby/object:Gem::Version
248
248
  version: '0'
249
249
  requirements: []
250
- rubygems_version: 4.0.10
250
+ rubygems_version: 4.0.16
251
251
  specification_version: 4
252
252
  summary: Next generation gem to build ruby based eventhub processor
253
253
  test_files: []