eventhub-processor2 1.25.0 → 1.26.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: d78c7de7448b619cc5dce05f62af274a5310e1abf85986e8cd7e014d49e8bbb5
4
- data.tar.gz: c56a15cde07013aea85c6d1c67c674fa55802e7c0cf8299a54f7b6a48f0e7278
3
+ metadata.gz: a22e1c2fd13d72c1b1a7ca6acd296f6e1a5a6b8fca1398f81d5cb4e2a04c220b
4
+ data.tar.gz: 18ca7a93b97092c0a66c4dde11a1cce29fdc505259bebb7ed951e1638dd04422
5
5
  SHA512:
6
- metadata.gz: dc364064bc7c6c54444c15165c204b4314533f7df2e4fd0e1a3d065e2ec19b5b6586501a603e0b1b8e3fb3b8f0357a9a3279b70ab9e45198e061a77c28b29a9b
7
- data.tar.gz: 65e9922a923b95ecdbade34deb040abee4a9575772df22cf183340182d26f9353a04f53b39ea69b6346c2ae4858ec9b8265095b98bb241ceefea673aaf3458ea
6
+ metadata.gz: 7965f0be501e337c8a0e8d6873417f13e884107016fad8f080550d69be14636cf3cdd31c7f884dda0a811a475cb73bba16ad1c2b2b85fdce76de95fd3785d02f
7
+ data.tar.gz: 70c95a713c4600c748a5e3bf5d625fd848110aa37c94b5bbcf3df2dcff847f1d6bd2c5bc4c1a69e6673a26065c9f42d4c02bbd627af235d53998a4ea81ed2ab0
@@ -1,4 +1,4 @@
1
- name: ci
1
+ name: 01 - Test
2
2
 
3
3
  on:
4
4
  push:
@@ -0,0 +1,57 @@
1
+ name: 02 - Test, Build and Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ env:
13
+ CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
14
+
15
+ steps:
16
+ - uses: actions/checkout@v6
17
+
18
+ - name: Set up Ruby
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: '4.0'
22
+ bundler: latest
23
+ bundler-cache: true
24
+ cache-version: 4
25
+
26
+ - name: Setup RabbitMQ
27
+ run: |
28
+ cd docker && docker build -t processor-rabbitmq .
29
+ docker run -d -p 5672:5672 -p 15672:15672 --name processor-rabbitmq processor-rabbitmq
30
+
31
+ - name: Run default task
32
+ run: |
33
+ bundle exec rake
34
+
35
+ build:
36
+ needs: test
37
+ runs-on: ubuntu-latest
38
+ permissions:
39
+ id-token: write # Required for OIDC
40
+ contents: write # Required for pushing tags
41
+
42
+ steps:
43
+ - name: Checkout current code
44
+ uses: actions/checkout@v6
45
+
46
+ - name: Set up Ruby
47
+ uses: ruby/setup-ruby@v1
48
+ with:
49
+ ruby-version: '4.0'
50
+ bundler-cache: true
51
+ cache-version: 1
52
+
53
+ - name: Build gem
54
+ run: gem build *.gemspec
55
+
56
+ - name: Push to Rubygems
57
+ uses: rubygems/release-gem@v1
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 4.0.1
1
+ ruby 4.0.2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog of EventHub::Processor2
2
2
 
3
+ # 1.26.0 / 2026-03-18
4
+
5
+ * Add HTTP resources for version, docs, changelog, and configuration with HTML rendering
6
+ * Add processor hooks for HTTP resource customization: `version`, `company_name`, `readme_as_html`, `changelog_as_html`, `configuration_as_html`, `sensitive_keys`, and `http_resources`
7
+ * Heartbeat endpoint returns detailed JSON status (version, pid, uptime, messages)
8
+ * Add distributed tracing with correlation_id and execution_id in structured log output
9
+ * Simplify HTTP configuration with shared `http.bind_address`, `http.port`, and `http.base_path`
10
+ * Add kramdown dependency for markdown to HTML conversion
11
+ * Rename GitHub Actions workflows and add test step to release workflow
12
+
3
13
  # 1.25.0 / 2026-01-13
4
14
 
5
15
  * Replace uuidtools dependency with Ruby's built-in SecureRandom
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/eventhub-processor2.svg)](https://badge.fury.io/rb/eventhub-processor2)
2
- [![ci](https://github.com/thomis/eventhub-processor2/actions/workflows/ci.yml/badge.svg)](https://github.com/thomis/eventhub-processor2/actions/workflows/ci.yml)
2
+ [![01 - Test](https://github.com/thomis/eventhub-processor2/actions/workflows/01_test.yml/badge.svg)](https://github.com/thomis/eventhub-processor2/actions/workflows/01_test.yml)
3
+ [![02 - Test, Build and Release](https://github.com/thomis/eventhub-processor2/actions/workflows/02_test_build_and_release.yml/badge.svg)](https://github.com/thomis/eventhub-processor2/actions/workflows/02_test_build_and_release.yml)
3
4
 
4
5
  # EventHub::Processor2
5
6
 
@@ -10,7 +11,7 @@ Processor2 has currently the following sub-components implemented
10
11
  * Publisher - responsible for message publishing
11
12
  * Watchdog - Checks regularly broker connection and defined listener queue(s)
12
13
  * Listener AMQP - Listens to defined AMQP queues, parses recevied message into a EventHub::Message instance and calls handle_message method as defined in derived class.
13
- * Listener HTTP - Provides an http endpoint for health checks (Exp. /svc/{class_name}/heartbeat)
14
+ * Listener HTTP - Provides HTTP endpoints for health checks and monitoring (e.g. /svc/{class_name}/heartbeat, /svc/{class_name}/version)
14
15
 
15
16
  Processor2 is using Bunny http://rubybunny.info a feature complete RabbitMQ Client to interact with message broker. Processor2 can deal with long running message processing.
16
17
 
@@ -65,6 +66,7 @@ module EventHub
65
66
  # => :content_type
66
67
  # => :priority
67
68
  # => :delivery_tag
69
+ # => :correlation_id (if present in incoming AMQP message)
68
70
 
69
71
  # if an exception is raised in your code
70
72
  # it will be automatically catched by
@@ -114,6 +116,73 @@ I, [2018-02-09T15:22:35.658522 #37966] INFO -- : Listener is starting...
114
116
  I, [2018-02-09T15:22:35.699161 #37966] INFO -- : Listening to queue [example]
115
117
  ```
116
118
 
119
+ ## Logging
120
+
121
+ 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:
122
+
123
+ ```bash
124
+ bundle exec ruby example.rb --console-log-only
125
+ ```
126
+
127
+ This outputs logs in JSON format suitable for log aggregation systems:
128
+
129
+ ```json
130
+ {"@timestamp":"2026-01-18T10:00:00.000Z","@version":"1","severity":"INFO","host":"server1","application":"example","environment":"production","message":"example (1.0.0): has been started"}
131
+ ```
132
+
133
+ ## Correlation ID
134
+
135
+ 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.
136
+
137
+ When an incoming AMQP message includes a `correlation_id` in its metadata:
138
+
139
+ 1. **Automatic logging**: All log messages during message processing will include `correlation_id` as a separate field in structured JSON output
140
+ 2. **Automatic publishing**: Any messages published during processing will automatically include the same correlation_id in their AMQP headers
141
+ 3. **Available in args**: The correlation_id is passed to `handle_message` via `args[:correlation_id]`
142
+ 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
143
+
144
+ This happens transparently without any changes to your `handle_message` implementation:
145
+
146
+ ```ruby
147
+ def handle_message(message, args = {})
148
+ # correlation_id is available in args if needed
149
+ correlation_id = args[:correlation_id]
150
+
151
+ # Logging automatically includes correlation_id in JSON output
152
+ EventHub.logger.info("Processing order")
153
+
154
+ # Publishing automatically includes correlation_id
155
+ publish(message: response.to_json)
156
+
157
+ message.copy
158
+ end
159
+ ```
160
+
161
+ You can also explicitly set or override the correlation_id when publishing:
162
+
163
+ ```ruby
164
+ publish(message: msg.to_json, correlation_id: "550e8400-e29b-41d4-a716-446655440000")
165
+ ```
166
+
167
+ If no `correlation_id` is present in the AMQP metadata, the message body's `execution_id` is used as fallback to ensure tracing continuity.
168
+
169
+ ### How it works
170
+
171
+ 1. **Received**: When an AMQP message arrives, `correlation_id` is extracted from the message metadata
172
+ 2. **Fallback**: If no `correlation_id` in AMQP metadata, the message body's `execution_id` is used instead (ensuring tracing continuity)
173
+ 3. **Stored**: The value is stored in thread-local storage (`Thread.current`) for the duration of message processing
174
+ 4. **Passed**: The `correlation_id` is passed to `handle_message` via `args[:correlation_id]`
175
+ 5. **Logging**: The logger automatically reads from thread-local storage and includes it in JSON output
176
+ 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)
177
+ 7. **New messages**: When creating a new `EventHub::Message`:
178
+ - With `correlation_id` present → `execution_id` is set to match `correlation_id`
179
+ - Without `correlation_id` → `execution_id` is set to a new UUID (default behavior)
180
+ 8. **Cleared**: After message processing completes, the stored value is cleared
181
+
182
+ This design ensures correlation_id flows transparently through the entire message processing lifecycle. No code changes are required for existing implementations - just update the processor2 gem dependency.
183
+
184
+ **Note:** We use `correlation_id` (snake_case) to follow Ruby naming conventions, AMQP standard message properties, and stay consistent with other args keys like `:queue_name`, `:content_type`, etc. The `correlation_id` value is typically a UUID (e.g., `550e8400-e29b-41d4-a716-446655440000`).
185
+
117
186
  ## Configuration
118
187
 
119
188
  If --config option is not provided processor tries to load config/{class_name}.json. If file does not exist it loads default values as specified below.
@@ -133,10 +202,10 @@ If --config option is not provided processor tries to load config/{class_name}.j
133
202
  "tls_ca_certificates": [],
134
203
  "verify_peer": false,
135
204
  "show_bunny_logs": false,
136
- "heartbeat": {
205
+ "http": {
137
206
  "bind_address": "localhost",
138
207
  "port": 8080,
139
- "path": "/svc/{class_name}/heartbeat"
208
+ "base_path": "/svc/{class_name}"
140
209
  }
141
210
  },
142
211
  "processor": {
@@ -228,6 +297,239 @@ Final configuration result
228
297
 
229
298
  ```
230
299
 
300
+ ## HTTP Resources
301
+
302
+ Processor2 exposes HTTP resources for health checks and monitoring. All resources share the same HTTP server configuration.
303
+
304
+ **Configuration:**
305
+ ```json
306
+ {
307
+ "server": {
308
+ "http": {
309
+ "bind_address": "localhost",
310
+ "port": 8080,
311
+ "base_path": "/svc/{class_name}"
312
+ }
313
+ }
314
+ }
315
+ ```
316
+
317
+ Resources are mounted under the `base_path`:
318
+ - `{base_path}/heartbeat` - Health check
319
+ - `{base_path}/version` - Version info as JSON
320
+ - `{base_path}/docs` - README documentation as HTML
321
+ - `{base_path}/docs/configuration` - Configuration as HTML table
322
+ - `{base_path}/docs/changelog` - CHANGELOG as HTML
323
+ - `{base_path}/assets/*` - Static assets (CSS, images)
324
+
325
+ Accessing `{base_path}` or `{base_path}/` redirects to `{base_path}/docs`.
326
+
327
+ **Backward Compatibility:** If you have existing configuration using the old `heartbeat` block with `bind_address`, `port`, and `path`, it will continue to work. The new `http` configuration takes precedence when both are present.
328
+
329
+ ### Heartbeat
330
+
331
+ Returns detailed processor status information as JSON.
332
+
333
+ ```
334
+ GET {base_path}/heartbeat
335
+ ```
336
+
337
+ **Response:** `200 OK` with JSON body
338
+ ```json
339
+ {
340
+ "version": "1.0.0",
341
+ "pid": 12345,
342
+ "environment": "production",
343
+ "heartbeat": {
344
+ "started": "2026-01-18T10:00:00.000Z",
345
+ "stamp_last_request": "2026-01-18T12:30:00.000Z",
346
+ "uptime_in_ms": 9000000,
347
+ "heartbeat_cycle_in_ms": 300000,
348
+ "queues_consuming_from": ["my_processor"],
349
+ "queues_publishing_to": ["event_hub.inbound"],
350
+ "host": "server1.example.com",
351
+ "addresses": [
352
+ {"interface": "en0", "host_name": "server1", "ip_address": "192.168.1.100"}
353
+ ],
354
+ "messages": {
355
+ "total": 1000,
356
+ "successful": 995,
357
+ "unsuccessful": 5,
358
+ "average_size": 2048,
359
+ "average_process_time_in_ms": 50,
360
+ "total_process_time_in_ms": 50000
361
+ }
362
+ }
363
+ }
364
+ ```
365
+
366
+ ### Version
367
+
368
+ Returns the processor version as JSON.
369
+
370
+ ```
371
+ GET {base_path}/version
372
+ ```
373
+
374
+ **Response:** `200 OK` with JSON body
375
+ ```json
376
+ {
377
+ "version": "1.0.0"
378
+ }
379
+ ```
380
+
381
+ The version is taken from the `version` method in your derived processor class. If not defined, it returns `"?.?.?"`.
382
+
383
+ ```ruby
384
+ class MyProcessor < EventHub::Processor2
385
+ def version
386
+ "1.0.0" # your version
387
+ end
388
+ end
389
+ ```
390
+
391
+ ### Docs
392
+
393
+ Serves README.md as HTML with a built-in layout.
394
+
395
+ ```
396
+ GET {base_path}/docs
397
+ ```
398
+
399
+ **Response:** `200 OK` with HTML page
400
+
401
+ By default, looks for `README.md` in the current directory, then `doc/README.md`. You can customize the path via configuration:
402
+
403
+ ```json
404
+ {
405
+ "server": {
406
+ "http": {
407
+ "docs": {
408
+ "readme_path": "/custom/path/to/README.md"
409
+ }
410
+ }
411
+ }
412
+ }
413
+ ```
414
+
415
+ Or override completely by defining a `readme_as_html` method in your processor:
416
+
417
+ ```ruby
418
+ class MyProcessor < EventHub::Processor2
419
+ def readme_as_html
420
+ "<h1>Custom Documentation</h1><p>Your content here.</p>"
421
+ end
422
+ end
423
+ ```
424
+
425
+ ### Changelog
426
+
427
+ Serves CHANGELOG.md as HTML with a built-in layout.
428
+
429
+ ```
430
+ GET {base_path}/docs/changelog
431
+ ```
432
+
433
+ **Response:** `200 OK` with HTML page
434
+
435
+ By default, looks for `CHANGELOG.md` in the current directory, then `doc/CHANGELOG.md`. You can customize the path via configuration:
436
+
437
+ ```json
438
+ {
439
+ "server": {
440
+ "http": {
441
+ "docs": {
442
+ "changelog_path": "/custom/path/to/CHANGELOG.md"
443
+ }
444
+ }
445
+ }
446
+ }
447
+ ```
448
+
449
+ Or override completely by defining a `changelog_as_html` method in your processor:
450
+
451
+ ```ruby
452
+ class MyProcessor < EventHub::Processor2
453
+ def changelog_as_html
454
+ "<h1>Custom Changelog</h1><p>Your changes here.</p>"
455
+ end
456
+ end
457
+ ```
458
+
459
+ ### Configuration
460
+
461
+ Displays the active configuration as an HTML table. Sensitive values (passwords, tokens, keys) are automatically redacted.
462
+
463
+ ```
464
+ GET {base_path}/docs/configuration
465
+ ```
466
+
467
+ **Response:** `200 OK` with HTML page
468
+
469
+ By default, the following keys are redacted: `password`, `secret`, `token`, `api_key`, `credential`. You can customize the list by defining a `sensitive_keys` method in your processor:
470
+
471
+ ```ruby
472
+ # Override the entire list
473
+ class MyProcessor < EventHub::Processor2
474
+ def sensitive_keys
475
+ %w[password secret token api_key credential connection_string]
476
+ end
477
+ end
478
+
479
+ # Or extend the default list
480
+ class MyProcessor < EventHub::Processor2
481
+ def sensitive_keys
482
+ EventHub::DocsRenderer::DEFAULT_SENSITIVE_KEYS + %w[connection_string]
483
+ end
484
+ end
485
+ ```
486
+
487
+ Or override the entire page by defining a `configuration_as_html` method:
488
+
489
+ ```ruby
490
+ class MyProcessor < EventHub::Processor2
491
+ def configuration_as_html
492
+ "<h1>Custom Configuration</h1><p>Your content here.</p>"
493
+ end
494
+ end
495
+ ```
496
+
497
+ ### Disabling Resources
498
+
499
+ By default, all HTTP resources are enabled. You can control which resources are available by defining an `http_resources` method in your processor. The navbar adapts automatically.
500
+
501
+ ```ruby
502
+ class MyProcessor < EventHub::Processor2
503
+ def http_resources
504
+ [:heartbeat, :version, :docs, :changelog, :configuration] # default: all enabled
505
+ end
506
+ end
507
+ ```
508
+
509
+ To disable the configuration page for example:
510
+
511
+ ```ruby
512
+ class MyProcessor < EventHub::Processor2
513
+ def http_resources
514
+ [:heartbeat, :version, :docs, :changelog]
515
+ end
516
+ end
517
+ ```
518
+
519
+ ### Customizing Footer
520
+
521
+ The documentation pages display company name, version, and environment in the footer. Company name defaults to "Novartis" but can be customized by defining a `company_name` method in your processor:
522
+
523
+ ```ruby
524
+ class MyProcessor < EventHub::Processor2
525
+ def company_name
526
+ "My Company"
527
+ end
528
+ end
529
+ ```
530
+
531
+ **Future Extension:** A future version could allow overriding the default layout template and CSS assets using convention over configuration (e.g., placing custom files in `doc/layout.erb` or `doc/app.css`).
532
+
231
533
  ## Development
232
534
 
233
535
  ```
@@ -244,13 +546,21 @@ Final configuration result
244
546
  bundle exec rake
245
547
  ```
246
548
 
247
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
549
+ To install this gem onto your local machine, run `bundle exec rake install`.
248
550
 
249
551
  ## Publishing
250
552
 
251
- This project uses [Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) to securely publish gems to RubyGems.org. Trusted Publishing eliminates the need for long-lived API tokens by using OpenID Connect (OIDC) to establish a trusted relationship between GitHub Actions and RubyGems.org.
252
-
253
- With Trusted Publishing configured, gem releases are automatically published to RubyGems when the release workflow runs, providing a more secure and streamlined publishing process.
553
+ This project uses [Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) to securely publish gems to RubyGems.org via GitHub Actions. To release a new version:
554
+
555
+ 1. Update the version number in `lib/eventhub/version.rb`
556
+ 2. Merge changes to `main`
557
+ 3. Create a version tag either via command line or GitHub:
558
+ ```
559
+ git tag v1.x.x
560
+ git push origin v1.x.x
561
+ ```
562
+ Or on GitHub: go to **Releases** → **Create a new release** → enter the tag name (e.g. `v1.26.0`), select `main` as target, and publish.
563
+ 4. The `02 - Test, Build and Release` workflow triggers automatically, runs tests, builds the gem, and publishes it to [rubygems.org](https://rubygems.org)
254
564
 
255
565
  ## Contributing
256
566
 
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency "eventhub-components", "~> 0.4"
29
29
  spec.add_dependency "base64", "~> 0.3.0"
30
30
  spec.add_dependency "logger", "~> 1.6"
31
+ spec.add_dependency "kramdown", "~> 2.4"
31
32
 
32
33
  spec.add_development_dependency "rake", "~> 13.2"
33
34
  spec.add_development_dependency "rspec", "~> 3.13"
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ ## [1.0.0] 2026-01-18
4
+
5
+ * Initial release
6
+ * Routes messages from example.outbound to example.inbound queue
7
+ * Supports JSON message format
8
+ * Preserves message headers
data/example/receiver.rb CHANGED
@@ -2,6 +2,44 @@ require_relative "../lib/eventhub/base"
2
2
 
3
3
  module EventHub
4
4
  class Receiver < Processor2
5
+ def version
6
+ "2.0.0"
7
+ end
8
+
9
+ def company_name
10
+ "Example Company"
11
+ end
12
+
13
+ # Custom README served via method instead of file
14
+ def readme_as_html
15
+ <<~HTML
16
+ <h1>Receiver Processor</h1>
17
+ <p>This processor receives messages and deletes associated files.</p>
18
+ <h2>Features</h2>
19
+ <ul>
20
+ <li>Receives messages from the queue</li>
21
+ <li>Deletes files based on message ID</li>
22
+ <li>Logs all operations</li>
23
+ </ul>
24
+ <h2>Configuration</h2>
25
+ <p>No special configuration required.</p>
26
+ HTML
27
+ end
28
+
29
+ # Custom CHANGELOG served via method instead of file
30
+ def changelog_as_html
31
+ <<~HTML
32
+ <h1>Changelog</h1>
33
+ <h2>[2.0.0] 2026-01-18</h2><ul>
34
+ <li>Added custom documentation via methods</li>
35
+ <li>Improved error handling</li>
36
+ </ul>
37
+ <h2>[1.0.0] 2025-01-01</h2><ul>
38
+ <li>Initial release</li>
39
+ </ul>
40
+ HTML
41
+ end
42
+
5
43
  def handle_message(message, args = {})
6
44
  id = message.body["id"]
7
45
  EventHub.logger.info("[#{id}] - Received")
data/example/router.rb CHANGED
@@ -3,6 +3,10 @@ require_relative "../lib/eventhub/base"
3
3
  module EventHub
4
4
  # Demo class
5
5
  class Router < Processor2
6
+ def version
7
+ "1.0.0"
8
+ end
9
+
6
10
  def handle_message(message, args = {})
7
11
  id = message.body["id"]
8
12
  EventHub.logger.info("Received: [#{id}]")
@@ -13,7 +13,8 @@ module EventHub
13
13
  end
14
14
 
15
15
  def start
16
- EventHub.logger.info("Heartbeat is starting...")
16
+ cycle = Configuration.processor[:heartbeat_cycle_in_s]
17
+ EventHub.logger.info("Heartbeat is starting [cycle: #{cycle}s]...")
17
18
 
18
19
  every(60 * 60 * 24) { EventHub.logger.info("Actual actors: #{Celluloid::Actor.all.size}: #{Celluloid::Actor.all.map { |a| a.class }.join(", ")}") }
19
20
 
@@ -16,8 +16,18 @@ module EventHub
16
16
  end
17
17
 
18
18
  def start
19
- EventHub.logger.info("Listener amqp is starting...")
20
- EventHub::Configuration.processor[:listener_queues].each_with_index do |queue_name, index|
19
+ server = EventHub::Configuration.server
20
+ queues = EventHub::Configuration.processor[:listener_queues]
21
+ settings = [
22
+ server[:user],
23
+ server[:host],
24
+ server[:port],
25
+ server[:vhost],
26
+ "tls=#{server[:tls]}",
27
+ queues.join(", ")
28
+ ].join(", ")
29
+ EventHub.logger.info("Listener amqp is starting [#{settings}]...")
30
+ queues.each_with_index do |queue_name, index|
21
31
  async.listen(queue_name: queue_name, index: index)
22
32
  end
23
33
  end
@@ -30,21 +40,26 @@ module EventHub
30
40
  with_listen(args) do |connection, channel, consumer, queue, queue_name|
31
41
  EventHub.logger.info("Listening to queue [#{queue_name}]")
32
42
  consumer.on_delivery do |delivery_info, metadata, payload|
33
- EventHub.logger.info("#{queue_name}: [#{delivery_info.delivery_tag}]" \
34
- " delivery")
35
-
36
- @processor_instance.statistics.measure(payload.size) do
37
- handle_payload(payload: payload,
38
- connection: connection,
39
- queue_name: queue_name,
40
- content_type: metadata[:content_type],
41
- priority: metadata[:priority],
42
- delivery_tag: delivery_info.delivery_tag)
43
- channel.acknowledge(delivery_info.delivery_tag, false)
43
+ CorrelationId.with(metadata[:correlation_id]) do
44
+ EventHub.logger.info("#{queue_name}: [#{delivery_info.delivery_tag}]" \
45
+ " delivery")
46
+
47
+ @processor_instance.statistics.measure(payload.size) do
48
+ handle_payload(payload: payload,
49
+ connection: connection,
50
+ queue_name: queue_name,
51
+ content_type: metadata[:content_type],
52
+ priority: metadata[:priority],
53
+ delivery_tag: delivery_info.delivery_tag,
54
+ correlation_id: metadata[:correlation_id])
55
+ channel.acknowledge(delivery_info.delivery_tag, false)
56
+ end
57
+
58
+ EventHub.logger.info("#{queue_name}: [#{delivery_info.delivery_tag}]" \
59
+ " acknowledged")
60
+ ensure
61
+ ExecutionId.clear
44
62
  end
45
-
46
- EventHub.logger.info("#{queue_name}: [#{delivery_info.delivery_tag}]" \
47
- " acknowledged")
48
63
  end
49
64
  queue.subscribe_with(consumer, block: false)
50
65
  end
@@ -77,6 +92,15 @@ module EventHub
77
92
  # convert to EventHub message
78
93
  message = EventHub::Message.from_json(args[:payload])
79
94
 
95
+ # set execution_id for logging
96
+ ExecutionId.current = message.process_execution_id if message.valid?
97
+
98
+ # use execution_id as correlation_id if not already set from AMQP metadata
99
+ if CorrelationId.current.nil? && message.valid?
100
+ CorrelationId.current = message.process_execution_id
101
+ args[:correlation_id] ||= message.process_execution_id
102
+ end
103
+
80
104
  # append to execution history
81
105
  message.append_to_execution_history(EventHub::Configuration.name)
82
106
 
@@ -105,7 +129,7 @@ module EventHub
105
129
  end
106
130
 
107
131
  def pass_arguments(args = {})
108
- keys_to_pass = [:queue_name, :content_type, :priority, :delivery_tag]
132
+ keys_to_pass = [:queue_name, :content_type, :priority, :delivery_tag, :correlation_id]
109
133
  args.select { |key| keys_to_pass.include?(key) }
110
134
  end
111
135