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,599 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'action'
4
+ require_relative 'const/types'
5
+ require_relative 'const/results'
6
+ require_relative 'steps/step'
7
+ require_relative 'steps/fail'
8
+ require_relative 'steps/pass'
9
+ require_relative 'steps/wrap'
10
+ require_relative 'steps/octo'
11
+ require_relative 'steps/resq_pass'
12
+ require_relative 'steps/resq_fail'
13
+ require_relative 'steps/if_condition_pass'
14
+ require_relative 'steps/if_condition_fail'
15
+ require_relative 'steps/unless_condition_pass'
16
+ require_relative 'steps/unless_condition_fail'
17
+ require_relative 'steps/inner_action_step'
18
+ require_relative 'steps/inner_action_fail'
19
+ require_relative 'steps/inner_action_pass'
20
+ require_relative 'steps/service_step'
21
+ require_relative 'steps/service_fail'
22
+ require_relative 'steps/service_pass'
23
+ require_relative 'steps/doby'
24
+ require_relative 'options_validator'
25
+ require_relative 'validators/condition'
26
+
27
+ module Decouplio
28
+ class Composer
29
+ class << self
30
+ def compose(logic_container_raw_data:, action_class:, palp_prefix: :root, parent_flow: {}, next_steps: nil)
31
+ flow = logic_container_raw_data.steps
32
+ palps = logic_container_raw_data.palps
33
+
34
+ steps_pool = {}
35
+ steps_flow = {}
36
+
37
+ flow = prepare_raw_data(flow, palp_prefix, action_class)
38
+ validate_flow(flow, palps, next_steps, action_class)
39
+ flow = compose_flow(flow, palps, next_steps, action_class, parent_flow)
40
+
41
+ flow.each do |step_id, stp|
42
+ steps_flow[step_id] = stp[:flow]
43
+ steps_flow.merge!(extract_palp_flow(stp))
44
+ steps_pool[step_id] = create_step_instance(stp, flow)
45
+ steps_pool.merge!(extract_palp_pool(stp))
46
+ end
47
+
48
+ {
49
+ first_step: steps_pool.keys.first,
50
+ steps_pool: steps_pool.freeze,
51
+ steps_flow: steps_flow.freeze
52
+ }
53
+ end
54
+
55
+ private
56
+
57
+ def prepare_raw_data(flow, palp_prefix, action_class)
58
+ flow = flow.map do |stp|
59
+ stp[:step_id] = random_id(name: stp[:name], palp_prefix: palp_prefix, flow: flow)
60
+ stp[:flow] = {}
61
+ stp = compose_resq(stp, palp_prefix, flow)
62
+ stp = compose_action(stp)
63
+ stp = compose_wrap(stp, action_class)
64
+ condition = compose_condition(stp, palp_prefix, flow)
65
+
66
+ [condition, stp].compact
67
+ end.flatten
68
+
69
+ flow.to_h do |stp|
70
+ [stp[:step_id], stp]
71
+ end
72
+ end
73
+
74
+ def validate_flow(flow, palps, next_steps, action_class)
75
+ OptionsValidator.new(
76
+ flow: flow,
77
+ palps: palps,
78
+ next_steps: next_steps,
79
+ action_class: action_class
80
+ ).call
81
+ end
82
+
83
+ def extract_palp_flow(stp)
84
+ return {} unless stp[:type] == Decouplio::Const::Types::OCTO_TYPE
85
+
86
+ stp[:hash_case].values.map { |composer_output| composer_output[:steps_flow] }.reduce({}, :merge)
87
+ end
88
+
89
+ def extract_palp_pool(stp)
90
+ return {} unless stp[:type] == Decouplio::Const::Types::OCTO_TYPE
91
+
92
+ stp[:hash_case].values.map { |composer_output| composer_output[:steps_pool] }.reduce({}, :merge)
93
+ end
94
+
95
+ def create_step_instance(stp, flow)
96
+ case stp[:type]
97
+ when Decouplio::Const::Types::STEP_TYPE
98
+ create_step(stp, flow)
99
+ when Decouplio::Const::Types::FAIL_TYPE
100
+ create_fail(stp, flow)
101
+ when Decouplio::Const::Types::PASS_TYPE
102
+ create_pass(stp, flow)
103
+ when Decouplio::Const::Types::IF_TYPE_PASS
104
+ create_if_condition_pass(stp)
105
+ when Decouplio::Const::Types::IF_TYPE_FAIL
106
+ create_if_condition_fail(stp)
107
+ when Decouplio::Const::Types::UNLESS_TYPE_PASS
108
+ create_unless_condition_pass(stp)
109
+ when Decouplio::Const::Types::UNLESS_TYPE_FAIL
110
+ create_unless_condition_fail(stp)
111
+ when Decouplio::Const::Types::OCTO_TYPE
112
+ create_octo(stp)
113
+ when Decouplio::Const::Types::WRAP_TYPE
114
+ create_wrap(flow, stp)
115
+ when Decouplio::Const::Types::RESQ_TYPE_STEP, Decouplio::Const::Types::RESQ_TYPE_PASS
116
+ create_resq_pass(stp, flow)
117
+ when Decouplio::Const::Types::RESQ_TYPE_FAIL
118
+ create_resq_fail(stp, flow)
119
+ when Decouplio::Const::Types::ACTION_TYPE_STEP
120
+ create_inner_action_step(stp, flow)
121
+ when Decouplio::Const::Types::ACTION_TYPE_FAIL
122
+ create_inner_action_fail(stp, flow)
123
+ when Decouplio::Const::Types::ACTION_TYPE_PASS
124
+ create_inner_action_pass(stp, flow)
125
+ when Decouplio::Const::Types::SERVICE_TYPE_STEP
126
+ create_inner_service_step(stp, flow)
127
+ when Decouplio::Const::Types::SERVICE_TYPE_FAIL
128
+ create_inner_service_fail(stp, flow)
129
+ when Decouplio::Const::Types::SERVICE_TYPE_PASS
130
+ create_inner_service_pass(stp, flow)
131
+ when Decouplio::Const::Types::DOBY_TYPE
132
+ create_doby(stp)
133
+ end
134
+ end
135
+
136
+ def create_step(stp, flow)
137
+ Decouplio::Steps::Step.new(
138
+ name: stp[:name],
139
+ on_success_type: success_type(flow, stp),
140
+ on_failure_type: failure_type(flow, stp)
141
+ )
142
+ end
143
+
144
+ def create_fail(stp, flow)
145
+ Decouplio::Steps::Fail.new(
146
+ name: stp[:name],
147
+ on_success_type: success_type(flow, stp),
148
+ on_failure_type: failure_type(flow, stp)
149
+ )
150
+ end
151
+
152
+ def create_pass(stp, flow)
153
+ Decouplio::Steps::Pass.new(
154
+ name: stp[:name],
155
+ on_success_type: success_type(flow, stp)
156
+ )
157
+ end
158
+
159
+ def create_if_condition_pass(stp)
160
+ Decouplio::Steps::IfConditionPass.new(
161
+ name: stp[:name]
162
+ )
163
+ end
164
+
165
+ def create_if_condition_fail(stp)
166
+ Decouplio::Steps::IfConditionFail.new(
167
+ name: stp[:name]
168
+ )
169
+ end
170
+
171
+ def create_unless_condition_pass(stp)
172
+ Decouplio::Steps::UnlessConditionPass.new(
173
+ name: stp[:name]
174
+ )
175
+ end
176
+
177
+ def create_unless_condition_fail(stp)
178
+ Decouplio::Steps::UnlessConditionFail.new(
179
+ name: stp[:name]
180
+ )
181
+ end
182
+
183
+ def create_octo(stp)
184
+ Decouplio::Steps::Octo.new(
185
+ name: stp[:name],
186
+ ctx_key: stp[:ctx_key]
187
+ )
188
+ end
189
+
190
+ def create_wrap(flow, stp)
191
+ Decouplio::Steps::Wrap.new(
192
+ name: stp[:name],
193
+ klass: stp[:klass],
194
+ method: stp[:method],
195
+ wrap_flow: stp[:wrap_flow],
196
+ on_success_type: success_type(flow, stp),
197
+ on_failure_type: failure_type(flow, stp)
198
+ )
199
+ end
200
+
201
+ def create_resq_pass(stp, flow)
202
+ Decouplio::Steps::ResqPass.new(
203
+ handler_hash: stp[:handler_hash],
204
+ step_to_resq: create_step_instance(stp[:step_to_resq], flow)
205
+ )
206
+ end
207
+
208
+ def create_resq_fail(stp, flow)
209
+ Decouplio::Steps::ResqFail.new(
210
+ handler_hash: stp[:handler_hash],
211
+ step_to_resq: create_step_instance(stp[:step_to_resq], flow)
212
+ )
213
+ end
214
+
215
+ def create_inner_action_step(stp, flow)
216
+ Decouplio::Steps::InnerActionStep.new(
217
+ name: stp[:name],
218
+ action: stp[:action],
219
+ on_success_type: success_type(flow, stp),
220
+ on_failure_type: failure_type(flow, stp)
221
+ )
222
+ end
223
+
224
+ def create_inner_action_fail(stp, flow)
225
+ Decouplio::Steps::InnerActionFail.new(
226
+ name: stp[:name],
227
+ action: stp[:action],
228
+ on_success_type: success_type(flow, stp),
229
+ on_failure_type: failure_type(flow, stp)
230
+ )
231
+ end
232
+
233
+ def create_inner_action_pass(stp, flow)
234
+ Decouplio::Steps::InnerActionPass.new(
235
+ name: stp[:name],
236
+ action: stp[:action],
237
+ on_success_type: success_type(flow, stp),
238
+ on_failure_type: failure_type(flow, stp)
239
+ )
240
+ end
241
+
242
+ def create_inner_service_step(stp, flow)
243
+ Decouplio::Steps::ServiceStep.new(
244
+ name: stp[:name],
245
+ service: stp[:service],
246
+ on_success_type: success_type(flow, stp),
247
+ on_failure_type: failure_type(flow, stp)
248
+ )
249
+ end
250
+
251
+ def create_inner_service_fail(stp, flow)
252
+ Decouplio::Steps::ServiceFail.new(
253
+ name: stp[:name],
254
+ service: stp[:service],
255
+ on_success_type: success_type(flow, stp),
256
+ on_failure_type: failure_type(flow, stp)
257
+ )
258
+ end
259
+
260
+ def create_inner_service_pass(stp, flow)
261
+ Decouplio::Steps::ServicePass.new(
262
+ name: stp[:name],
263
+ service: stp[:service],
264
+ on_success_type: success_type(flow, stp),
265
+ on_failure_type: failure_type(flow, stp)
266
+ )
267
+ end
268
+
269
+ def create_doby(stp)
270
+ Decouplio::Steps::Doby.new(
271
+ name: stp[:name],
272
+ doby_class: stp[:doby_class],
273
+ doby_options: stp[:doby_options]
274
+ )
275
+ end
276
+
277
+ def compose_flow(flow, palps, next_steps, action_class, flow_hash = {})
278
+ flow.each_with_index do |(step_id, stp), idx|
279
+ case stp[:type]
280
+ when Decouplio::Const::Types::STEP_TYPE,
281
+ Decouplio::Const::Types::PASS_TYPE,
282
+ Decouplio::Const::Types::WRAP_TYPE,
283
+ Decouplio::Const::Types::ACTION_TYPE_STEP,
284
+ Decouplio::Const::Types::ACTION_TYPE_PASS,
285
+ Decouplio::Const::Types::SERVICE_TYPE_STEP,
286
+ Decouplio::Const::Types::SERVICE_TYPE_PASS,
287
+ Decouplio::Const::Types::RESQ_TYPE_STEP,
288
+ Decouplio::Const::Types::RESQ_TYPE_PASS
289
+ compose_step_flow(stp, step_id, flow, idx, flow_hash, next_steps)
290
+ when Decouplio::Const::Types::FAIL_TYPE,
291
+ Decouplio::Const::Types::RESQ_TYPE_FAIL,
292
+ Decouplio::Const::Types::ACTION_TYPE_FAIL,
293
+ Decouplio::Const::Types::SERVICE_TYPE_FAIL
294
+ compose_fail_flow(stp, step_id, flow, idx, flow_hash, next_steps)
295
+ when Decouplio::Const::Types::DOBY_TYPE
296
+ compose_doby_flow(stp, step_id, flow, idx, flow_hash, next_steps)
297
+ when Decouplio::Const::Types::IF_TYPE_PASS, Decouplio::Const::Types::UNLESS_TYPE_PASS
298
+ compose_pass_condition_flow(stp, flow, idx, flow_hash)
299
+ when Decouplio::Const::Types::IF_TYPE_FAIL, Decouplio::Const::Types::UNLESS_TYPE_FAIL
300
+ compose_fail_condition_flow(stp, flow, idx, flow_hash)
301
+ when Decouplio::Const::Types::OCTO_TYPE
302
+ compose_octo_flow(stp, step_id, idx, flow, palps, flow_hash, action_class)
303
+ end
304
+ end
305
+ end
306
+
307
+ def compose_step_flow(stp, step_id, flow, idx, flow_hash, next_steps)
308
+ flow_values = flow.values + (next_steps&.values || [])
309
+ stp[:flow][Decouplio::Const::Results::PASS] = next_success_step(
310
+ flow_values,
311
+ idx,
312
+ flow[step_id][:on_success]
313
+ )
314
+ stp[:flow][Decouplio::Const::Results::FAIL] = next_failure_step(
315
+ flow_values,
316
+ idx,
317
+ flow[step_id][:on_failure]
318
+ )
319
+ stp[:flow][Decouplio::Const::Results::ERROR] = next_failure_step(
320
+ flow_values,
321
+ idx,
322
+ flow[step_id][:on_error]
323
+ )
324
+ stp[:flow][Decouplio::Const::Results::PASS] ||= flow_hash[Decouplio::Const::Results::PASS]
325
+ stp[:flow][Decouplio::Const::Results::FAIL] ||= flow_hash[Decouplio::Const::Results::FAIL]
326
+ stp[:flow][Decouplio::Const::Results::ERROR] ||= flow_hash[Decouplio::Const::Results::ERROR]
327
+ stp[:flow][Decouplio::Const::Results::FINISH_HIM] = Decouplio::Const::Results::NO_STEP
328
+ end
329
+
330
+ def compose_doby_flow(stp, _step_id, flow, idx, flow_hash, next_steps)
331
+ flow_values = flow.values + (next_steps&.values || [])
332
+ stp[:flow][Decouplio::Const::Results::PASS] = next_success_step(
333
+ flow_values,
334
+ idx,
335
+ nil
336
+ )
337
+ stp[:flow][Decouplio::Const::Results::FAIL] = next_failure_step(
338
+ flow_values,
339
+ idx,
340
+ nil
341
+ )
342
+ stp[:flow][Decouplio::Const::Results::ERROR] = next_failure_step(
343
+ flow_values,
344
+ idx,
345
+ nil
346
+ )
347
+ stp[:flow][Decouplio::Const::Results::PASS] ||= flow_hash[Decouplio::Const::Results::PASS]
348
+ stp[:flow][Decouplio::Const::Results::FAIL] ||= flow_hash[Decouplio::Const::Results::FAIL]
349
+ stp[:flow][Decouplio::Const::Results::ERROR] ||= flow_hash[Decouplio::Const::Results::ERROR]
350
+ stp[:flow][Decouplio::Const::Results::FINISH_HIM] = Decouplio::Const::Results::NO_STEP
351
+ end
352
+
353
+ def compose_fail_flow(stp, step_id, flow, idx, flow_hash, next_steps)
354
+ flow_values = flow.values + (next_steps&.values || [])
355
+ stp[:flow][Decouplio::Const::Results::PASS] = next_failure_step(
356
+ flow_values,
357
+ idx,
358
+ flow[step_id][:on_success]
359
+ )
360
+ stp[:flow][Decouplio::Const::Results::FAIL] = next_failure_step(
361
+ flow_values,
362
+ idx,
363
+ flow[step_id][:on_failure]
364
+ )
365
+ stp[:flow][Decouplio::Const::Results::ERROR] = next_failure_step(
366
+ flow_values,
367
+ idx,
368
+ flow[step_id][:on_error]
369
+ )
370
+ stp[:flow][Decouplio::Const::Results::PASS] ||= flow_hash[Decouplio::Const::Results::FAIL]
371
+ stp[:flow][Decouplio::Const::Results::FAIL] ||= flow_hash[Decouplio::Const::Results::FAIL]
372
+ stp[:flow][Decouplio::Const::Results::ERROR] ||= flow_hash[Decouplio::Const::Results::ERROR]
373
+ stp[:flow][Decouplio::Const::Results::FINISH_HIM] = Decouplio::Const::Results::NO_STEP
374
+ end
375
+
376
+ def compose_pass_condition_flow(stp, flow, idx, flow_hash)
377
+ stp[:flow][Decouplio::Const::Results::PASS] = next_success_step(flow.values, idx, nil)
378
+ stp[:flow][Decouplio::Const::Results::FAIL] = next_success_step(flow.values, idx + 1, nil)
379
+ stp[:flow][Decouplio::Const::Results::FAIL] ||= flow_hash[Decouplio::Const::Results::PASS]
380
+ end
381
+
382
+ def compose_fail_condition_flow(stp, flow, idx, flow_hash)
383
+ stp[:flow][Decouplio::Const::Results::PASS] = next_failure_step(flow.values, idx, nil)
384
+ stp[:flow][Decouplio::Const::Results::FAIL] = next_failure_step(flow.values, idx + 1, nil)
385
+ stp[:flow][Decouplio::Const::Results::FAIL] ||= flow_hash[Decouplio::Const::Results::FAIL]
386
+ end
387
+
388
+ def compose_octo_flow(stp, step_id, idx, flow, palps, flow_hash, action_class)
389
+ stp[:flow][Decouplio::Const::Results::PASS] = next_success_step(
390
+ flow.values,
391
+ idx,
392
+ flow[step_id][:on_success]
393
+ )
394
+ stp[:flow][Decouplio::Const::Results::FAIL] = next_failure_step(
395
+ flow.values,
396
+ idx,
397
+ flow[step_id][:on_failure]
398
+ )
399
+ stp[:flow][Decouplio::Const::Results::PASS] ||= flow_hash[Decouplio::Const::Results::PASS]
400
+ stp[:flow][Decouplio::Const::Results::FAIL] ||= flow_hash[Decouplio::Const::Results::FAIL]
401
+ stp[:flow][Decouplio::Const::Results::FINISH_HIM] = Decouplio::Const::Results::NO_STEP
402
+ stp = compose_strategy(stp, palps, flow.to_a[(idx + 1)..].to_h, action_class)
403
+ stp[:hash_case].each do |strategy_key, strategy_raw_data|
404
+ stp[:flow][strategy_key] = strategy_raw_data[:first_step]
405
+ end
406
+ end
407
+
408
+ def success_type(flow, stp)
409
+ return :finish_him if [:on_success, true].include?(finish_him(stp))
410
+
411
+ step_id = stp.dig(:flow, Decouplio::Const::Results::PASS)
412
+ Decouplio::Const::Types::PASS_FLOW.include?(
413
+ flow[step_id]&.[](:type)
414
+ )
415
+ end
416
+
417
+ def failure_type(flow, stp)
418
+ return :finish_him if [:on_failure, true].include?(finish_him(stp))
419
+
420
+ step_id = stp.dig(:flow, Decouplio::Const::Results::FAIL)
421
+ Decouplio::Const::Types::FAIL_FLOW.include?(
422
+ flow[step_id]&.[](:type)
423
+ )
424
+ end
425
+
426
+ def finish_him(stp)
427
+ if stp[:on_success] == :finish_him
428
+ :on_success
429
+ elsif stp[:on_failure] == :finish_him
430
+ :on_failure
431
+ elsif stp.key?(:finish_him)
432
+ stp[:finish_him]
433
+ end
434
+ end
435
+
436
+ def compose_wrap(stp, action_class)
437
+ if Decouplio::Const::Types::WRAP_TYPE == stp[:type]
438
+ stp[:wrap_flow] = Flow.call(logic: stp[:wrap_flow], action_class: action_class)
439
+ elsif Decouplio::Const::Types::WRAP_TYPE == stp.dig(:step_to_resq, :type)
440
+ stp[:step_to_resq][:wrap_flow] = Flow.call(logic: stp[:step_to_resq][:wrap_flow], action_class: action_class)
441
+ end
442
+
443
+ stp
444
+ end
445
+
446
+ def compose_condition(stp, palp_prefix, flow)
447
+ condition_options = stp.slice(:if, :unless)
448
+
449
+ return if condition_options.empty?
450
+
451
+ Decouplio::Validators::Condition.validate(
452
+ condition_options: condition_options,
453
+ type: stp[:type]
454
+ )
455
+
456
+ condition = ([%i[name type]] + condition_options.invert.to_a).transpose.to_h
457
+ condition[:step_id] = random_id(name: condition[:name], palp_prefix: palp_prefix, flow: flow)
458
+ condition[:type] = Decouplio::Const::Types::STEP_TYPE_TO_CONDITION_TYPE.dig(stp[:type], condition[:type])
459
+ condition[:flow] = {}
460
+ condition
461
+ end
462
+
463
+ def compose_action(stp)
464
+ return stp if Decouplio::Const::Types::ACTION_NOT_ALLOWED_STEPS.include?(stp[:type])
465
+
466
+ if !stp[:name].is_a?(Symbol) && stp[:name] < Decouplio::Action
467
+ stp[:action] = stp[:name]
468
+ stp[:name] = stp[:name].name.to_sym
469
+ elsif stp[:name].is_a?(Class) && stp[:name].respond_to?(:call)
470
+ stp[:service] = stp[:name]
471
+ stp[:name] = stp[:name].name.to_sym
472
+ elsif stp.dig(:step_to_resq, :name) &&
473
+ !stp.dig(:step_to_resq, :name).is_a?(Symbol) &&
474
+ stp.dig(:step_to_resq, :name) < Decouplio::Action
475
+ stp[:step_to_resq][:action] = stp[:step_to_resq][:name]
476
+ stp[:step_to_resq][:name] = stp[:step_to_resq][:name].name.to_sym
477
+ elsif stp.dig(:step_to_resq, :name).is_a?(Class) && stp.dig(:step_to_resq, :name).respond_to?(:call)
478
+ stp[:step_to_resq][:service] = stp[:step_to_resq][:name]
479
+ stp[:step_to_resq][:name] = stp[:step_to_resq][:name].name.to_sym
480
+ elsif stp[:name].is_a?(Class)
481
+ stp[:action] = stp[:name]
482
+ elsif stp.dig(:step_to_resq, :name).is_a?(Class)
483
+ stp[:step_to_resq][:action] = stp.dig(:step_to_resq, :name)
484
+ end
485
+
486
+ if stp.key?(:action)
487
+ stp[:type] = Decouplio::Const::Types::STEP_TYPE_TO_INNER_TYPE[stp[:type]]
488
+ elsif stp.dig(:step_to_resq, :action)
489
+ stp[:step_to_resq][:type] = Decouplio::Const::Types::STEP_TYPE_TO_INNER_TYPE[stp[:type]]
490
+ end
491
+
492
+ if stp.key?(:service)
493
+ stp[:type] = Decouplio::Const::Types::STEP_TYPE_TO_SERVICE_TYPE[stp[:type]]
494
+ elsif stp.dig(:step_to_resq, :service)
495
+ stp[:step_to_resq][:type] = Decouplio::Const::Types::STEP_TYPE_TO_SERVICE_TYPE[stp[:type]]
496
+ end
497
+
498
+ stp
499
+ end
500
+
501
+ def compose_strategy(stp, palps, next_steps, action_class)
502
+ return stp unless stp[:type] == Decouplio::Const::Types::OCTO_TYPE
503
+
504
+ stp[:hash_case] = stp[:hash_case].to_h do |strategy_key, options|
505
+ strategy_flow = compose(
506
+ logic_container_raw_data: palps[options[:palp]],
507
+ action_class: action_class,
508
+ palp_prefix: options[:palp],
509
+ parent_flow: stp[:flow],
510
+ next_steps: next_steps
511
+ )
512
+ [
513
+ strategy_key,
514
+ strategy_flow
515
+ ]
516
+ end
517
+ stp
518
+ end
519
+
520
+ def compose_resq(stp, palp_prefix, flow)
521
+ return stp unless stp[:type] == Decouplio::Const::Types::RESQ_TYPE
522
+
523
+ options_for_resq = stp[:step_to_resq].slice(
524
+ :on_success,
525
+ :on_failure,
526
+ :finish_him,
527
+ :if,
528
+ :unless
529
+ )
530
+ stp[:step_id] = random_id(name: stp[:name], palp_prefix: palp_prefix, flow: flow)
531
+ stp[:flow] = {}
532
+ handler_hash = {}
533
+ stp[:handler_hash].each do |handler_method, error_classes|
534
+ [error_classes].flatten.each do |error_class|
535
+ handler_hash[error_class] = handler_method
536
+ end
537
+ end
538
+ stp[:handler_hash] = handler_hash
539
+ stp[:type] = Decouplio::Const::Types::STEP_TYPE_TO_RESQ_TYPE[stp[:step_to_resq][:type]]
540
+ stp.merge(options_for_resq)
541
+ end
542
+
543
+ def next_success_step(steps, idx, value)
544
+ steps_slice = steps[(idx + 1)..]
545
+ steps_slice.each_with_index do |stp, index|
546
+ if value == stp[:name]
547
+ prev_step = steps_slice[index - 1]
548
+ if [
549
+ Decouplio::Const::Types::IF_TYPE_PASS,
550
+ Decouplio::Const::Types::UNLESS_TYPE_PASS
551
+ ].include?(prev_step[:type])
552
+ return prev_step[:step_id]
553
+ else
554
+ return stp[:step_id]
555
+ end
556
+ elsif !value && Decouplio::Const::Types::SUCCESS_TRACK_STEP_TYPES.include?(stp[:type])
557
+ return stp[:step_id]
558
+ end
559
+ end
560
+
561
+ Decouplio::Const::Results::NO_STEP
562
+ end
563
+
564
+ def next_failure_step(steps, idx, value)
565
+ steps_slice = steps[(idx + 1)..]
566
+ steps_slice.each_with_index do |stp, index|
567
+ if value == stp[:name]
568
+ prev_step = steps_slice[index - 1]
569
+ if [
570
+ Decouplio::Const::Types::IF_TYPE_FAIL,
571
+ Decouplio::Const::Types::UNLESS_TYPE_FAIL
572
+ ].include?(prev_step[:type])
573
+ return prev_step[:step_id]
574
+ else
575
+ return stp[:step_id]
576
+ end
577
+ elsif !value && Decouplio::Const::Types::FAILURE_TRACK_STEP_TYPES.include?(stp[:type])
578
+ return stp[:step_id]
579
+ end
580
+ end
581
+
582
+ Decouplio::Const::Results::NO_STEP
583
+ end
584
+
585
+ def random_id(name:, palp_prefix:, flow:)
586
+ loop do
587
+ random_step_id =
588
+ "#{palp_prefix}_#{name}_#{random_value}#{random_value}#{random_value}#{random_value}#{random_value}".to_sym
589
+
590
+ break random_step_id if flow.select { |stp| stp[:step_id] == random_step_id }.empty?
591
+ end
592
+ end
593
+
594
+ def random_value
595
+ (10..99).to_a.sample
596
+ end
597
+ end
598
+ end
599
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decouplio
4
+ module Const
5
+ module Colors
6
+ BLACK = "\033[0;30m"
7
+ DARK_GRAY = "\033[1;30m"
8
+ RED = "\033[0;31m"
9
+ LIGHT_RED = "\033[1;31m"
10
+ GREEN = "\033[0;32m"
11
+ LIGHT_GREEN = "\033[1;32m"
12
+ BROWN_ORANGE = "\033[0;33m"
13
+ YELLOW = "\033[1;33m"
14
+ BLUE = "\033[0;34m"
15
+ LIGHT_BLUE = "\033[1;34m"
16
+ PURPLE = "\033[0;35m"
17
+ LIGHT_PURPLE = "\033[1;35m"
18
+ CYAN = "\033[0;36m"
19
+ LIGHT_CYAN = "\033[1;36m"
20
+ LIGHT_GRAY = "\033[0;37m"
21
+ WHITE = "\033[1;37m"
22
+ NO_COLOR = "\033[0m"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decouplio
4
+ module Const
5
+ module ReservedMethods
6
+ NAMES = %i[
7
+ []
8
+ success?
9
+ failure?
10
+ fail_action
11
+ pass_action
12
+ append_railway_flow
13
+ inspect
14
+ to_s
15
+ ].freeze
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decouplio
4
+ module Const
5
+ module Results
6
+ PASS = true
7
+ FAIL = false
8
+ ERROR = :error
9
+ FINISH_HIM = :finish_him
10
+ NO_STEP = nil
11
+ end
12
+ end
13
+ end