legionio 0.3.4 → 0.4.3

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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +136 -0
  3. data/.gitignore +15 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +94 -0
  6. data/CHANGELOG.md +47 -0
  7. data/Dockerfile +9 -0
  8. data/Gemfile +3 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +161 -0
  11. data/Rakefile +32 -0
  12. data/bitbucket-pipelines.yml +19 -0
  13. data/docker_deploy.rb +10 -0
  14. data/exe/legion +4 -0
  15. data/exe/legionio +53 -0
  16. data/exe/lex_gen +5 -0
  17. data/legionio.gemspec +64 -0
  18. data/lib/legion.rb +25 -0
  19. data/lib/legion/cli.rb +56 -0
  20. data/lib/legion/cli/chain.rb +35 -0
  21. data/lib/legion/cli/cohort.rb +10 -0
  22. data/lib/legion/cli/function.rb +41 -0
  23. data/lib/legion/cli/lex/actor.rb +31 -0
  24. data/lib/legion/cli/lex/exchange.rb +32 -0
  25. data/lib/legion/cli/lex/message.rb +32 -0
  26. data/lib/legion/cli/lex/queue.rb +45 -0
  27. data/lib/legion/cli/lex/runner.rb +70 -0
  28. data/lib/legion/cli/lex/templates/actor.erb +6 -0
  29. data/lib/legion/cli/lex/templates/actor_spec.erb +0 -0
  30. data/lib/legion/cli/lex/templates/base/bitbucket.yml.erb +69 -0
  31. data/lib/legion/cli/lex/templates/base/gemfile.erb +3 -0
  32. data/lib/legion/cli/lex/templates/base/gemspec.erb +26 -0
  33. data/lib/legion/cli/lex/templates/base/gitignore.erb +11 -0
  34. data/lib/legion/cli/lex/templates/base/lex.erb +9 -0
  35. data/lib/legion/cli/lex/templates/base/lex_spec.erb +5 -0
  36. data/lib/legion/cli/lex/templates/base/lic.erb +21 -0
  37. data/lib/legion/cli/lex/templates/base/rakefile.erb +6 -0
  38. data/lib/legion/cli/lex/templates/base/readme.md.erb +2 -0
  39. data/lib/legion/cli/lex/templates/base/rubocop.yml.erb +15 -0
  40. data/lib/legion/cli/lex/templates/base/spec_helper.rb.erb +11 -0
  41. data/lib/legion/cli/lex/templates/base/version.erb +7 -0
  42. data/lib/legion/cli/lex/templates/exchange.erb +11 -0
  43. data/lib/legion/cli/lex/templates/exchange_spec.erb +0 -0
  44. data/lib/legion/cli/lex/templates/message.erb +23 -0
  45. data/lib/legion/cli/lex/templates/message_spec.erb +0 -0
  46. data/lib/legion/cli/lex/templates/queue.erb +12 -0
  47. data/lib/legion/cli/lex/templates/queue_helper.erb +24 -0
  48. data/lib/legion/cli/lex/templates/queue_spec.erb +11 -0
  49. data/lib/legion/cli/lex/templates/runner.erb +11 -0
  50. data/lib/legion/cli/lex/templates/runner_spec.erb +11 -0
  51. data/lib/legion/cli/relationship.rb +22 -0
  52. data/lib/legion/cli/task.rb +49 -0
  53. data/lib/legion/cli/trigger.rb +88 -0
  54. data/lib/legion/cli/version.rb +5 -0
  55. data/lib/legion/extensions.rb +219 -0
  56. data/lib/legion/extensions/actors/base.rb +47 -0
  57. data/lib/legion/extensions/actors/defaults.rb +28 -0
  58. data/lib/legion/extensions/actors/every.rb +48 -0
  59. data/lib/legion/extensions/actors/loop.rb +32 -0
  60. data/lib/legion/extensions/actors/nothing.rb +15 -0
  61. data/lib/legion/extensions/actors/once.rb +40 -0
  62. data/lib/legion/extensions/actors/poll.rb +87 -0
  63. data/lib/legion/extensions/actors/subscription.rb +139 -0
  64. data/lib/legion/extensions/builders/actors.rb +61 -0
  65. data/lib/legion/extensions/builders/base.rb +36 -0
  66. data/lib/legion/extensions/builders/helpers.rb +24 -0
  67. data/lib/legion/extensions/builders/runners.rb +58 -0
  68. data/lib/legion/extensions/core.rb +131 -0
  69. data/lib/legion/extensions/data.rb +58 -0
  70. data/lib/legion/extensions/data/migrator.rb +28 -0
  71. data/lib/legion/extensions/data/model.rb +8 -0
  72. data/lib/legion/extensions/helpers/base.rb +82 -0
  73. data/lib/legion/extensions/helpers/cache.rb +23 -0
  74. data/lib/legion/extensions/helpers/core.rb +41 -0
  75. data/lib/legion/extensions/helpers/data.rb +23 -0
  76. data/lib/legion/extensions/helpers/lex.rb +48 -0
  77. data/lib/legion/extensions/helpers/logger.rb +44 -0
  78. data/lib/legion/extensions/helpers/task.rb +60 -0
  79. data/lib/legion/extensions/helpers/transport.rb +44 -0
  80. data/lib/legion/extensions/transport.rb +159 -0
  81. data/lib/legion/lex.rb +89 -0
  82. data/lib/legion/process.rb +124 -0
  83. data/lib/legion/runner.rb +55 -0
  84. data/lib/legion/runner/log.rb +10 -0
  85. data/lib/legion/runner/status.rb +69 -0
  86. data/lib/legion/service.rb +130 -0
  87. data/lib/legion/supervision.rb +15 -0
  88. data/lib/legion/version.rb +3 -0
  89. metadata +244 -39
@@ -0,0 +1,36 @@
1
+ module Legion
2
+ module Extensions
3
+ module Builder
4
+ module Base
5
+ def find_files(name, path = extension_path)
6
+ files = []
7
+ return files unless Dir.exist? "#{path}/#{name}"
8
+
9
+ Dir["#{path}/#{name}/*.rb"].each do |file|
10
+ files.push(file)
11
+ end
12
+ files
13
+ end
14
+
15
+ def require_files(files)
16
+ files.each { |file| require file }
17
+ end
18
+
19
+ def const_defined_two?(item, root = Kernel)
20
+ root.const_defined?(item.to_s)
21
+ end
22
+
23
+ def define_constant_two(item, root: Kernel, type: Module)
24
+ return true if root.const_defined?(item)
25
+
26
+ root.const_set(item.to_s, type.new)
27
+ end
28
+
29
+ def define_get(item, root: Kernel, type: Module)
30
+ define_constant_two(item, root: root, type: type) if const_defined_two?(item, root: root)
31
+ root.const_get(item)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'base'
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Builder
6
+ module Helpers
7
+ include Legion::Extensions::Builder::Base
8
+
9
+ def build_helpers
10
+ @helpers ||= []
11
+ @helpers.push(require_files(helper_files))
12
+ end
13
+
14
+ def helper_files
15
+ @helper_files ||= find_files('helpers')
16
+ end
17
+
18
+ def helpers
19
+ @helpers
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,58 @@
1
+ require_relative 'base'
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Builder
6
+ module Runners
7
+ include Legion::Extensions::Builder::Base
8
+
9
+ attr_reader :runners
10
+
11
+ def build_runners
12
+ @runners = {}
13
+ lex_class.const_set('Runners', Module.new) unless lex_class.const_defined?('Runners')
14
+ require_files(runner_files)
15
+ build_runner_list
16
+ end
17
+
18
+ def build_runner_list
19
+ runner_files.each do |file|
20
+ runner_name = file.split('/').last.sub('.rb', '')
21
+ runner_class = "#{lex_class}::Runners::#{runner_name.split('_').collect(&:capitalize).join}"
22
+ loaded_runner = Kernel.const_get(runner_class)
23
+
24
+ @runners[runner_name.to_sym] = {
25
+ extension: lex_class.to_s.downcase,
26
+ extension_name: extension_name,
27
+ extension_class: lex_class,
28
+ runner_name: runner_name,
29
+ runner_class: runner_class,
30
+ runner_path: file,
31
+ class_methods: {}
32
+ }
33
+
34
+ if settings.key?(:runners) && settings[:runners].key?(runner_name.to_sym)
35
+ @runners[runner_name.to_sym][:desc] = settings[:runners][runner_name.to_sym][:desc]
36
+ end
37
+
38
+ loaded_runner.public_instance_methods(false).each do |runner_method|
39
+ @runners[runner_name.to_sym][:class_methods][runner_method] = {
40
+ args: loaded_runner.instance_method(runner_method).parameters
41
+ }
42
+ end
43
+
44
+ loaded_runner.methods(false).each do |runner_method|
45
+ @runners[runner_name.to_sym][:class_methods][runner_method] = {
46
+ args: loaded_runner.method(runner_method).parameters
47
+ }
48
+ end
49
+ end
50
+ end
51
+
52
+ def runner_files
53
+ @runner_files ||= find_files('runners')
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,131 @@
1
+ require_relative 'builders/actors'
2
+ require_relative 'builders/helpers'
3
+ require_relative 'builders/runners'
4
+
5
+ require_relative 'helpers/core'
6
+ require_relative 'helpers/task'
7
+ require_relative 'helpers/logger'
8
+ require_relative 'helpers/lex'
9
+ require_relative 'helpers/transport'
10
+ require_relative 'helpers/data'
11
+ require_relative 'helpers/cache'
12
+
13
+ require_relative 'actors/base'
14
+ require_relative 'actors/every'
15
+ require_relative 'actors/loop'
16
+ require_relative 'actors/once'
17
+ require_relative 'actors/poll'
18
+ require_relative 'actors/subscription'
19
+ require_relative 'actors/nothing'
20
+
21
+ module Legion
22
+ module Extensions
23
+ module Core
24
+ include Legion::Extensions::Helpers::Transport
25
+ include Legion::Extensions::Helpers::Lex
26
+
27
+ include Legion::Extensions::Builder::Runners
28
+ include Legion::Extensions::Builder::Helpers
29
+ include Legion::Extensions::Builder::Actors
30
+
31
+ def autobuild
32
+ @actors = {}
33
+ @meta_actors = {}
34
+ @runners = {}
35
+ @helpers = []
36
+
37
+ @queues = {}
38
+ @exchanges = {}
39
+ @messages = {}
40
+ build_settings
41
+ build_transport
42
+ build_data if Legion::Settings[:data][:connected] && data_required?
43
+ build_helpers
44
+ build_runners
45
+ build_actors
46
+ end
47
+
48
+ def data_required?
49
+ false
50
+ end
51
+
52
+ def transport_required?
53
+ true
54
+ end
55
+
56
+ def cache_required?
57
+ false
58
+ end
59
+
60
+ def crypt_required?
61
+ false
62
+ end
63
+
64
+ def vault_required?
65
+ false
66
+ end
67
+
68
+ def build_data
69
+ auto_generate_data
70
+ lex_class::Data.build
71
+ end
72
+
73
+ def build_transport
74
+ if File.exist? "#{extension_path}/transport/autobuild.rb"
75
+ require "#{extension_path}/transport/autobuild"
76
+ extension_class::Transport::AutoBuild.build
77
+ log.warn 'still using transport::autobuild, please upgrade'
78
+ elsif File.exist? "#{extension_path}/transport.rb"
79
+ require "#{extension_path}/transport"
80
+ extension_class::Transport.build
81
+ else
82
+ auto_generate_transport
83
+ extension_class::Transport.build
84
+ end
85
+ end
86
+
87
+ def build_settings # rubocop:disable Metrics/AbcSize
88
+ if Legion::Settings[:extensions].key?(lex_name.to_sym)
89
+ Legion::Settings[:default_extension_settings].each do |key, value|
90
+ Legion::Settings[:extensions][lex_name.to_sym][key.to_sym] = if Legion::Settings[:extensions][lex_name.to_sym].key?(key.to_sym)
91
+ value.merge(Legion::Settings[:extensions][lex_name.to_sym][key.to_sym])
92
+ else
93
+ value
94
+ end
95
+ end
96
+ else
97
+ Legion::Settings[:extensions][lex_name.to_sym] = Legion::Settings[:default_extension_settings]
98
+ end
99
+
100
+ default_settings.each do |key, value|
101
+ Legion::Settings[:extensions][lex_name.to_sym][key.to_sym] = if Legion::Settings[:extensions][lex_name.to_sym].key?(key.to_sym)
102
+ value.merge(Legion::Settings[:extensions][lex_name.to_sym][key.to_sym])
103
+ else
104
+ value
105
+ end
106
+ end
107
+ end
108
+
109
+ def default_settings
110
+ {}
111
+ end
112
+
113
+ def auto_generate_transport
114
+ require 'legion/extensions/transport'
115
+ log.debug 'running meta magic to generate a transport base class'
116
+ return if Kernel.const_defined? "#{lex_class}::Transport"
117
+
118
+ Kernel.const_get(lex_class.to_s).const_set('Transport', Module.new { extend Legion::Extensions::Transport })
119
+ end
120
+
121
+ def auto_generate_data
122
+ require 'legion/extensions/data'
123
+ log.debug 'running meta magic to generate a data base class'
124
+ Kernel.const_get(lex_class.to_s).const_set('Data', Module.new { extend Legion::Extensions::Data })
125
+ rescue StandardError => e
126
+ log.error e.message
127
+ log.error e.backtrace
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,58 @@
1
+ require 'legion/extensions/data/migrator'
2
+ require 'legion/extensions/data/model'
3
+
4
+ module Legion
5
+ module Extensions
6
+ module Data
7
+ include Legion::Extensions::Helpers::Data
8
+ include Legion::Extensions::Helpers::Logger
9
+
10
+ def build
11
+ @models = []
12
+ @migrations = []
13
+ if Dir[File.expand_path("#{data_path}/migrations/*.rb")].count.positive?
14
+ log.debug('Has migrations, checking status')
15
+ run
16
+ end
17
+
18
+ models = Dir[File.expand_path("#{data_path}/models/*.rb")]
19
+ if models.count.positive?
20
+ log.debug('Including LEX models')
21
+ models.each do |file|
22
+ require file
23
+ end
24
+
25
+ models_class.constants.select do |model|
26
+ models_class.const_get(model).extend Legion::Extensions::Data::Model
27
+ end
28
+ end
29
+
30
+ true
31
+ end
32
+
33
+ def extension_model
34
+ Legion::Data::Model::Extension[namespace: lex_class.to_s]
35
+ end
36
+
37
+ def schema_version
38
+ extension_model.values[:schema_version]
39
+ end
40
+
41
+ def migrations_path
42
+ "#{data_path}/migrations/"
43
+ end
44
+
45
+ def migrate_class
46
+ @migrate_class ||= Legion::Extensions::Data::Migrator.new(migrations_path, lex_class.to_s)
47
+ end
48
+
49
+ def run
50
+ return true if migrate_class.is_current?
51
+
52
+ log.debug('Running LEX schema migrator')
53
+ results = migrate_class.run
54
+ extension_model.update(schema_version: results)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,28 @@
1
+ require 'sequel/extensions/migration'
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Data
6
+ class Migrator < Sequel::IntegerMigrator
7
+ def initialize(path, extension, **)
8
+ @path = path
9
+ @extension = extension
10
+ super(Legion::Data::Connection.sequel, path)
11
+ end
12
+
13
+ def default_schema_column
14
+ :schema_version
15
+ end
16
+
17
+ def default_schema_table
18
+ :extensions
19
+ end
20
+
21
+ def schema_dataset
22
+ Legion::Data::Connection.sequel.from(default_schema_table).where(namespace: @extension)
23
+ end
24
+ alias ds schema_dataset
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,8 @@
1
+ module Legion
2
+ module Extensions
3
+ module Data
4
+ module Model
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,82 @@
1
+ module Legion
2
+ module Extensions
3
+ module Helpers
4
+ module Base
5
+ def lex_class
6
+ @lex_class ||= Kernel.const_get(calling_class_array[0..2].join('::'))
7
+ end
8
+ alias extension_class lex_class
9
+
10
+ def lex_name
11
+ @lex_name ||= calling_class_array[2].gsub(/(?<!^)[A-Z]/) { "_#{Regexp.last_match(0)}" }.downcase
12
+ end
13
+ alias extension_name lex_name
14
+ alias lex_filename lex_name
15
+
16
+ def lex_const
17
+ @lex_const ||= calling_class_array[2]
18
+ end
19
+
20
+ def calling_class
21
+ @calling_class ||= respond_to?(:ancestors) ? ancestors.first : self.class
22
+ end
23
+
24
+ def calling_class_array
25
+ @calling_class_array ||= calling_class.to_s.split('::')
26
+ end
27
+
28
+ def actor_class
29
+ calling_class
30
+ end
31
+
32
+ def actor_name
33
+ @actor_name ||= calling_class_array.last.gsub(/(?<!^)[A-Z]/) { "_#{Regexp.last_match(0)}" }.downcase
34
+ end
35
+
36
+ def actor_const
37
+ @actor_const ||= calling_class_array.last
38
+ end
39
+
40
+ def runner_class
41
+ @runner_class ||= Kernel.const_get(actor_class.to_s.sub!('Actor', 'Runners'))
42
+ end
43
+
44
+ def runner_name
45
+ @runner_name ||= runner_class.to_s.split('::').last.gsub(/(?<!^)[A-Z]/) { "_#{Regexp.last_match(0)}" }.downcase
46
+ end
47
+
48
+ def runner_const
49
+ @runner_const ||= runner_class.to_s.split('::').last
50
+ end
51
+
52
+ def full_path
53
+ @full_path ||= "#{Gem::Specification.find_by_name("lex-#{lex_name}").gem_dir}/lib/legion/extensions/#{lex_filename}"
54
+ end
55
+ alias extension_path full_path
56
+
57
+ def from_json(string)
58
+ Legion::JSON.load(string)
59
+ end
60
+
61
+ def normalize(thing)
62
+ if thing.is_a? String
63
+ to_json(from_json(thing))
64
+ else
65
+ from_json(to_json(thing))
66
+ end
67
+ end
68
+
69
+ def to_dotted_hash(hash, recursive_key = '')
70
+ hash.each_with_object({}) do |(k, v), ret|
71
+ key = recursive_key + k.to_s
72
+ if v.is_a? Hash
73
+ ret.merge! to_dotted_hash(v, "#{key}.")
74
+ else
75
+ ret[key.to_sym] = v
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,23 @@
1
+ require 'legion/extensions/helpers/base'
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Helpers
6
+ module Cache
7
+ include Legion::Extensions::Helpers::Base
8
+
9
+ def cache_namespace
10
+ @cache_namespace ||= lex_name
11
+ end
12
+
13
+ def cache_set(key, value, ttl: 60, **)
14
+ Legion::Cache.set(cache_namespace + key, value, ttl: ttl)
15
+ end
16
+
17
+ def cache_get(key)
18
+ Legion::Cache.get(cache_namespace + key)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end