decouplio 1.0.0alpha

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 (136) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +53 -0
  3. data/.dockerignore +12 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +106 -0
  7. data/.rubocop_todo.yml +147 -0
  8. data/.ruby-version +1 -0
  9. data/.vscode/settings.json +3 -0
  10. data/Dockerfile +12 -0
  11. data/Gemfile +8 -0
  12. data/LICENSE +21 -0
  13. data/LICENSE.txt +21 -0
  14. data/README.md +29 -0
  15. data/Rakefile +8 -0
  16. data/benchmarks/.ruby-version +1 -0
  17. data/benchmarks/Dockerfile +12 -0
  18. data/benchmarks/Gemfile +11 -0
  19. data/benchmarks/benchmarks.rb +527 -0
  20. data/bin/console +15 -0
  21. data/bin/setup +8 -0
  22. data/decouplio.gemspec +40 -0
  23. data/docker-compose.yml +18 -0
  24. data/docs/_config.yml +1 -0
  25. data/docs/benchmarks.md +1 -0
  26. data/docs/context.md +74 -0
  27. data/docs/context.rb +62 -0
  28. data/docs/doby.md +80 -0
  29. data/docs/doby.rb +38 -0
  30. data/docs/error_store.md +347 -0
  31. data/docs/error_store.rb +202 -0
  32. data/docs/fail.md +1016 -0
  33. data/docs/fail.rb +762 -0
  34. data/docs/index.md +25 -0
  35. data/docs/inner_action.md +63 -0
  36. data/docs/inner_action.rb +43 -0
  37. data/docs/logic_block.md +25 -0
  38. data/docs/octo.md +269 -0
  39. data/docs/octo.rb +164 -0
  40. data/docs/pass.md +309 -0
  41. data/docs/pass.rb +213 -0
  42. data/docs/quick_start.md +71 -0
  43. data/docs/quick_start.rb +38 -0
  44. data/docs/resq.md +263 -0
  45. data/docs/resq.rb +176 -0
  46. data/docs/step.md +737 -0
  47. data/docs/step.rb +526 -0
  48. data/docs/step_as_a_service.md +109 -0
  49. data/docs/step_as_a_service.rb +77 -0
  50. data/docs/wrap.md +232 -0
  51. data/docs/wrap.rb +137 -0
  52. data/lib/decouplio/action.rb +111 -0
  53. data/lib/decouplio/composer.rb +599 -0
  54. data/lib/decouplio/const/colors.rb +25 -0
  55. data/lib/decouplio/const/reserved_methods.rb +18 -0
  56. data/lib/decouplio/const/results.rb +13 -0
  57. data/lib/decouplio/const/types.rb +173 -0
  58. data/lib/decouplio/const/validations/action_option_class.rb +17 -0
  59. data/lib/decouplio/const/validations/common.rb +14 -0
  60. data/lib/decouplio/const/validations/fail.rb +34 -0
  61. data/lib/decouplio/const/validations/logic.rb +15 -0
  62. data/lib/decouplio/const/validations/octo.rb +44 -0
  63. data/lib/decouplio/const/validations/palp.rb +20 -0
  64. data/lib/decouplio/const/validations/pass.rb +32 -0
  65. data/lib/decouplio/const/validations/resq.rb +67 -0
  66. data/lib/decouplio/const/validations/step.rb +35 -0
  67. data/lib/decouplio/const/validations/wrap.rb +41 -0
  68. data/lib/decouplio/default_error_handler.rb +24 -0
  69. data/lib/decouplio/errors/action_class_error.rb +26 -0
  70. data/lib/decouplio/errors/base_error.rb +30 -0
  71. data/lib/decouplio/errors/error_store_error.rb +17 -0
  72. data/lib/decouplio/errors/extra_key_for_fail_error.rb +26 -0
  73. data/lib/decouplio/errors/extra_key_for_octo_error.rb +26 -0
  74. data/lib/decouplio/errors/extra_key_for_pass_error.rb +26 -0
  75. data/lib/decouplio/errors/extra_key_for_resq_error.rb +29 -0
  76. data/lib/decouplio/errors/extra_key_for_step_error.rb +23 -0
  77. data/lib/decouplio/errors/extra_key_for_wrap_error.rb +23 -0
  78. data/lib/decouplio/errors/fail_controversial_keys_error.rb +26 -0
  79. data/lib/decouplio/errors/fail_finish_him_error.rb +26 -0
  80. data/lib/decouplio/errors/fail_is_first_step_error.rb +18 -0
  81. data/lib/decouplio/errors/invalid_error_class_error.rb +29 -0
  82. data/lib/decouplio/errors/invalid_wrap_name_error.rb +23 -0
  83. data/lib/decouplio/errors/logic_is_not_defined_error.rb +23 -0
  84. data/lib/decouplio/errors/logic_redefinition_error.rb +23 -0
  85. data/lib/decouplio/errors/octo_block_is_not_defined_error.rb +18 -0
  86. data/lib/decouplio/errors/octo_controversial_keys_error.rb +26 -0
  87. data/lib/decouplio/errors/options_validation_error.rb +7 -0
  88. data/lib/decouplio/errors/palp_block_is_not_defined_error.rb +18 -0
  89. data/lib/decouplio/errors/palp_is_not_defined_error.rb +26 -0
  90. data/lib/decouplio/errors/palp_validation_error.rb +21 -0
  91. data/lib/decouplio/errors/pass_controversial_keys_error.rb +26 -0
  92. data/lib/decouplio/errors/pass_finish_him_error.rb +26 -0
  93. data/lib/decouplio/errors/required_options_is_missing_for_octo_error.rb +25 -0
  94. data/lib/decouplio/errors/resq_definition_error.rb +21 -0
  95. data/lib/decouplio/errors/resq_error_class_error.rb +29 -0
  96. data/lib/decouplio/errors/resq_handler_method_error.rb +26 -0
  97. data/lib/decouplio/errors/step_controversial_keys_error.rb +26 -0
  98. data/lib/decouplio/errors/step_finish_him_error.rb +26 -0
  99. data/lib/decouplio/errors/step_is_not_defined_for_fail_error.rb +26 -0
  100. data/lib/decouplio/errors/step_is_not_defined_for_step_error.rb +27 -0
  101. data/lib/decouplio/errors/step_is_not_defined_for_wrap_error.rb +26 -0
  102. data/lib/decouplio/errors/step_name_error.rb +20 -0
  103. data/lib/decouplio/errors/wrap_block_is_not_defined_error.rb +18 -0
  104. data/lib/decouplio/errors/wrap_controversial_keys_error.rb +26 -0
  105. data/lib/decouplio/errors/wrap_finish_him_error.rb +26 -0
  106. data/lib/decouplio/errors/wrap_klass_method_error.rb +23 -0
  107. data/lib/decouplio/flow.rb +17 -0
  108. data/lib/decouplio/logic_dsl.rb +96 -0
  109. data/lib/decouplio/octo_hash_case.rb +31 -0
  110. data/lib/decouplio/octo_options_validator.rb +89 -0
  111. data/lib/decouplio/options_validator.rb +566 -0
  112. data/lib/decouplio/processor.rb +20 -0
  113. data/lib/decouplio/steps/base_resq.rb +31 -0
  114. data/lib/decouplio/steps/base_step.rb +16 -0
  115. data/lib/decouplio/steps/doby.rb +32 -0
  116. data/lib/decouplio/steps/fail.rb +50 -0
  117. data/lib/decouplio/steps/if_condition_fail.rb +28 -0
  118. data/lib/decouplio/steps/if_condition_pass.rb +26 -0
  119. data/lib/decouplio/steps/inner_action_fail.rb +55 -0
  120. data/lib/decouplio/steps/inner_action_pass.rb +38 -0
  121. data/lib/decouplio/steps/inner_action_step.rb +51 -0
  122. data/lib/decouplio/steps/octo.rb +22 -0
  123. data/lib/decouplio/steps/pass.rb +35 -0
  124. data/lib/decouplio/steps/resq_fail.rb +10 -0
  125. data/lib/decouplio/steps/resq_pass.rb +10 -0
  126. data/lib/decouplio/steps/service_fail.rb +51 -0
  127. data/lib/decouplio/steps/service_pass.rb +36 -0
  128. data/lib/decouplio/steps/service_step.rb +47 -0
  129. data/lib/decouplio/steps/step.rb +43 -0
  130. data/lib/decouplio/steps/unless_condition_fail.rb +28 -0
  131. data/lib/decouplio/steps/unless_condition_pass.rb +26 -0
  132. data/lib/decouplio/steps/wrap.rb +62 -0
  133. data/lib/decouplio/validators/condition.rb +49 -0
  134. data/lib/decouplio/version.rb +5 -0
  135. data/lib/decouplio.rb +7 -0
  136. metadata +266 -0
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_error'
4
+ require_relative '../const/validations/common'
5
+
6
+ module Decouplio
7
+ module Errors
8
+ class StepNameError < Decouplio::Errors::BaseError
9
+ def template
10
+ Decouplio::Const::Validations::Common::STEP_NAME
11
+ end
12
+
13
+ def interpolation_values
14
+ [
15
+ @errored_option
16
+ ]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_error'
4
+ require_relative '../const/validations/wrap'
5
+
6
+ module Decouplio
7
+ module Errors
8
+ class WrapBlockIsNotDefinedError < Decouplio::Errors::BaseError
9
+ def template
10
+ Decouplio::Const::Validations::Wrap::NOT_DEFINED
11
+ end
12
+
13
+ def interpolation_values
14
+ []
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_error'
4
+ require_relative '../const/validations/wrap'
5
+
6
+ module Decouplio
7
+ module Errors
8
+ class WrapControversialKeysError < Decouplio::Errors::BaseError
9
+ def template
10
+ Decouplio::Const::Validations::Wrap::VALIDATION_ERROR_MESSAGE
11
+ end
12
+
13
+ def interpolation_values
14
+ [
15
+ @errored_option,
16
+ format(
17
+ Decouplio::Const::Validations::Wrap::CONTROVERSIAL_KEYS,
18
+ *@details
19
+ ),
20
+ Decouplio::Const::Validations::Wrap::ALLOWED_OPTIONS_MESSAGE,
21
+ Decouplio::Const::Validations::Wrap::MANUAL_URL
22
+ ]
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_error'
4
+ require_relative '../const/validations/wrap'
5
+
6
+ module Decouplio
7
+ module Errors
8
+ class WrapFinishHimError < Decouplio::Errors::BaseError
9
+ def template
10
+ Decouplio::Const::Validations::Wrap::VALIDATION_ERROR_MESSAGE
11
+ end
12
+
13
+ def interpolation_values
14
+ [
15
+ @errored_option,
16
+ format(
17
+ Decouplio::Const::Validations::Common::WRONG_FINISH_HIM_VALUE,
18
+ @details
19
+ ),
20
+ Decouplio::Const::Validations::Wrap::ALLOWED_OPTIONS_MESSAGE,
21
+ Decouplio::Const::Validations::Wrap::MANUAL_URL
22
+ ]
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_error'
4
+ require_relative '../const/validations/wrap'
5
+
6
+ module Decouplio
7
+ module Errors
8
+ class WrapKlassMethodError < Decouplio::Errors::BaseError
9
+ def template
10
+ Decouplio::Const::Validations::Wrap::VALIDATION_ERROR_MESSAGE
11
+ end
12
+
13
+ def interpolation_values
14
+ [
15
+ @errored_option,
16
+ Decouplio::Const::Validations::Wrap::KLASS_AND_METHOD_PRESENCE,
17
+ Decouplio::Const::Validations::Wrap::ALLOWED_OPTIONS_MESSAGE,
18
+ Decouplio::Const::Validations::Wrap::MANUAL_URL
19
+ ]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'logic_dsl'
4
+ require_relative 'composer'
5
+
6
+ module Decouplio
7
+ class Flow
8
+ def self.call(logic:, action_class:)
9
+ logic_container_raw_data = Class.new(Decouplio::LogicDsl, &logic)
10
+
11
+ Decouplio::Composer.compose(
12
+ logic_container_raw_data: logic_container_raw_data,
13
+ action_class: action_class
14
+ )
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'flow'
4
+ require_relative 'const/types'
5
+ require_relative 'octo_hash_case'
6
+ require_relative 'errors/options_validation_error'
7
+ require_relative 'errors/palp_validation_error'
8
+ require_relative 'errors/resq_definition_error'
9
+ require_relative 'errors/wrap_block_is_not_defined_error'
10
+ require_relative 'errors/palp_block_is_not_defined_error'
11
+ require_relative 'errors/fail_is_first_step_error'
12
+ require_relative 'errors/octo_block_is_not_defined_error'
13
+
14
+ module Decouplio
15
+ class LogicDsl
16
+ DEFAULT_WRAP_NAME = 'wrap'
17
+
18
+ class << self
19
+ attr_reader :steps, :palps
20
+
21
+ def inherited(subclass)
22
+ subclass.init_steps
23
+ end
24
+
25
+ def init_steps
26
+ @steps = []
27
+ @palps = {}
28
+ end
29
+
30
+ def step(stp, **options)
31
+ @steps << options.merge(type: Decouplio::Const::Types::STEP_TYPE, name: stp)
32
+ end
33
+
34
+ def fail(stp, **options)
35
+ raise Decouplio::Errors::FailCanNotBeTheFirstStepError if @steps.empty?
36
+
37
+ @steps << options.merge(type: Decouplio::Const::Types::FAIL_TYPE, name: stp)
38
+ end
39
+
40
+ def pass(stp, **options)
41
+ @steps << options.merge(type: Decouplio::Const::Types::PASS_TYPE, name: stp)
42
+ end
43
+
44
+ def octo(octo_name, **options, &block)
45
+ raise Decouplio::Errors::OctoBlockIsNotDefinedError unless block_given?
46
+
47
+ hash_case = Class.new(Decouplio::OctoHashCase, &block).hash_case
48
+
49
+ raise Decouplio::Errors::OctoBlockIsNotDefinedError if hash_case.empty?
50
+
51
+ options[:hash_case] = hash_case
52
+ @steps << options.merge(type: Decouplio::Const::Types::OCTO_TYPE, name: octo_name)
53
+ end
54
+
55
+ def palp(palp_name, **options, &block)
56
+ raise Decouplio::Errors::PalpBlockIsNotDefinedError unless block_given?
57
+
58
+ options.empty? || raise(Decouplio::Errors::PalpValidationError)
59
+
60
+ @palps[palp_name] = Class.new(self, &block)
61
+ end
62
+
63
+ def resq(name = :resq, **options)
64
+ unless Decouplio::Const::Types::MAIN_FLOW_TYPES.include?(@steps.last&.[](:type))
65
+ raise Decouplio::Errors::ResqDefinitionError
66
+ end
67
+
68
+ @steps << {
69
+ name: name,
70
+ type: Decouplio::Const::Types::RESQ_TYPE,
71
+ step_to_resq: @steps.delete(@steps.last),
72
+ handler_hash: options
73
+ }
74
+ end
75
+
76
+ def wrap(name = nil, **options, &block)
77
+ raise Decouplio::Errors::WrapBlockIsNotDefinedError unless block_given?
78
+
79
+ @steps << options.merge(
80
+ type: Decouplio::Const::Types::WRAP_TYPE,
81
+ name: name,
82
+ wrap_flow: block
83
+ )
84
+ end
85
+
86
+ def doby(doby_class, **options)
87
+ @steps << {
88
+ type: Decouplio::Const::Types::DOBY_TYPE,
89
+ name: doby_class.name.to_sym,
90
+ doby_class: doby_class,
91
+ doby_options: options
92
+ }
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'octo_options_validator'
4
+
5
+ module Decouplio
6
+ class OctoHashCase
7
+ class << self
8
+ attr_reader :hash_case
9
+
10
+ def inherited(subclass)
11
+ subclass.init_hash_case
12
+ super(subclass)
13
+ end
14
+
15
+ def init_hash_case
16
+ @hash_case = {}
17
+ end
18
+
19
+ def on(strategy_flow, **options)
20
+ validate_options(options)
21
+ @hash_case[strategy_flow] = options
22
+ end
23
+
24
+ private
25
+
26
+ def validate_options(options)
27
+ OctoOptionsValidator.call(options: options)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors/options_validation_error'
4
+
5
+ module Decouplio
6
+ class OctoOptionsValidator
7
+ def self.call(options:)
8
+ new(options: options).call
9
+ end
10
+
11
+ def initialize(options:)
12
+ @options = options
13
+ end
14
+
15
+ def call
16
+ validate_option_keys
17
+ validate_option_count
18
+ end
19
+
20
+ private
21
+
22
+ def validate_option_keys
23
+ extra_options = (@options.keys - ON_ALLOWED_OPTIONS)
24
+ return if extra_options.size.zero?
25
+
26
+ raise_validation_error(
27
+ compose_message(
28
+ STRATEGY_ON_ERROR_MESSAGE,
29
+ YELLOW,
30
+ extra_options,
31
+ EXTRA_OPTIONS_NOT_ALLOWED % extra_options,
32
+ ON_ALLOWED_OPTIONS,
33
+ STRATEGY_MANUAL_URL,
34
+ NO_COLOR
35
+ )
36
+ )
37
+ end
38
+
39
+ def validate_option_count
40
+ return if @options.keys.size == 1
41
+
42
+ raise_validation_error(
43
+ compose_message(
44
+ STRATEGY_ON_ERROR_MESSAGE,
45
+ YELLOW,
46
+ @options,
47
+ ONLY_ONE_OPTION_PER_TIME_IS_ALLOWED,
48
+ ON_ALLOWED_OPTIONS,
49
+ STRATEGY_MANUAL_URL,
50
+ NO_COLOR
51
+ )
52
+ )
53
+ end
54
+
55
+ def raise_validation_error(message)
56
+ raise Decouplio::Errors::OptionsValidationError, message
57
+ end
58
+
59
+ def compose_message(message, *interpolation_params)
60
+ message % interpolation_params
61
+ end
62
+
63
+ ALLOWED_OPTIONS = %i[palp step].freeze
64
+ YELLOW = "\033[1;33m"
65
+ NO_COLOR = "\033[0m"
66
+ STRATEGY_ON_ERROR_MESSAGE = <<~ERROR_MESSAGE
67
+ %s
68
+ Next options are not allowed for "on":
69
+ %s
70
+
71
+ Details:
72
+ %s
73
+
74
+ Allowed options are:
75
+ %s
76
+
77
+ Please read the manual about allowed options here:
78
+ %s
79
+ %s
80
+ ERROR_MESSAGE
81
+ EXTRA_OPTIONS_NOT_ALLOWED = '%s is not allowed for "on"'
82
+ ONLY_ONE_OPTION_PER_TIME_IS_ALLOWED = 'Only one option is allowed for "on".'
83
+ ON_ALLOWED_OPTIONS = %i[
84
+ step
85
+ palp
86
+ ].freeze
87
+ STRATEGY_MANUAL_URL = 'https://stub.strategy.manual.url'
88
+ end
89
+ end