legion-transport 1.2.0 → 1.2.2
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/.github/workflows/ci.yml +18 -0
- data/.rubocop.yml +46 -10
- data/CHANGELOG.md +20 -1
- data/CLAUDE.md +144 -0
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/README.md +123 -21
- data/legion-transport.gemspec +13 -13
- data/lib/legion/transport/common.rb +4 -1
- data/lib/legion/transport/connection/ssl.rb +2 -0
- data/lib/legion/transport/connection/vault.rb +2 -0
- data/lib/legion/transport/connection.rb +8 -24
- data/lib/legion/transport/consumer.rb +3 -0
- data/lib/legion/transport/exchange.rb +7 -10
- data/lib/legion/transport/exchanges/agent.rb +13 -0
- data/lib/legion/transport/exchanges/crypt.rb +2 -0
- data/lib/legion/transport/exchanges/extensions.rb +2 -0
- data/lib/legion/transport/exchanges/lex.rb +2 -0
- data/lib/legion/transport/exchanges/node.rb +2 -0
- data/lib/legion/transport/exchanges/task.rb +2 -0
- data/lib/legion/transport/local.rb +51 -0
- data/lib/legion/transport/message.rb +42 -21
- data/lib/legion/transport/messages/check_subtask.rb +2 -0
- data/lib/legion/transport/messages/dynamic.rb +3 -1
- data/lib/legion/transport/messages/lex_register.rb +2 -0
- data/lib/legion/transport/messages/request_cluster_secret.rb +6 -4
- data/lib/legion/transport/messages/subtask.rb +5 -3
- data/lib/legion/transport/messages/task.rb +3 -5
- data/lib/legion/transport/messages/task_log.rb +3 -3
- data/lib/legion/transport/messages/task_update.rb +4 -7
- data/lib/legion/transport/queue.rb +20 -6
- data/lib/legion/transport/queues/agent.rb +26 -0
- data/lib/legion/transport/queues/node.rb +2 -0
- data/lib/legion/transport/queues/node_crypt.rb +3 -1
- data/lib/legion/transport/queues/node_status.rb +2 -0
- data/lib/legion/transport/queues/task_log.rb +3 -1
- data/lib/legion/transport/queues/task_update.rb +2 -0
- data/lib/legion/transport/settings.rb +38 -36
- data/lib/legion/transport/version.rb +3 -1
- data/lib/legion/transport.rb +19 -17
- metadata +23 -31
- data/.github/workflows/rubocop-analysis.yml +0 -41
- data/.github/workflows/sourcehawk-scan.yml +0 -20
- data/CODE_OF_CONDUCT.md +0 -75
- data/CONTRIBUTING.md +0 -55
- data/INDIVIDUAL_CONTRIBUTOR_LICENSE.md +0 -30
- data/NOTICE.txt +0 -9
- data/SECURITY.md +0 -9
- data/attribution.txt +0 -1
- data/lib/legion/transport/messages/extension.rb +0 -21
- data/sourcehawk.yml +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b44d9bbca572702bcfe3d8f37f5ff0330b9e2fd5626d3a094bf32219470fb457
|
|
4
|
+
data.tar.gz: 36521e18cfe03a26403538bc1001d5f6b0203219c50b466447eae5f00bfaeec4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 131abad2f93409e13ed874eedf04f0014f61b89fa0d953449ad8747076ae48841e9a8a30a37174086e4cfc37a08fd039410d88d9b74c16b4eb81b7dca865798d
|
|
7
|
+
data.tar.gz: cbead836289a7df9f8fdc44d9e157fc86874b63795b587f2c27ecf4dd2cdeab8b8b3820fb6905086ca9e80af5dded515df51b77eb7e675c5bc9b0c8779b12718
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
ci:
|
|
9
|
+
uses: LegionIO/.github/.github/workflows/ci.yml@main
|
|
10
|
+
with:
|
|
11
|
+
needs-rabbitmq: true
|
|
12
|
+
|
|
13
|
+
release:
|
|
14
|
+
needs: ci
|
|
15
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
16
|
+
uses: LegionIO/.github/.github/workflows/release.yml@main
|
|
17
|
+
secrets:
|
|
18
|
+
rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
|
data/.rubocop.yml
CHANGED
|
@@ -1,22 +1,58 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 3.4
|
|
3
|
+
NewCops: enable
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
|
|
1
6
|
Layout/LineLength:
|
|
2
|
-
Max:
|
|
7
|
+
Max: 160
|
|
8
|
+
|
|
9
|
+
Layout/SpaceAroundEqualsInParameterDefault:
|
|
10
|
+
EnforcedStyle: space
|
|
11
|
+
|
|
12
|
+
Layout/HashAlignment:
|
|
13
|
+
EnforcedHashRocketStyle: table
|
|
14
|
+
EnforcedColonStyle: table
|
|
15
|
+
|
|
3
16
|
Metrics/MethodLength:
|
|
4
|
-
Max:
|
|
17
|
+
Max: 50
|
|
18
|
+
|
|
5
19
|
Metrics/ClassLength:
|
|
6
20
|
Max: 1500
|
|
21
|
+
|
|
22
|
+
Metrics/ModuleLength:
|
|
23
|
+
Max: 1500
|
|
24
|
+
|
|
7
25
|
Metrics/BlockLength:
|
|
8
|
-
Max:
|
|
26
|
+
Max: 40
|
|
27
|
+
AllowedPatterns: ['describe', 'context', 'it', 'shared_examples']
|
|
9
28
|
Exclude:
|
|
10
|
-
- 'spec
|
|
11
|
-
|
|
12
|
-
|
|
29
|
+
- 'spec/**/*'
|
|
30
|
+
|
|
31
|
+
Naming/PredicateMethod:
|
|
32
|
+
Enabled: false
|
|
33
|
+
|
|
34
|
+
Style/OneClassPerFile:
|
|
35
|
+
Exclude:
|
|
36
|
+
- 'lib/legion/transport/messages/task_update.rb'
|
|
37
|
+
|
|
38
|
+
Metrics/AbcSize:
|
|
39
|
+
Max: 60
|
|
40
|
+
|
|
13
41
|
Metrics/CyclomaticComplexity:
|
|
14
42
|
Max: 15
|
|
43
|
+
|
|
44
|
+
Metrics/PerceivedComplexity:
|
|
45
|
+
Max: 17
|
|
46
|
+
|
|
15
47
|
Style/Documentation:
|
|
16
48
|
Enabled: false
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
49
|
+
|
|
50
|
+
Style/SymbolArray:
|
|
51
|
+
Enabled: true
|
|
52
|
+
|
|
21
53
|
Style/FrozenStringLiteralComment:
|
|
54
|
+
Enabled: true
|
|
55
|
+
EnforcedStyle: always
|
|
56
|
+
|
|
57
|
+
Naming/FileName:
|
|
22
58
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
# Legion::Transport ChangeLog
|
|
2
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
## [1.2.2] - 2026-03-17
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- `Exchanges::Agent` topic exchange for identity-bound agent communication
|
|
9
|
+
- `Queues::Agent` per-agent queue (`agent.<agent_id>`) with auto-delete lifecycle
|
|
10
|
+
- Agent exchange separates identity-scoped traffic from infrastructure node traffic
|
|
11
|
+
|
|
12
|
+
## [1.2.1] - 2026-03-16
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- `Legion::Transport::Local` in-memory pub/sub for local development mode (no RabbitMQ required)
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Specs for all previously untested messages/, queues/, and exchanges/ subdirectories
|
|
19
|
+
- Coverage for 18 source files: 7 messages, 5 queues, 4 exchanges (plus task message)
|
|
20
|
+
- Line coverage increased from 65.9% to 81.64%
|
|
21
|
+
|
|
3
22
|
## v1.2.0
|
|
4
|
-
Moving from BitBucket to GitHub
|
|
23
|
+
Moving from BitBucket to GitHub. All git history is reset from this point on
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# legion-transport: AMQP Transport Layer for LegionIO
|
|
2
|
+
|
|
3
|
+
**Repository Level 3 Documentation**
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/CLAUDE.md`
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Ruby gem that manages the connection between LegionIO and its FIFO queue system (RabbitMQ over AMQP 0.9.1). Provides abstractions for exchanges, queues, messages, and consumers with thread-safe connection management.
|
|
9
|
+
|
|
10
|
+
**GitHub**: https://github.com/LegionIO/legion-transport
|
|
11
|
+
**License**: Apache-2.0
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Legion::Transport
|
|
17
|
+
├── Connection # Thread-safe RabbitMQ session/channel management
|
|
18
|
+
│ ├── SSL # TLS configuration (cert, key, CA, Vault PKI)
|
|
19
|
+
│ └── Vault # Vault-based credential retrieval (stub)
|
|
20
|
+
├── Exchange # Base exchange class (extends Bunny::Exchange)
|
|
21
|
+
│ └── Exchanges/
|
|
22
|
+
│ ├── Task # Task routing exchange
|
|
23
|
+
│ ├── Node # Node communication exchange
|
|
24
|
+
│ ├── Crypt # Encryption exchange
|
|
25
|
+
│ ├── Extensions # Extension exchange
|
|
26
|
+
│ └── Lex # LEX exchange (inherits Extensions)
|
|
27
|
+
├── Queue # Base queue class (extends Bunny::Queue)
|
|
28
|
+
│ └── Queues/
|
|
29
|
+
│ ├── Node # Node queue
|
|
30
|
+
│ ├── NodeCrypt # Node encryption queue
|
|
31
|
+
│ ├── NodeStatus # Node status queue
|
|
32
|
+
│ ├── TaskLog # Task logging queue
|
|
33
|
+
│ └── TaskUpdate # Task update queue
|
|
34
|
+
├── Message # Base message class with publish, encode, encrypt
|
|
35
|
+
│ └── Messages/
|
|
36
|
+
│ ├── Task # Task messages with dynamic routing keys
|
|
37
|
+
│ ├── SubTask # Subtask messages (conditions, transforms)
|
|
38
|
+
│ ├── Dynamic # Dynamic function-based messages
|
|
39
|
+
│ ├── CheckSubtask
|
|
40
|
+
│ ├── LexRegister
|
|
41
|
+
│ ├── RequestClusterSecret
|
|
42
|
+
│ ├── TaskLog
|
|
43
|
+
│ └── TaskUpdate
|
|
44
|
+
├── Consumer # AMQP consumer with auto-generated tags
|
|
45
|
+
├── Common # Shared utilities (channel mgmt, options merging, consumer tags)
|
|
46
|
+
├── Local # In-memory pub/sub for local development mode (no RabbitMQ)
|
|
47
|
+
├── Settings # Default configuration with env var overrides
|
|
48
|
+
└── Version # 1.2.1
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Key Design Patterns
|
|
52
|
+
|
|
53
|
+
### AMQP Client
|
|
54
|
+
Uses `bunny` gem for AMQP 0.9.1. The entry point sets `Legion::Transport::TYPE = 'bunny'` and `Legion::Transport::CONNECTOR = ::Bunny` as constants.
|
|
55
|
+
|
|
56
|
+
### Thread-Safe Connection Management
|
|
57
|
+
- `Concurrent::AtomicReference` wraps the AMQP session (one per process)
|
|
58
|
+
- `Concurrent::ThreadLocalVar` provides per-thread channels
|
|
59
|
+
- Auto-recovery on blocked/unblocked/recovery events
|
|
60
|
+
|
|
61
|
+
### Options Merging
|
|
62
|
+
`Common#options_builder` deep-merges default options -> class options -> instance options. Used by both Exchange and Queue constructors.
|
|
63
|
+
|
|
64
|
+
### Auto-Recreate on Mismatch
|
|
65
|
+
Both Exchange and Queue classes catch `PreconditionFailed` errors (parameter mismatch with existing RabbitMQ declarations) and attempt to delete + recreate once before raising.
|
|
66
|
+
|
|
67
|
+
## Dependencies
|
|
68
|
+
|
|
69
|
+
| Gem | Purpose |
|
|
70
|
+
|-----|---------|
|
|
71
|
+
| `bunny` (>= 2.23) | CRuby AMQP client |
|
|
72
|
+
| `concurrent-ruby` (>= 1.2) | Thread-safe data structures |
|
|
73
|
+
| `legion-json` | JSON serialization |
|
|
74
|
+
| `legion-settings` | Configuration management |
|
|
75
|
+
|
|
76
|
+
Optional runtime dependencies:
|
|
77
|
+
- `legion-crypt` - Message encryption support
|
|
78
|
+
- `legion-data` - Database models (used by Dynamic/SubTask messages)
|
|
79
|
+
- `legion-logging` - Structured logging
|
|
80
|
+
|
|
81
|
+
## Configuration
|
|
82
|
+
|
|
83
|
+
Settings are loaded via `Legion::Transport::Settings` with env var overrides:
|
|
84
|
+
|
|
85
|
+
| Env Var | Default | Description |
|
|
86
|
+
|---------|---------|-------------|
|
|
87
|
+
| `transport.connection.host` | `127.0.0.1` | RabbitMQ host |
|
|
88
|
+
| `transport.connection.port` | `5672` | RabbitMQ port |
|
|
89
|
+
| `transport.connection.user` | `guest` | RabbitMQ user |
|
|
90
|
+
| `transport.connection.password` | `guest` | RabbitMQ password |
|
|
91
|
+
| `transport.connection.vhost` | `/` | RabbitMQ vhost |
|
|
92
|
+
| `transport.prefetch` | `2` | Consumer prefetch count |
|
|
93
|
+
| `transport.messages.encrypt` | `false` | Enable message encryption |
|
|
94
|
+
| `transport.messages.ttl` | `nil` | Message TTL |
|
|
95
|
+
| `transport.messages.persistent` | `true` | Persistent messages |
|
|
96
|
+
|
|
97
|
+
Vault integration: If `Legion::Settings[:crypt][:vault][:connected]` is true, credentials are fetched from `rabbitmq/creds/legion` in Vault.
|
|
98
|
+
|
|
99
|
+
## File Map
|
|
100
|
+
|
|
101
|
+
| Path | Purpose |
|
|
102
|
+
|------|---------|
|
|
103
|
+
| `lib/legion/transport.rb` | Entry point, connector detection, logger/settings |
|
|
104
|
+
| `lib/legion/transport/connection.rb` | Session/channel lifecycle (setup, reconnect, shutdown) |
|
|
105
|
+
| `lib/legion/transport/connection/ssl.rb` | TLS settings module |
|
|
106
|
+
| `lib/legion/transport/connection/vault.rb` | Vault PKI integration (stub) |
|
|
107
|
+
| `lib/legion/transport/common.rb` | Shared module (channel access, deep_merge, consumer tags) |
|
|
108
|
+
| `lib/legion/transport/exchange.rb` | Base Exchange class |
|
|
109
|
+
| `lib/legion/transport/queue.rb` | Base Queue class |
|
|
110
|
+
| `lib/legion/transport/message.rb` | Base Message class with publish/encode/encrypt |
|
|
111
|
+
| `lib/legion/transport/consumer.rb` | AMQP consumer wrapper |
|
|
112
|
+
| `lib/legion/transport/settings.rb` | Default config, env var loading, Vault cred fetch |
|
|
113
|
+
| `lib/legion/transport/version.rb` | Version constant |
|
|
114
|
+
| `spec/` | RSpec test suite |
|
|
115
|
+
|
|
116
|
+
## Queue Defaults
|
|
117
|
+
|
|
118
|
+
All queues are created with:
|
|
119
|
+
- `durable: true` - survives broker restart
|
|
120
|
+
- `manual_ack: true` - explicit acknowledgment required
|
|
121
|
+
- `x-max-priority: 255` - priority queue support
|
|
122
|
+
- `x-overflow: reject-publish` - rejects new messages when full
|
|
123
|
+
- Dead letter exchange: `<exchange>.dlx`
|
|
124
|
+
|
|
125
|
+
## Exchange Defaults
|
|
126
|
+
|
|
127
|
+
All exchanges are created as:
|
|
128
|
+
- `type: topic` - supports routing key pattern matching
|
|
129
|
+
- `durable: true` - survives broker restart
|
|
130
|
+
- `auto_delete: false` - persists when no queues bound
|
|
131
|
+
|
|
132
|
+
## Testing
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
bundle install
|
|
136
|
+
bundle exec rspec
|
|
137
|
+
bundle exec rubocop
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Spec count: 144 examples
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
**Maintained By**: Matthew Iverson (@Esity)
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright 2021
|
|
189
|
+
Copyright 2021 Esity
|
|
190
190
|
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
192
|
you may not use this file except in compliance with the License.
|
data/README.md
CHANGED
|
@@ -1,36 +1,90 @@
|
|
|
1
|
-
Legion::Transport
|
|
2
|
-
=====
|
|
1
|
+
# Legion::Transport
|
|
3
2
|
|
|
4
|
-
Legion::Transport is the gem responsible for connecting LegionIO to
|
|
3
|
+
Legion::Transport is the Ruby gem responsible for connecting LegionIO to its FIFO queue system (RabbitMQ over AMQP 0.9.1). It provides thread-safe connection management, exchange/queue abstractions, message publishing with optional encryption, and consumer wrappers.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
------------------------------------------------
|
|
5
|
+
## Features
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
- Thread-safe connection management using `concurrent-ruby`
|
|
8
|
+
- AMQP 0.9.1 client via `bunny`
|
|
9
|
+
- Topic-based exchange routing with priority queue support
|
|
10
|
+
- Optional message encryption via `legion-crypt`
|
|
11
|
+
- Dynamic credential retrieval from HashiCorp Vault
|
|
12
|
+
- Auto-recovery on connection loss
|
|
13
|
+
- Dead letter exchange support
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
* Ruby 2.4+
|
|
15
|
+
## Supported Ruby Versions
|
|
13
16
|
|
|
17
|
+
- Ruby >= 3.4
|
|
14
18
|
|
|
15
|
-
Installation
|
|
16
|
-
------------------------
|
|
17
|
-
|
|
18
|
-
You can verify your installation using this piece of code:
|
|
19
|
+
## Installation
|
|
19
20
|
|
|
20
21
|
```bash
|
|
21
22
|
gem install legion-transport
|
|
22
23
|
```
|
|
23
24
|
|
|
25
|
+
Or add to your Gemfile:
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
gem 'legion-transport'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### Basic Connection
|
|
34
|
+
|
|
24
35
|
```ruby
|
|
25
36
|
require 'legion/transport'
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
|
|
38
|
+
Legion::Transport::Connection.setup
|
|
39
|
+
Legion::Transport::Connection.channel # => Bunny::Channel
|
|
40
|
+
Legion::Transport::Connection.session # => Bunny::Session
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Publishing a Message
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
Legion::Transport::Messages::Task.new(
|
|
47
|
+
function: 'my_function',
|
|
48
|
+
queue: 'my_extension',
|
|
49
|
+
routing_key: 'my_extension.my_function',
|
|
50
|
+
task_id: SecureRandom.uuid
|
|
51
|
+
).publish
|
|
30
52
|
```
|
|
31
53
|
|
|
32
|
-
|
|
33
|
-
|
|
54
|
+
### Creating a Queue
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
queue = Legion::Transport::Queues::Node.new
|
|
58
|
+
queue.subscribe do |delivery_info, properties, payload|
|
|
59
|
+
# process message
|
|
60
|
+
queue.acknowledge(delivery_info.delivery_tag)
|
|
61
|
+
end
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Creating an Exchange
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
exchange = Legion::Transport::Exchanges::Task.new
|
|
68
|
+
exchange.publish(payload, routing_key: 'task.my_runner.my_function')
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
72
|
+
|
|
73
|
+
Configuration is managed through `legion-settings` with environment variable overrides:
|
|
74
|
+
|
|
75
|
+
| Setting | Env Var | Default |
|
|
76
|
+
|---------|---------|---------|
|
|
77
|
+
| Host | `transport.connection.host` | `127.0.0.1` |
|
|
78
|
+
| Port | `transport.connection.port` | `5672` |
|
|
79
|
+
| User | `transport.connection.user` | `guest` |
|
|
80
|
+
| Password | `transport.connection.password` | `guest` |
|
|
81
|
+
| VHost | `transport.connection.vhost` | `/` |
|
|
82
|
+
| Prefetch | `transport.prefetch` | `2` |
|
|
83
|
+
| Encrypt | `transport.messages.encrypt` | `false` |
|
|
84
|
+
| TTL | `transport.messages.ttl` | `nil` |
|
|
85
|
+
| Persistent | `transport.messages.persistent` | `true` |
|
|
86
|
+
|
|
87
|
+
### Full Default Settings
|
|
34
88
|
|
|
35
89
|
```json
|
|
36
90
|
{
|
|
@@ -85,7 +139,55 @@ Settings
|
|
|
85
139
|
}
|
|
86
140
|
}
|
|
87
141
|
```
|
|
88
|
-
Authors
|
|
89
|
-
----------
|
|
90
142
|
|
|
91
|
-
|
|
143
|
+
### Vault Integration
|
|
144
|
+
|
|
145
|
+
When connected to HashiCorp Vault, credentials are automatically fetched from `rabbitmq/creds/legion`:
|
|
146
|
+
|
|
147
|
+
```ruby
|
|
148
|
+
# Vault must be connected via legion-crypt
|
|
149
|
+
# Credentials are fetched automatically during connection setup
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### TLS Support
|
|
153
|
+
|
|
154
|
+
TLS can be configured through transport settings:
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
# Settings under [:transport][:tls]
|
|
158
|
+
{
|
|
159
|
+
use_tls: true,
|
|
160
|
+
tls_cert: '/path/to/cert.pem',
|
|
161
|
+
tls_key: '/path/to/key.pem',
|
|
162
|
+
ca_certs: '/path/to/ca.pem',
|
|
163
|
+
verify_peer: true,
|
|
164
|
+
use_vault_pki: false
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Dependencies
|
|
169
|
+
|
|
170
|
+
| Gem | Version | Purpose |
|
|
171
|
+
|-----|---------|---------|
|
|
172
|
+
| `bunny` | >= 2.23 | AMQP 0.9.1 client |
|
|
173
|
+
| `concurrent-ruby` | >= 1.2 | Thread-safe data structures |
|
|
174
|
+
| `legion-json` | any | JSON serialization |
|
|
175
|
+
| `legion-settings` | any | Configuration management |
|
|
176
|
+
|
|
177
|
+
## Development
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
bundle install
|
|
181
|
+
bundle exec rspec
|
|
182
|
+
bundle exec rubocop
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Authors
|
|
186
|
+
|
|
187
|
+
- [Matthew Iverson](https://github.com/Esity) - current maintainer
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
|
|
192
|
+
|
|
193
|
+
Copyright 2021 Esity
|
data/legion-transport.gemspec
CHANGED
|
@@ -6,28 +6,28 @@ Gem::Specification.new do |spec|
|
|
|
6
6
|
spec.name = 'legion-transport'
|
|
7
7
|
spec.version = Legion::Transport::VERSION
|
|
8
8
|
spec.authors = ['Esity']
|
|
9
|
-
spec.email =
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
10
|
|
|
11
11
|
spec.summary = 'Manages the connection to the transport tier(RabbitMQ)'
|
|
12
12
|
spec.description = 'The Gem to connect LegionIO and it\'s extensions to the transport tier'
|
|
13
|
-
spec.homepage = 'https://github.com/
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/legion-transport'
|
|
14
14
|
spec.license = 'Apache-2.0'
|
|
15
15
|
spec.require_paths = ['lib']
|
|
16
|
-
spec.required_ruby_version = '>=
|
|
16
|
+
spec.required_ruby_version = '>= 3.4'
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
18
|
-
spec.
|
|
19
|
-
spec.extra_rdoc_files = %w[README.md LICENSE CHANGELOG.md]
|
|
18
|
+
spec.extra_rdoc_files = %w[README.md LICENSE CHANGELOG.md]
|
|
20
19
|
spec.metadata = {
|
|
21
|
-
'bug_tracker_uri'
|
|
22
|
-
'changelog_uri'
|
|
23
|
-
'documentation_uri'
|
|
24
|
-
'homepage_uri'
|
|
25
|
-
'source_code_uri'
|
|
26
|
-
'wiki_uri'
|
|
20
|
+
'bug_tracker_uri' => 'https://github.com/LegionIO/legion-transport/issues',
|
|
21
|
+
'changelog_uri' => 'https://github.com/LegionIO/legion-transport/blob/main/CHANGELOG.md',
|
|
22
|
+
'documentation_uri' => 'https://github.com/LegionIO/legion-transport',
|
|
23
|
+
'homepage_uri' => 'https://github.com/LegionIO/LegionIO',
|
|
24
|
+
'source_code_uri' => 'https://github.com/LegionIO/legion-transport',
|
|
25
|
+
'wiki_uri' => 'https://github.com/LegionIO/legion-transport/wiki',
|
|
26
|
+
'rubygems_mfa_required' => 'true'
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
spec.add_dependency 'bunny', '>= 2.
|
|
30
|
-
spec.add_dependency 'concurrent-ruby', '>= 1.
|
|
29
|
+
spec.add_dependency 'bunny', '>= 2.23'
|
|
30
|
+
spec.add_dependency 'concurrent-ruby', '>= 1.2'
|
|
31
31
|
spec.add_dependency 'legion-json'
|
|
32
32
|
spec.add_dependency 'legion-settings'
|
|
33
33
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'legion/transport/connection'
|
|
2
4
|
|
|
3
5
|
module Legion
|
|
@@ -53,7 +55,8 @@ module Legion
|
|
|
53
55
|
|
|
54
56
|
def close!
|
|
55
57
|
Legion::Transport.logger.error 'close! called'
|
|
56
|
-
false unless Legion::Transport::Connection.channel_open?
|
|
58
|
+
return false unless Legion::Transport::Connection.channel_open?
|
|
59
|
+
|
|
57
60
|
Legion::Transport::Connection.channel.close
|
|
58
61
|
end
|
|
59
62
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'concurrent-ruby'
|
|
2
4
|
|
|
3
5
|
module Legion
|
|
@@ -22,32 +24,20 @@ module Legion
|
|
|
22
24
|
setup(connection_name: connection_name)
|
|
23
25
|
end
|
|
24
26
|
|
|
25
|
-
def setup(connection_name: 'Legion', **)
|
|
27
|
+
def setup(connection_name: 'Legion', **)
|
|
26
28
|
Legion::Transport.logger.info("Using transport connector: #{Legion::Transport::CONNECTOR}")
|
|
27
29
|
|
|
28
30
|
if @session.respond_to?(:value) && session.respond_to?(:closed?) && session.closed?
|
|
29
31
|
@channel_thread = Concurrent::ThreadLocalVar.new(nil)
|
|
30
32
|
elsif @session.respond_to?(:value) && session.respond_to?(:closed?) && session.open?
|
|
31
33
|
nil
|
|
32
|
-
elsif Legion::Transport::TYPE == 'march_hare'
|
|
33
|
-
@session ||= Concurrent::AtomicReference.new(
|
|
34
|
-
MarchHare.connect(host: settings[:connection][:host],
|
|
35
|
-
vhost: settings[:connection][:vhost],
|
|
36
|
-
user: settings[:connection][:user],
|
|
37
|
-
password: settings[:connection][:password],
|
|
38
|
-
port: settings[:connection][:port])
|
|
39
|
-
)
|
|
40
|
-
@channel_thread = Concurrent::ThreadLocalVar.new(nil)
|
|
41
|
-
session.start
|
|
42
|
-
session.create_channel.basic_qos(settings[:prefetch])
|
|
43
|
-
Legion::Settings[:transport][:connected] = true
|
|
44
34
|
else
|
|
45
35
|
@session ||= Concurrent::AtomicReference.new(
|
|
46
36
|
connector.new(
|
|
47
37
|
Legion::Settings[:transport][:connection],
|
|
48
38
|
connection_name: connection_name,
|
|
49
|
-
logger:
|
|
50
|
-
log_level:
|
|
39
|
+
logger: Legion::Transport.logger,
|
|
40
|
+
log_level: :warn
|
|
51
41
|
)
|
|
52
42
|
)
|
|
53
43
|
@channel_thread = Concurrent::ThreadLocalVar.new(nil)
|
|
@@ -57,9 +47,7 @@ module Legion
|
|
|
57
47
|
Legion::Settings[:transport][:connected] = true
|
|
58
48
|
end
|
|
59
49
|
|
|
60
|
-
if session.respond_to? :on_blocked
|
|
61
|
-
session.on_blocked { Legion::Transport.logger.warn('Legion::Transport is being blocked by RabbitMQ!') }
|
|
62
|
-
end
|
|
50
|
+
session.on_blocked { Legion::Transport.logger.warn('Legion::Transport is being blocked by RabbitMQ!') } if session.respond_to? :on_blocked
|
|
63
51
|
|
|
64
52
|
if session.respond_to? :on_unblocked
|
|
65
53
|
session.on_unblocked do
|
|
@@ -76,15 +64,11 @@ module Legion
|
|
|
76
64
|
true
|
|
77
65
|
end
|
|
78
66
|
|
|
79
|
-
def channel
|
|
67
|
+
def channel
|
|
80
68
|
return @channel_thread.value if !@channel_thread.value.nil? && @channel_thread.value.open?
|
|
81
69
|
|
|
82
70
|
@channel_thread.value = session.create_channel(nil, settings[:channel][:default_worker_pool_size], false, 10)
|
|
83
|
-
|
|
84
|
-
@channel_thread.value.basic_qos(settings[:prefetch])
|
|
85
|
-
else
|
|
86
|
-
@channel_thread.value.prefetch(settings[:prefetch])
|
|
87
|
-
end
|
|
71
|
+
@channel_thread.value.prefetch(settings[:prefetch])
|
|
88
72
|
@channel_thread.value
|
|
89
73
|
end
|
|
90
74
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Legion
|
|
2
4
|
module Transport
|
|
3
5
|
class Consumer < Legion::Transport::CONNECTOR::Consumer
|
|
4
6
|
include Legion::Transport::Common
|
|
7
|
+
|
|
5
8
|
attr_reader :consumer_tag
|
|
6
9
|
|
|
7
10
|
def initialize(queue:, no_ack: false, exclusive: false, consumer_tag: generate_consumer_tag, **opts)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Legion
|
|
2
4
|
module Transport
|
|
3
5
|
class Exchange < Legion::Transport::CONNECTOR::Exchange
|
|
@@ -6,13 +8,7 @@ module Legion
|
|
|
6
8
|
def initialize(exchange = exchange_name, options = {})
|
|
7
9
|
@options = options
|
|
8
10
|
@type = options[:type] || default_type
|
|
9
|
-
|
|
10
|
-
super_options = options_builder(default_options, exchange_options, @options)
|
|
11
|
-
super_options[:type] = @type
|
|
12
|
-
super(channel, exchange, **super_options)
|
|
13
|
-
else
|
|
14
|
-
super(channel, @type, exchange, options_builder(default_options, exchange_options, @options))
|
|
15
|
-
end
|
|
11
|
+
super(channel, @type, exchange, options_builder(default_options, exchange_options, @options))
|
|
16
12
|
rescue Legion::Transport::CONNECTOR::PreconditionFailed, Legion::Transport::CONNECTOR::ChannelAlreadyClosed
|
|
17
13
|
raise unless @retries.nil?
|
|
18
14
|
|
|
@@ -23,7 +19,8 @@ module Legion
|
|
|
23
19
|
|
|
24
20
|
def delete_exchange(exchange)
|
|
25
21
|
Legion::Transport.logger.warn "Exchange:#{exchange} exists with wrong parameters, deleting and creating"
|
|
26
|
-
channel.
|
|
22
|
+
@channel = Legion::Transport::Connection.channel
|
|
23
|
+
@channel.exchange_delete(exchange)
|
|
27
24
|
end
|
|
28
25
|
|
|
29
26
|
def default_options
|
|
@@ -48,7 +45,7 @@ module Legion
|
|
|
48
45
|
end
|
|
49
46
|
|
|
50
47
|
def delete(options = {})
|
|
51
|
-
super
|
|
48
|
+
super
|
|
52
49
|
true
|
|
53
50
|
rescue Legion::Transport::CONNECTOR::PreconditionFailed
|
|
54
51
|
false
|
|
@@ -60,7 +57,7 @@ module Legion
|
|
|
60
57
|
|
|
61
58
|
def channel
|
|
62
59
|
@channel ||= Legion::Transport::Connection.channel
|
|
63
|
-
rescue ChannelLevelException => e
|
|
60
|
+
rescue Legion::Transport::CONNECTOR::ChannelLevelException => e
|
|
64
61
|
@channel = Legion::Transport::Connection.channel
|
|
65
62
|
raise e unless @channel.open?
|
|
66
63
|
end
|