legionio 0.2.0 → 0.3.4

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. metadata +22 -104
  3. data/.circleci/config.yml +0 -98
  4. data/.gitignore +0 -14
  5. data/.rspec +0 -2
  6. data/.rubocop.yml +0 -56
  7. data/CHANGELOG.md +0 -7
  8. data/Gemfile +0 -15
  9. data/LICENSE.txt +0 -21
  10. data/README.md +0 -46
  11. data/Rakefile +0 -38
  12. data/bin/console +0 -16
  13. data/bin/legion +0 -61
  14. data/bin/setup +0 -8
  15. data/bin/test +0 -32
  16. data/bitbucket-pipelines.yml +0 -55
  17. data/exe/legion +0 -58
  18. data/legion.gemspec +0 -60
  19. data/lib/legion.rb +0 -21
  20. data/lib/legion/exceptions/handled_task.rb +0 -6
  21. data/lib/legion/exceptions/invalidjson.rb +0 -8
  22. data/lib/legion/exceptions/missingargument.rb +0 -8
  23. data/lib/legion/exceptions/wrongtype.rb +0 -10
  24. data/lib/legion/exceptions/wrongtypes/array.rb +0 -11
  25. data/lib/legion/exceptions/wrongtypes/hash.rb +0 -11
  26. data/lib/legion/exceptions/wrongtypes/integer.rb +0 -11
  27. data/lib/legion/exceptions/wrongtypes/string.rb +0 -11
  28. data/lib/legion/extensions.rb +0 -151
  29. data/lib/legion/extensions/actors/base.rb +0 -53
  30. data/lib/legion/extensions/actors/every.rb +0 -50
  31. data/lib/legion/extensions/actors/loop.rb +0 -34
  32. data/lib/legion/extensions/actors/nothing.rb +0 -15
  33. data/lib/legion/extensions/actors/once.rb +0 -42
  34. data/lib/legion/extensions/actors/poll.rb +0 -90
  35. data/lib/legion/extensions/actors/subscription.rb +0 -120
  36. data/lib/legion/extensions/builders/actors.rb +0 -62
  37. data/lib/legion/extensions/builders/base.rb +0 -38
  38. data/lib/legion/extensions/builders/helpers.rb +0 -26
  39. data/lib/legion/extensions/builders/runners.rb +0 -54
  40. data/lib/legion/extensions/core.rb +0 -84
  41. data/lib/legion/extensions/helpers/base.rb +0 -88
  42. data/lib/legion/extensions/helpers/core.rb +0 -20
  43. data/lib/legion/extensions/helpers/lex.rb +0 -22
  44. data/lib/legion/extensions/helpers/logger.rb +0 -48
  45. data/lib/legion/extensions/helpers/task.rb +0 -42
  46. data/lib/legion/extensions/helpers/transport.rb +0 -45
  47. data/lib/legion/extensions/transport.rb +0 -156
  48. data/lib/legion/process.rb +0 -138
  49. data/lib/legion/runner.rb +0 -57
  50. data/lib/legion/runner/log.rb +0 -12
  51. data/lib/legion/runner/status.rb +0 -72
  52. data/lib/legion/service.rb +0 -80
  53. data/lib/legion/supervison.rb +0 -14
  54. data/lib/legion/version.rb +0 -5
  55. data/settings/client.json +0 -9
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
- module Legion
5
- module Extensions
6
- module Helpers
7
- module Core
8
- include Legion::Extensions::Helpers::Base
9
-
10
- def settings
11
- if Legion::Settings[:extensions].key?(lex_filename.to_sym)
12
- Legion::Settings[:extensions][lex_filename.to_sym]
13
- else
14
- { logger: { level: 'info', extended: false } }
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Legion
4
- module Extensions
5
- module Helpers
6
- module Lex
7
- include Legion::Extensions::Helpers::Core
8
- include Legion::Extensions::Helpers::Logger
9
-
10
- def self.included(base)
11
- base.send :extend, Legion::Extensions::Helpers::Core if base.class == Class
12
- base.send :extend, Legion::Extensions::Helpers::Logger if base.class == Class
13
- base.extend base if base.class == Module
14
- end
15
-
16
- def default_settings
17
- { logger: { level: 'info' } }
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Legion
4
- module Extensions
5
- module Helpers
6
- module Logger
7
- def log
8
- return @log unless @log.nil?
9
-
10
- logger_hash = { lex: lex_filename || nil }
11
- logger_hash[:lex] = lex_filename.first if logger_hash[:lex].is_a? Array
12
- if respond_to?(:settings) && settings.key?(:logger)
13
- logger_hash[:level] = settings[:logger][:level] if settings[:logger].key? :level
14
- logger_hash[:level] = settings[:logger][:log_file] if settings[:logger].key? :log_file
15
- logger_hash[:trace] = settings[:logger][:trace] if settings[:logger].key? :trace
16
- logger_hash[:extended] = settings[:logger][:extended] if settings[:logger].key? :extended
17
- elsif respond_to?(:settings)
18
- Legion::Logging.warn Legion::Settings[:extensions][lex_filename.to_sym]
19
- Legion::Logging.warn "#{lex_name} has settings but no :logger key"
20
- else
21
- Legion::Logging.warn 'no settings'
22
- end
23
- @log = Legion::Logging::Logger.new(logger_hash)
24
- end
25
-
26
- def handle_exception(exception, task_id: nil, **opts)
27
- log.error exception.message + " for task_id: #{task_id} but was logged "
28
- log.error exception.backtrace[0..10]
29
- log.error opts
30
-
31
- unless task_id.nil?
32
- Legion::Transport::Messages::TaskLog.new(
33
- task_id: task_id,
34
- runner_class: to_s,
35
- entry: {
36
- exception: true,
37
- message: exception.message,
38
- **opts
39
- }
40
- ).publish
41
- end
42
-
43
- raise Legion::Exception::HandledTask
44
- end
45
- end
46
- end
47
- end
48
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'legion/transport'
4
- require 'legion/transport/messages/task_update'
5
- require 'legion/transport/messages/task_log'
6
-
7
- module Legion
8
- module Extensions
9
- module Helpers
10
- module Task
11
- def generate_task_log(task_id:, runner_class: to_s, function:, **payload)
12
- Legion::Transport::Messages::TaskLog.new(task_id: task_id, runner_class: runner_class, function: function, entry: payload).publish
13
- end
14
-
15
- def task_update(task_id, status, **opts)
16
- return if task_id.nil? || status.nil?
17
-
18
- update_hash = { task_id: task_id, status: status }
19
- %i[results payload function_args payload results].each do |column|
20
- update_hash[column] = opts[column] if opts.key? column
21
- end
22
- Legion::Transport::Messages::TaskUpdate.new(update_hash).publish
23
- rescue StandardError => e
24
- log.fatal e.message
25
- log.fatal e.backtrace
26
- raise e
27
- end
28
-
29
- def generate_task_id(function_id:, status: 'task.queued', **opts)
30
- insert = { status: status, function_id: function_id }
31
- insert[:payload] = Legion::JSON.dump(opts[:payload]) if opts.key? :payload
32
- insert[:function_args] = Legion::JSON.dump(opts[:args]) if opts.key? :args
33
- %i[master_id parent_id relationship_id task_id].each do |column|
34
- insert[column] = opts[column] if opts.key? column
35
- end
36
-
37
- { success: true, task_id: Legion::Data::Model::Task.insert(insert), **insert }
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Legion
6
- module Extensions
7
- module Helpers
8
- module Transport
9
- include Legion::Extensions::Helpers::Base
10
-
11
- def transport_path
12
- @transport_path ||= "#{full_path}/transport"
13
- end
14
-
15
- def transport_class
16
- @transport_class ||= lex_class::Transport
17
- end
18
-
19
- def messages
20
- @messages ||= transport_class::Messages
21
- end
22
-
23
- def queues
24
- @queues ||= transport_class::Queues
25
- end
26
-
27
- def exchanges
28
- @exchanges ||= transport_class::Exchanges
29
- end
30
-
31
- def default_exchange
32
- @default_exchange ||= build_default_exchange
33
- end
34
-
35
- def build_default_exchange
36
- exchange = "#{transport_class}::Exchanges::#{lex_const}"
37
- return Object.const_get(exchange) if transport_class::Exchanges.const_defined? lex_const
38
-
39
- transport_class::Exchanges.const_set(lex_const, Class.new(Legion::Transport::Exchange))
40
- @default_exchange = Kernel.const_get(exchange)
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,156 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Legion
4
- module Extensions
5
- module Transport
6
- include Legion::Extensions::Helpers::Transport
7
-
8
- attr_accessor :exchanges, :queues, :consumers, :messages
9
- def build
10
- @queues = []
11
- @exchanges = []
12
- @messages = []
13
- @consumers = []
14
- generate_base_modules
15
- require_transport_items
16
-
17
- build_e_to_e
18
- build_e_to_q(e_to_q)
19
- build_e_to_q(additional_e_to_q)
20
- auto_create_dlx_exchange
21
- auto_create_dlx_queue
22
- rescue StandardError => e
23
- Legion::Logging.error e.message
24
- Legion::Logging.error e.backtrace
25
- end
26
-
27
- def generate_base_modules
28
- lex_class.const_set('Transport', Module.new) unless lex_class.const_defined?('Transport')
29
- %w[Queues Exchanges Messages Consumers].each do |thing|
30
- next if transport_class.const_defined? thing
31
-
32
- transport_class.const_set(thing, Module.new)
33
- end
34
- end
35
-
36
- def require_transport_items
37
- { 'exchanges': @exchanges, 'queues': @queues, 'consumers': @consumers, 'messages': @messages }.each do |item, obj|
38
- Dir[File.expand_path("#{transport_path}/#{item}/*.rb")].sort.each do |file|
39
- require file
40
- file_name = file.to_s.split('/').last.split('.').first
41
- obj.push(file_name) unless obj.include?(file_name)
42
- end
43
- end
44
- end
45
-
46
- def auto_create_exchange(exchange, default_exchange = false)
47
- if Object.const_defined? exchange
48
- Legion::Logging.warn "#{exchange} is already defined"
49
- return
50
- end
51
- return build_default_exchange if default_exchange
52
-
53
- transport_class::Exchanges.const_set(exchange.split('::').pop, Class.new(Legion::Transport::Exchange) do
54
- def exchange_name
55
- self.class.ancestors.first.to_s.split('::')[5].downcase
56
- end
57
- end)
58
- end
59
-
60
- def auto_create_queue(queue)
61
- if Kernel.const_defined?(queue)
62
- Legion::Logging.warn "#{queue} is already defined"
63
- return
64
- end
65
-
66
- Kernel.const_set(queue, Class.new(Legion::Transport::Queue))
67
- end
68
-
69
- def auto_create_dlx_exchange
70
- return if transport_class::Exchanges.const_defined? 'Dlx'
71
-
72
- dlx = transport_class::Exchanges.const_set('Dlx', Class.new(default_exchange) do
73
- def exchange_name
74
- "#{super}.dlx"
75
- end
76
- end)
77
- dlx.new
78
- dlx
79
- end
80
-
81
- def auto_create_dlx_queue
82
- return if transport_class::Queues.const_defined?('Dlx')
83
-
84
- special_name = default_exchange.new.exchange_name
85
- dlx_queue = Legion::Transport::Queue.new "#{special_name}.dlx"
86
- dlx_queue.bind("#{special_name}.dlx", { routing_key: '#' })
87
- end
88
-
89
- def build_e_to_q(array)
90
- array.each do |binding|
91
- binding[:routing_key] = nil unless binding.key? :routing_key
92
- binding[:to] = nil unless binding.key? :to
93
- bind_e_to_q(**binding)
94
- end
95
- end
96
-
97
- def bind_e_to_q(to:, from: default_exchange, routing_key: nil)
98
- if from.is_a? String
99
- from = "#{transport_class}::Exchanges::#{from.split('_').collect(&:capitalize).join}" unless from.include?('::')
100
- auto_create_exchange(from) unless Object.const_defined? from
101
- end
102
-
103
- if to.is_a? String
104
- to = "#{transport_class}::Queues::#{to.split('_').collect(&:capitalize).join}" unless to.include?('::')
105
- auto_create_queue(to) unless Object.const_defined?(to)
106
- end
107
-
108
- routing_key = to.to_s.split('::').last.downcase if routing_key.nil?
109
- bind(from, to, routing_key: routing_key)
110
- end
111
-
112
- def build_e_to_e
113
- e_to_e.each do |binding|
114
- if binding[:from].is_a? String
115
- binding[:from] = "#{transport_class}::Exchanges::#{binding[:from].capitalize}" unless binding[:from].include?('::')
116
- auto_create_exchange(binding[:from]) unless Object.const_defined? binding[:from]
117
- end
118
-
119
- if binding[:to].is_a? String
120
- binding[:to] = "#{transport_class}::Exchanges::#{binding[:to].capitalize}" unless binding[:to].include?('::')
121
- auto_create_exchange(binding[:to]) unless Object.const_defined? binding[:to]
122
- end
123
-
124
- bind(binding[:from], binding[:to], binding)
125
- end
126
- end
127
-
128
- def bind(from, to, routing_key: nil, **_options)
129
- from = from.is_a?(String) ? Kernel.const_get(from).new : from.new
130
- to = to.is_a?(String) ? Kernel.const_get(to).new : to.new
131
- to.bind(from, routing_key: routing_key)
132
- rescue StandardError => e
133
- Legion::Logging.fatal e.message
134
- Legion::Logging.fatal e.backtrace
135
- Legion::Logging.fatal({ from: from, to: to, routing_key: routing_key })
136
- end
137
-
138
- def e_to_q
139
- [] if !@exchanges.count != 1
140
- auto = []
141
- @queues.each do |queue|
142
- auto.push(from: @exchanges.first, to: queue, routing_key: queue)
143
- end
144
- auto
145
- end
146
-
147
- def e_to_e
148
- []
149
- end
150
-
151
- def additional_e_to_q
152
- []
153
- end
154
- end
155
- end
156
- end
@@ -1,138 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'fileutils'
4
-
5
- module Legion
6
- # Responsible for starting the Legion process
7
- class Process
8
- def self.run!(options)
9
- Legion::Process.new(options).run!
10
- end
11
-
12
- attr_reader :options, :quit, :service
13
-
14
- def initialize(options)
15
- @options = options
16
- options[:logfile] = File.expand_path(logfile) if logfile?
17
- options[:pidfile] = File.expand_path(pidfile) if pidfile?
18
- end
19
-
20
- def daemonize?
21
- options[:daemonize]
22
- end
23
-
24
- def logfile
25
- options[:logfile]
26
- end
27
-
28
- def pidfile
29
- options[:pidfile]
30
- end
31
-
32
- def logfile?
33
- !logfile.nil?
34
- end
35
-
36
- def pidfile?
37
- !pidfile.nil?
38
- end
39
-
40
- def info(msg)
41
- puts "[#{::Process.pid}] [#{Time.now}] #{msg}"
42
- end
43
-
44
- def run!
45
- start_time = Time.now
46
- @options[:time_limit] = @options[:time_limit].to_i if @options.key? :time_limit
47
- @quit = false
48
- check_pid
49
- daemonize if daemonize?
50
- write_pid
51
- trap_signals
52
-
53
- until quit
54
- sleep(1) # in real life, something productive would happen here
55
- if @options.key? :time_limit
56
- @quit = true if Time.now - start_time > @options[:time_limit]
57
- end
58
- end
59
- Legion::Logging.info('Legion is shutting down!')
60
- Legion.shutdown
61
- Legion::Logging.info('Legion has shutdown. Goodbye!')
62
-
63
- exit
64
- end
65
-
66
- #==========================================================================
67
- # DAEMONIZING, PID MANAGEMENT, and OUTPUT REDIRECTION
68
- #==========================================================================
69
-
70
- def daemonize
71
- exit if fork
72
- ::Process.setsid
73
- exit if fork
74
- Dir.chdir '/'
75
- end
76
-
77
- def write_pid
78
- if pidfile?
79
- begin
80
- File.open(pidfile, ::File::CREAT | ::File::EXCL | ::File::WRONLY) { |f| f.write(::Process.pid.to_s) }
81
- at_exit { File.delete(pidfile) if File.exist?(pidfile) }
82
- rescue Errno::EEXIST
83
- check_pid
84
- retry
85
- end
86
- end
87
- false
88
- end
89
-
90
- def check_pid
91
- if pidfile?
92
- case pid_status(pidfile)
93
- when :running, :not_owned
94
- exit(1)
95
- when :dead
96
- File.delete(pidfile)
97
- end
98
- end
99
- false
100
- end
101
-
102
- def pid_status(pidfile)
103
- return :exited unless File.exist?(pidfile)
104
-
105
- pid = ::File.read(pidfile).to_i
106
- return :dead if pid.zero?
107
-
108
- ::Process.kill(0, pid)
109
- :running
110
- rescue Errno::ESRCH
111
- :dead
112
- rescue Errno::EPERM
113
- :not_owned
114
- end
115
-
116
- #==========================================================================
117
- # SIGNAL HANDLING
118
- #==========================================================================
119
-
120
- def trap_signals
121
- # trap(:QUIT) do # graceful shutdown
122
- # info 'shutting down'
123
- # @quit = true
124
- # end
125
-
126
- trap('SIGTERM') do
127
- info 'sigterm'
128
- end
129
-
130
- trap('SIGHUP') do
131
- info 'sithup'
132
- end
133
- trap('SIGINT') do
134
- @quit = true
135
- end
136
- end
137
- end
138
- end