legion-transport 1.1.4 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rubocop-analysis.yml +41 -0
  3. data/.github/workflows/sourcehawk-scan.yml +20 -0
  4. data/.gitignore +4 -2
  5. data/.rubocop.yml +7 -6
  6. data/CHANGELOG.md +2 -7
  7. data/CODE_OF_CONDUCT.md +75 -0
  8. data/CONTRIBUTING.md +55 -0
  9. data/Gemfile +7 -0
  10. data/INDIVIDUAL_CONTRIBUTOR_LICENSE.md +30 -0
  11. data/LICENSE +201 -0
  12. data/NOTICE.txt +9 -0
  13. data/README.md +90 -2
  14. data/SECURITY.md +9 -0
  15. data/attribution.txt +1 -0
  16. data/legion-transport.gemspec +23 -33
  17. data/lib/legion/transport.rb +25 -2
  18. data/lib/legion/transport/common.rb +3 -3
  19. data/lib/legion/transport/connection.rb +45 -18
  20. data/lib/legion/transport/connection/ssl.rb +35 -0
  21. data/lib/legion/transport/connection/vault.rb +9 -0
  22. data/lib/legion/transport/consumer.rb +0 -0
  23. data/lib/legion/transport/exchange.rb +15 -3
  24. data/lib/legion/transport/exchanges/crypt.rb +1 -1
  25. data/lib/legion/transport/exchanges/extensions.rb +11 -0
  26. data/lib/legion/transport/exchanges/lex.rb +1 -4
  27. data/lib/legion/transport/exchanges/node.rb +0 -0
  28. data/lib/legion/transport/exchanges/task.rb +0 -0
  29. data/lib/legion/transport/message.rb +53 -14
  30. data/lib/legion/transport/messages/check_subtask.rb +0 -0
  31. data/lib/legion/transport/messages/dynamic.rb +2 -1
  32. data/lib/legion/transport/messages/{node_health.rb → extension.rb} +4 -4
  33. data/lib/legion/transport/messages/lex_register.rb +3 -3
  34. data/lib/legion/transport/messages/request_cluster_secret.rb +0 -0
  35. data/lib/legion/transport/messages/subtask.rb +11 -0
  36. data/lib/legion/transport/messages/task.rb +41 -0
  37. data/lib/legion/transport/messages/task_log.rb +0 -0
  38. data/lib/legion/transport/messages/task_update.rb +7 -2
  39. data/lib/legion/transport/queue.rb +6 -6
  40. data/lib/legion/transport/queues/node.rb +0 -0
  41. data/lib/legion/transport/queues/node_crypt.rb +0 -0
  42. data/lib/legion/transport/queues/node_status.rb +0 -0
  43. data/lib/legion/transport/queues/task_log.rb +0 -0
  44. data/lib/legion/transport/queues/task_update.rb +0 -0
  45. data/lib/legion/transport/settings.rb +59 -35
  46. data/lib/legion/transport/version.rb +1 -1
  47. data/sonar-project.properties +1 -1
  48. data/sourcehawk.yml +4 -0
  49. metadata +44 -142
  50. data/.circleci/config.yml +0 -89
  51. data/.rspec +0 -1
  52. data/Rakefile +0 -6
  53. data/bin/console +0 -14
  54. data/bin/setup +0 -8
  55. data/bitbucket-pipelines.yml +0 -24
  56. data/settings/transport.json +0 -5
@@ -1,7 +1,7 @@
1
1
  module Legion
2
2
  module Transport
3
3
  module Exchanges
4
- class Lex < Legion::Transport::Exchange
4
+ class Crypt < Legion::Transport::Exchange
5
5
  def exchange_name
6
6
  'crypt'
7
7
  end
@@ -0,0 +1,11 @@
1
+ module Legion
2
+ module Transport
3
+ module Exchanges
4
+ class Extensions < Legion::Transport::Exchange
5
+ def exchange_name
6
+ 'extensions'
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,10 +1,7 @@
1
1
  module Legion
2
2
  module Transport
3
3
  module Exchanges
4
- class Lex < Legion::Transport::Exchange
5
- def exchange_name
6
- 'lex'
7
- end
4
+ class Lex < Legion::Transport::Exchanges::Extensions
8
5
  end
9
6
  end
10
7
  end
File without changes
File without changes
@@ -8,12 +8,10 @@ module Legion
8
8
  validate
9
9
  end
10
10
 
11
- def publish(options = @options) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
11
+ def publish(options = @options) # rubocop:disable Metrics/AbcSize
12
12
  raise unless @valid
13
13
 
14
- $exchanges = {} if $exchanges.nil?
15
- $exchanges[exchange.to_s] = exchange.new unless $exchanges.key?(exchange.to_s)
16
- exchange_dest = $exchanges[exchange.to_s]
14
+ exchange_dest = exchange.respond_to?(:new) ? exchange.new : exchange
17
15
  exchange_dest.publish(encode_message,
18
16
  routing_key: routing_key || '',
19
17
  content_type: options[:content_type] || content_type,
@@ -21,7 +19,48 @@ module Legion
21
19
  type: options[:type] || type,
22
20
  priority: options[:priority] || priority,
23
21
  expiration: options[:expiration] || expiration,
24
- headers: headers)
22
+ headers: headers,
23
+ persistent: persistent,
24
+ message_id: message_id,
25
+ timestamp: timestamp)
26
+ end
27
+
28
+ def app_id
29
+ @options[:app_id] if @options.key? :app_id
30
+
31
+ 'legion'
32
+ end
33
+
34
+ def message_id
35
+ @options[:message_id] || @options[:task_id]
36
+ end
37
+
38
+ # user_id Sender's identifier. https://www.rabbitmq.com/extensions.html#validated-user-id
39
+ def user_id
40
+ @options[:user_id] || Legion::Transport.settings[:connection][:user]
41
+ end
42
+
43
+ def reply_to
44
+ @options[:reply_to]
45
+ end
46
+
47
+ # ID of the message that this message is a reply to
48
+ def correlation_id
49
+ nil
50
+ end
51
+
52
+ def persistent
53
+ @options[:persistent] || Legion::Transport.settings[:messages][:persistent]
54
+ end
55
+
56
+ def expiration
57
+ if @options.key? :expiration
58
+ @options[:expiration]
59
+ elsif @options.key? :ttl
60
+ @options[:ttl]
61
+ elsif Legion::Transport.settings[:messages].key? :expiration
62
+ Legion::Transport.settings[:messages][:expiration]
63
+ end
25
64
  end
26
65
 
27
66
  def message
@@ -29,7 +68,7 @@ module Legion
29
68
  end
30
69
 
31
70
  def routing_key
32
- nil
71
+ @options[:routing_key] if @options.key? :routing_key
33
72
  end
34
73
 
35
74
  def encode_message
@@ -66,7 +105,7 @@ module Legion
66
105
  end
67
106
 
68
107
  def headers
69
- @options[:headers] ||= {}
108
+ @options[:headers] ||= Concurrent::Hash.new
70
109
  %i[task_id relationship_id trigger_namespace_id trigger_function_id parent_id master_id runner_namespace runner_class namespace_id function_id function chain_id debug].each do |header| # rubocop:disable Layout/LineLength
71
110
  next unless @options.key? header
72
111
 
@@ -74,18 +113,14 @@ module Legion
74
113
  end
75
114
  @options[:headers]
76
115
  rescue StandardError => e
77
- Legion::Logging.error e.message
78
- Legion::Logging.error e.backtrace
116
+ Legion::Transport.logger.error e.message
117
+ Legion::Transport.logger.error e.backtrace
79
118
  end
80
119
 
81
120
  def priority
82
121
  0
83
122
  end
84
123
 
85
- def expiration
86
- nil
87
- end
88
-
89
124
  def content_type
90
125
  'application/json'
91
126
  end
@@ -99,12 +134,16 @@ module Legion
99
134
  end
100
135
 
101
136
  def timestamp
102
- now.to_i
137
+ Time.now.to_i
103
138
  end
104
139
 
105
140
  def validate
106
141
  @valid = true
107
142
  end
143
+
144
+ def channel
145
+ Legion::Transport::Connection.channel
146
+ end
108
147
  end
109
148
  end
110
149
  end
File without changes
@@ -7,7 +7,8 @@ module Legion::Transport::Messages # rubocop:disable Style/ClassAndModuleChildre
7
7
  end
8
8
 
9
9
  def message
10
- { args: @options[:args] || @options }
10
+ { args: @options[:args] || @options,
11
+ function: function.values[:name] }
11
12
  end
12
13
 
13
14
  def routing_key
@@ -1,15 +1,15 @@
1
- require 'legion/transport/exchanges/lex'
1
+ require 'legion/transport/exchanges/extensions'
2
2
 
3
3
  module Legion
4
4
  module Transport
5
5
  module Messages
6
- class NodeHealth < Legion::Transport::Message
6
+ class LexRegister < Legion::Transport::Message
7
7
  def exchange
8
- Legion::Transport::Exchanges::Node
8
+ Legion::Transport::Exchanges::Extensions
9
9
  end
10
10
 
11
11
  def routing_key
12
- 'health'
12
+ 'extensions.register.'
13
13
  end
14
14
 
15
15
  def validate
@@ -1,15 +1,15 @@
1
- require 'legion/transport/exchanges/lex'
1
+ require 'legion/transport/exchanges/extensions'
2
2
 
3
3
  module Legion
4
4
  module Transport
5
5
  module Messages
6
6
  class LexRegister < Legion::Transport::Message
7
7
  def exchange
8
- Legion::Transport::Exchanges::Lex
8
+ Legion::Transport::Exchanges::Extensions
9
9
  end
10
10
 
11
11
  def routing_key
12
- 'lex.register.save'
12
+ 'extension_manager.register.save'
13
13
  end
14
14
 
15
15
  def validate
@@ -16,6 +16,17 @@ module Legion
16
16
  }
17
17
  end
18
18
 
19
+ def routing_key # rubocop:disable Metrics/AbcSize
20
+ if @options[:conditions].is_a?(String) && @options[:conditions].length > 2
21
+ 'task.subtask.conditioner'
22
+ elsif @options[:transformation].is_a?(String) && @options[:transformation].length > 2
23
+ 'task.subtask.transform'
24
+ elsif @options[:function_id].is_a? Integer
25
+ function = Legion::Data::Model::Function[@options[:function_id]]
26
+ "#{function.runner.extension.values[:exchange]}.#{function.runner.values[:queue]}.#{function.values[:name]}"
27
+ end
28
+ end
29
+
19
30
  def validate
20
31
  raise TypeError unless @options[:function].is_a? String
21
32
 
@@ -0,0 +1,41 @@
1
+ module Legion
2
+ module Transport
3
+ module Messages
4
+ class Task < Legion::Transport::Message
5
+ def exchange
6
+ if @options.key?(:exchange) && @options[:exchange].is_a?(String)
7
+ Legion::Transport::Exchanges.new(@options[:exchange])
8
+ else
9
+ Legion::Transport::Exchanges::Task.new
10
+ end
11
+ end
12
+
13
+ def message
14
+ @options
15
+ end
16
+
17
+ def routing_key # rubocop:disable Metrics/AbcSize
18
+ if @options.key? :routing_key
19
+ @options[:routing_key]
20
+ elsif @options[:conditions].is_a?(String) && @options[:conditions].length > 2
21
+ 'task.subtask.conditioner'
22
+ elsif @options[:transformation].is_a?(String) && @options[:transformation].length > 2
23
+ 'task.subtask.transform'
24
+ elsif @options[:queue].is_a?(String) && @options[:function].is_a?(String)
25
+ "#{@options[:queue]}.#{@options[:function]}"
26
+ elsif @options[:queue].is_a?(String) && @options[:function_name].is_a?(String)
27
+ "#{@options[:queue]}.#{@options[:function_name]}"
28
+ elsif @options[:queue].is_a?(String) && @options[:name].is_a?(String)
29
+ "#{@options[:queue]}.#{@options[:name]}"
30
+ end
31
+ end
32
+
33
+ def validate
34
+ raise TypeError unless @options[:function].is_a? String
35
+
36
+ @valid = true
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
File without changes
@@ -2,8 +2,13 @@ require 'legion/transport/exchanges/task'
2
2
 
3
3
  module Legion
4
4
  module Exception
5
- class InvalidTaskStatus; end
6
- class InvalidTaskId; end
5
+ class InvalidTaskStatus < ArgumentError
6
+ # exception class
7
+ end
8
+
9
+ class InvalidTaskId < ArgumentError
10
+ # exception class
11
+ end
7
12
  end
8
13
  end
9
14
 
@@ -9,18 +9,18 @@ module Legion
9
9
  super(channel, queue, options_builder(default_options, queue_options, options))
10
10
  rescue Legion::Transport::CONNECTOR::PreconditionFailed
11
11
  retries.zero? ? retries = 1 : raise
12
- recreate_queue(channel, queue)
12
+ recreate_queue(queue)
13
13
  retry
14
14
  end
15
15
 
16
- def recreate_queue(channel, queue)
17
- Legion::Logging.warn "Queue:#{queue} exists with wrong parameters, deleting and creating"
18
- queue = ::Bunny::Queue.new(channel, queue, no_declare: true, passive: true)
16
+ def recreate_queue(queue)
17
+ Legion::Transport.logger.warn "Queue:#{queue} exists with wrong parameters, deleting and creating"
18
+ queue = ::Bunny::Queue.new(Legion::Transport::Connection.channel, queue, no_declare: true, passive: true)
19
19
  queue.delete(if_empty: true)
20
20
  end
21
21
 
22
22
  def default_options
23
- hash = {}
23
+ hash = Concurrent::Hash.new
24
24
  hash[:manual_ack] = true
25
25
  hash[:durable] = true
26
26
  hash[:exclusive] = false
@@ -35,7 +35,7 @@ module Legion
35
35
  end
36
36
 
37
37
  def queue_options
38
- {}
38
+ Concurrent::Hash.new
39
39
  end
40
40
 
41
41
  def queue_name
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -3,62 +3,86 @@ require 'legion/settings'
3
3
  module Legion
4
4
  module Transport
5
5
  module Settings
6
- # Legion::Settings.merge_settings('transport', default) if Legion::Settings.method_defined? :merge_settings
7
6
  def self.connection
8
7
  {
9
8
  read_timeout: 1,
10
- heartbeat: 1,
9
+ heartbeat: 30,
11
10
  automatically_recover: true,
12
11
  continuation_timeout: 4000,
13
12
  network_recovery_interval: 1,
14
13
  connection_timeout: 1,
15
- user: 'guest',
16
- password: 'guest',
17
- host: '127.0.0.1',
18
- port: '5672',
19
- vhost: 'legion',
20
- recovery_attempts: 0,
21
- logger_level: 'info'
14
+ frame_max: 65_536,
15
+ user: ENV['transport.connection.user'] || 'guest',
16
+ password: ENV['transport.connection.password'] || 'guest',
17
+ host: ENV['transport.connection.host'] || '127.0.0.1',
18
+ port: ENV['transport.connection.port'] || '5672',
19
+ vhost: ENV['transport.connection.vhost'] || '/',
20
+ recovery_attempts: 100,
21
+ logger_level: ENV['transport.log_level'] || 'info',
22
+ connected: false
22
23
  }.merge(grab_vault_creds)
23
24
  end
24
25
 
25
26
  def self.grab_vault_creds
26
27
  return {} unless Legion::Settings[:crypt][:vault][:connected]
27
28
 
29
+ Legion::Transport.logger.info 'Attempting to grab RabbitMQ creds from vault'
28
30
  lease = Legion::Crypt.read('rabbitmq/creds/legion', type: nil)
29
- Legion::Logging.debug 'successfully grabbed amqp username from Vault'
31
+ Legion::Transport.logger.debug 'successfully grabbed amqp username from Vault'
30
32
  { user: lease[:username], password: lease[:password] }
31
33
  rescue StandardError
34
+ Legion::Transport.logger.warn 'Error reading rabbitmq creds from vault'
32
35
  {}
33
36
  end
34
37
 
38
+ def self.channel
39
+ {
40
+ default_worker_pool_size: ENV['transport.channel.default_worker_pool_size'] || 1,
41
+ session_worker_pool_size: ENV['transport.channel.session_worker_pool_size'] || 8
42
+ }
43
+ end
44
+
45
+ def self.queues
46
+ {
47
+ manual_ack: true,
48
+ durable: true,
49
+ exclusive: false,
50
+ block: false,
51
+ auto_delete: false,
52
+ arguments: { 'x-max-priority': 255, 'x-overflow': 'reject-publish' }
53
+ }
54
+ end
55
+
56
+ def self.exchanges
57
+ {
58
+ type: 'topic',
59
+ arguments: {},
60
+ auto_delete: false,
61
+ durable: true,
62
+ internal: false
63
+ }
64
+ end
65
+
66
+ def self.messages
67
+ {
68
+ encrypt: ENV['transport.messsages.encrypt'] == 'true',
69
+ ttl: ENV['transport.messages.ttl'],
70
+ priority: ENV['transport.messages.priority'].to_i || 0,
71
+ persistent: ENV['transport.messages.persistent'] == 'true'
72
+ }
73
+ end
74
+
35
75
  def self.default
36
76
  {
37
77
  type: 'rabbitmq',
38
78
  connected: false,
39
- logger_level: 'info',
40
- messages: {
41
- encrypt: false,
42
- ttl: nil,
43
- priority: 0
44
- },
45
- exchanges: {
46
- type: 'topic',
47
- arguments: {},
48
- auto_delete: false,
49
- durable: true,
50
- internal: false
51
- },
52
- queues: {
53
- manual_ack: true,
54
- durable: true,
55
- exclusive: false,
56
- block: false,
57
- auto_delete: false,
58
- arguments: { 'x-max-priority': 255, 'x-overflow': 'reject-publish' }
59
- },
60
- prefetch: 2,
61
- connection: connection
79
+ logger_level: ENV['transport.logger_level'] || 'info',
80
+ messages: messages,
81
+ prefetch: ENV['transport.prefetch'].to_i || 2,
82
+ exchanges: exchanges,
83
+ queues: queues,
84
+ connection: connection,
85
+ channel: channel
62
86
  }
63
87
  end
64
88
  end
@@ -67,6 +91,6 @@ end
67
91
 
68
92
  begin
69
93
  Legion::Settings.merge_settings('transport', Legion::Transport::Settings.default) if Legion.const_defined?('Settings')
70
- rescue StandardError => e
71
- Legion::Logging.fatal(e.message) if Legion::Logging.method_defined?(:fatal)
94
+ rescue StandardError
95
+ Legion::Transport.logger.fatal(e.message)
72
96
  end