decouplio 1.0.0alpha1 → 1.0.0alpha4

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +11 -1
  3. data/.rubocop.yml +7 -0
  4. data/README.md +12 -3
  5. data/benchmarks/Gemfile +2 -1
  6. data/benchmarks/multi_step_benchmark.rb +336 -0
  7. data/benchmarks/single_step_benchmark.rb +159 -0
  8. data/decouplio.gemspec +4 -4
  9. data/docker-compose.yml +13 -2
  10. data/lib/decouplio/action.rb +34 -3
  11. data/lib/decouplio/composer.rb +111 -22
  12. data/lib/decouplio/const/doby_aide_options.rb +15 -0
  13. data/lib/decouplio/const/error_messages.rb +9 -0
  14. data/lib/decouplio/const/reserved_methods.rb +13 -9
  15. data/lib/decouplio/const/results.rb +2 -0
  16. data/lib/decouplio/const/types.rb +19 -5
  17. data/lib/decouplio/const/validations/aide.rb +38 -0
  18. data/lib/decouplio/const/validations/doby.rb +36 -0
  19. data/lib/decouplio/const/validations/fail.rb +5 -1
  20. data/lib/decouplio/const/validations/octo.rb +2 -1
  21. data/lib/decouplio/errors/aide_can_not_be_first_step_error.rb +18 -0
  22. data/lib/decouplio/errors/aide_controversial_keys_error.rb +26 -0
  23. data/lib/decouplio/errors/aide_finish_him_error.rb +26 -0
  24. data/lib/decouplio/errors/doby_controversial_keys_error.rb +26 -0
  25. data/lib/decouplio/errors/doby_finish_him_error.rb +26 -0
  26. data/lib/decouplio/errors/execution_error.rb +20 -0
  27. data/lib/decouplio/errors/{fail_is_first_step_error.rb → fail_can_not_be_first_step_error.rb} +1 -1
  28. data/lib/decouplio/errors/step_is_not_defined_for_aide_error.rb +26 -0
  29. data/lib/decouplio/errors/step_is_not_defined_for_doby_error.rb +27 -0
  30. data/lib/decouplio/errors/step_is_not_defined_for_pass_error.rb +27 -0
  31. data/lib/decouplio/logic_dsl.rb +30 -3
  32. data/lib/decouplio/options_validator.rb +162 -13
  33. data/lib/decouplio/steps/aide.rb +37 -0
  34. data/lib/decouplio/steps/base_resq.rb +13 -3
  35. data/lib/decouplio/steps/doby.rb +14 -9
  36. data/lib/decouplio/steps/fail.rb +7 -22
  37. data/lib/decouplio/steps/inner_action_fail.rb +7 -22
  38. data/lib/decouplio/steps/inner_action_step.rb +7 -18
  39. data/lib/decouplio/steps/octo.rb +7 -2
  40. data/lib/decouplio/steps/service_fail.rb +11 -23
  41. data/lib/decouplio/steps/service_pass.rb +4 -1
  42. data/lib/decouplio/steps/service_step.rb +11 -19
  43. data/lib/decouplio/steps/shared/fail_resolver.rb +40 -0
  44. data/lib/decouplio/steps/shared/step_resolver.rb +43 -0
  45. data/lib/decouplio/steps/step.rb +7 -18
  46. data/lib/decouplio/steps/wrap.rb +7 -18
  47. data/lib/decouplio/validators/condition.rb +10 -0
  48. data/lib/decouplio/version.rb +1 -1
  49. metadata +30 -41
  50. data/benchmarks/benchmarks.rb +0 -527
  51. data/docs/_config.yml +0 -1
  52. data/docs/benchmarks.md +0 -1
  53. data/docs/context.md +0 -74
  54. data/docs/context.rb +0 -62
  55. data/docs/doby.md +0 -80
  56. data/docs/doby.rb +0 -38
  57. data/docs/error_store.md +0 -347
  58. data/docs/error_store.rb +0 -202
  59. data/docs/fail.md +0 -1016
  60. data/docs/fail.rb +0 -762
  61. data/docs/index.md +0 -25
  62. data/docs/inner_action.md +0 -63
  63. data/docs/inner_action.rb +0 -43
  64. data/docs/logic_block.md +0 -25
  65. data/docs/octo.md +0 -269
  66. data/docs/octo.rb +0 -164
  67. data/docs/pass.md +0 -309
  68. data/docs/pass.rb +0 -213
  69. data/docs/quick_start.md +0 -71
  70. data/docs/quick_start.rb +0 -38
  71. data/docs/resq.md +0 -263
  72. data/docs/resq.rb +0 -176
  73. data/docs/step.md +0 -737
  74. data/docs/step.rb +0 -526
  75. data/docs/step_as_a_service.md +0 -109
  76. data/docs/step_as_a_service.rb +0 -77
  77. data/docs/wrap.md +0 -232
  78. data/docs/wrap.rb +0 -137
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 455ba12276135c618f5d53a9ff53bf8d3c7ec8074e387ea4790f2307e344c4ec
4
- data.tar.gz: 126488804cc9391fdb0fe3f9a0d2ac4060fa42bbe1d733af64bec5681e9f890d
3
+ metadata.gz: 837f903aec27c7a95ab61c92f4072e040fa4c2dfc74ebcafe0f740428b3cce59
4
+ data.tar.gz: faeef52b5bc5f8f1abdd419c13cd7871576c86a23e9d5d00c8aa9ab12a150b05
5
5
  SHA512:
6
- metadata.gz: '00912905816c9e9393e907185347ddd3d9fb2de753a2fa3d7aeaae704ef8d93e26ff5f3ae62a7589384921717b9d764af2e2502b7c43866fb503f63837079999'
7
- data.tar.gz: 50d1d117ee1ec34f94f750c1f2d1aad73f41127e8585bd01ee32209b361d067b6fa054b242878e18bfa01682344388badb386dc6a39883a1957516ccfc4a202f
6
+ metadata.gz: 5df71fc94709fc03625e36281d5458043616200153deee80fb5e2013900d85f8412a0adb30ce1516a90633e4ecef8aa9ff37d7ff5b7cdfc1aca1b2179aee7e0c
7
+ data.tar.gz: b39a6be930ed5ce6adf0257537fd5b99392259d889fc236457ed4d9b6f5e69a868648cf2a945f064be25d6978d8ad158001554d0b24da2e32cd92c1fe39a217c
data/.circleci/config.yml CHANGED
@@ -3,7 +3,7 @@ version: 2.1
3
3
  executors:
4
4
  test_executor:
5
5
  docker:
6
- - image: circleci/ruby:${RUBY_VERSION}
6
+ - image: cimg/ruby:${RUBY_VERSION}
7
7
  working_directory: ~/decouplio
8
8
 
9
9
  jobs:
@@ -51,3 +51,13 @@ workflows:
51
51
  name: 'ruby 3.0.3'
52
52
  ruby_version: 3.0.3
53
53
  bundler_version: 2.2.32
54
+ # TODO: Currently rspec-mocks has some issue, or maybe decouplio has an issue
55
+ # needs to be investigated
56
+ # 3 specs are failing
57
+ # rspec ./spec/resq_spec.rb:174
58
+ # rspec ./spec/resq_spec.rb:286
59
+ # rspec ./spec/resq_spec.rb:398
60
+ # - build:
61
+ # name: 'ruby 3.1.2'
62
+ # ruby_version: 3.1.2
63
+ # bundler_version: 2.2.32
data/.rubocop.yml CHANGED
@@ -104,3 +104,10 @@ RSpec/MultipleMemoizedHelpers:
104
104
  Naming/PredicateName:
105
105
  Exclude:
106
106
  - lib/decouplio/step.rb
107
+
108
+ Naming/MethodParameterName:
109
+ Exclude:
110
+ - spec/support/cases/**/*
111
+
112
+ Naming/RescuedExceptionsVariableName:
113
+ Enabled: false
data/README.md CHANGED
@@ -14,15 +14,24 @@ And then execute:
14
14
 
15
15
  $ bundle
16
16
 
17
- Or install it yourself as:
17
+ Or install it by yourself:
18
18
 
19
19
  $ gem install decouplio
20
20
 
21
- # [>>>>>>>DOCS HERE<<<<<<<](https://github.com/differencialx/decouplio/blob/master/docs/index.md)
21
+ ## Currently decouplio is in alpha testing, more features will come soon.
22
+
23
+ ### Compatibility
24
+ Ruby:
25
+ - 2.7
26
+ - 3.0
27
+
28
+ ### [Documentation is HERE](https://differencialx.github.io/decouplio.github.io/)
22
29
 
23
30
  ## Contributing
24
31
 
25
- Bug reports and pull requests are welcome on GitHub at https://github.com/differencialx/decouplio.
32
+ Bug reports and pull requests are welcome on GitHub at https://github.com/differencialx/decouplio/issues.
33
+
34
+ More detailed description for contribution process will be added later.
26
35
 
27
36
  ## License
28
37
 
data/benchmarks/Gemfile CHANGED
@@ -3,7 +3,8 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gem 'active_interaction', '~> 4.1'
6
- gem 'decouplio', path: '../'
6
+ gem 'benchmark-ips'
7
+ gem 'decouplio'
7
8
  gem 'interactor', '~> 3.0'
8
9
  gem 'mutations'
9
10
  gem 'pry-byebug'
@@ -0,0 +1,336 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_interaction'
4
+ require 'interactor'
5
+ require 'mutations'
6
+ require 'trailblazer'
7
+ require 'decouplio'
8
+ require 'benchmark/ips'
9
+
10
+ class RegularServiceTest
11
+ attr_accessor :ctx, :param1
12
+
13
+ def self.call(param1:)
14
+ new(param1: param1).call
15
+ end
16
+
17
+ def initialize(param1:)
18
+ @param1 = param1
19
+ @ctx = {}
20
+ end
21
+
22
+ def call
23
+ step_one
24
+ step_two
25
+ step_three
26
+ step_four
27
+ step_five
28
+ step_six
29
+ step_seven
30
+ step_eight
31
+ step_nine
32
+ self
33
+ end
34
+
35
+ def step_one
36
+ ctx[:step_one] = param1
37
+ end
38
+
39
+ def step_two
40
+ ctx[:step_two] = ctx[:step_one]
41
+ end
42
+
43
+ def step_three
44
+ ctx[:step_three] = ctx[:step_two]
45
+ end
46
+
47
+ def step_four
48
+ ctx[:step_four] = ctx[:step_three]
49
+ end
50
+
51
+ def step_five
52
+ ctx[:step_five] = ctx[:step_four]
53
+ end
54
+
55
+ def step_six
56
+ ctx[:step_six] = ctx[:step_five]
57
+ end
58
+
59
+ def step_seven
60
+ ctx[:step_seven] = ctx[:step_six]
61
+ end
62
+
63
+ def step_eight
64
+ ctx[:step_eight] = ctx[:step_seven]
65
+ end
66
+
67
+ def step_nine
68
+ ctx[:step_nine] = ctx[:step_eight]
69
+ end
70
+ end
71
+
72
+ class DecouplioTestSeveralSteps < Decouplio::Action
73
+ logic do
74
+ step :step_one
75
+ step :step_two
76
+ step :step_three
77
+ step :step_four
78
+ step :step_five
79
+ step :step_six
80
+ step :step_seven
81
+ step :step_eight
82
+ step :step_nine
83
+ end
84
+
85
+ def step_one(param1:, **)
86
+ ctx[:step_one] = param1
87
+ end
88
+
89
+ def step_two(step_one:, **)
90
+ ctx[:step_two] = step_one
91
+ end
92
+
93
+ def step_three(step_two:, **)
94
+ ctx[:step_three] = step_two
95
+ end
96
+
97
+ def step_four(step_three:, **)
98
+ ctx[:step_four] = step_three
99
+ end
100
+
101
+ def step_five(step_four:, **)
102
+ ctx[:step_five] = step_four
103
+ end
104
+
105
+ def step_six(step_five:, **)
106
+ ctx[:step_six] = step_five
107
+ end
108
+
109
+ def step_seven(step_six:, **)
110
+ ctx[:step_seven] = step_six
111
+ end
112
+
113
+ def step_eight(step_seven:, **)
114
+ ctx[:step_eight] = step_seven
115
+ end
116
+
117
+ def step_nine(step_eight:, **)
118
+ ctx[:step_nine] = step_eight
119
+ end
120
+ end
121
+
122
+ class StepOne
123
+ include Interactor
124
+
125
+ def call
126
+ context.step_one = context.param1
127
+ end
128
+ end
129
+
130
+ class StepTwo
131
+ include Interactor
132
+
133
+ def call
134
+ context.step_two = context.step_one
135
+ end
136
+ end
137
+
138
+ class StepThree
139
+ include Interactor
140
+
141
+ def call
142
+ context.step_three = context.step_two
143
+ end
144
+ end
145
+
146
+ class StepFour
147
+ include Interactor
148
+
149
+ def call
150
+ context.step_four = context.step_three
151
+ end
152
+ end
153
+
154
+ class StepFive
155
+ include Interactor
156
+
157
+ def call
158
+ context.step_five = context.step_four
159
+ end
160
+ end
161
+
162
+ class StepSix
163
+ include Interactor
164
+
165
+ def call
166
+ context.step_six = context.step_five
167
+ end
168
+ end
169
+
170
+ class StepSeven
171
+ include Interactor
172
+
173
+ def call
174
+ context.step_seven = context.step_six
175
+ end
176
+ end
177
+
178
+ class StepEight
179
+ include Interactor
180
+
181
+ def call
182
+ context.step_eight = context.step_seven
183
+ end
184
+ end
185
+
186
+ class StepNine
187
+ include Interactor
188
+
189
+ def call
190
+ context.step_nine = context.step_eight
191
+ end
192
+ end
193
+
194
+ class InteractorTestOrganizer
195
+ include Interactor::Organizer
196
+
197
+ organize StepOne,
198
+ StepTwo,
199
+ StepThree,
200
+ StepFour,
201
+ StepFive,
202
+ StepSix,
203
+ StepSeven,
204
+ StepEight,
205
+ StepNine
206
+ end
207
+
208
+ class TrailblazerTestSeveralSteps < Trailblazer::Activity::Railway
209
+ step :step_one
210
+ step :step_two
211
+ step :step_three
212
+ step :step_four
213
+ step :step_five
214
+ step :step_six
215
+ step :step_seven
216
+ step :step_eight
217
+ step :step_nine
218
+
219
+ def step_one(ctx, param1:, **)
220
+ ctx[:step_one] = param1
221
+ end
222
+
223
+ def step_two(ctx, step_one:, **)
224
+ ctx[:step_two] = step_one
225
+ end
226
+
227
+ def step_three(ctx, step_two:, **)
228
+ ctx[:step_three] = step_two
229
+ end
230
+
231
+ def step_four(ctx, step_three:, **)
232
+ ctx[:step_four] = step_three
233
+ end
234
+
235
+ def step_five(ctx, step_four:, **)
236
+ ctx[:step_five] = step_four
237
+ end
238
+
239
+ def step_six(ctx, step_five:, **)
240
+ ctx[:step_six] = step_five
241
+ end
242
+
243
+ def step_seven(ctx, step_six:, **)
244
+ ctx[:step_seven] = step_six
245
+ end
246
+
247
+ def step_eight(ctx, step_seven:, **)
248
+ ctx[:step_eight] = step_seven
249
+ end
250
+
251
+ def step_nine(ctx, step_eight:, **)
252
+ ctx[:step_nine] = step_eight
253
+ end
254
+ end
255
+
256
+ class DecouplioStepOne
257
+ def self.call(ctx:, **)
258
+ ctx[:step_one] = ctx[:param1]
259
+ end
260
+ end
261
+
262
+ class DecouplioStepTwo
263
+ def self.call(ctx:, **)
264
+ ctx[:step_two] = ctx[:step_one]
265
+ end
266
+ end
267
+
268
+ class DecouplioStepThree
269
+ def self.call(ctx:, **)
270
+ ctx[:step_three] = ctx[:step_two]
271
+ end
272
+ end
273
+
274
+ class DecouplioStepFour
275
+ def self.call(ctx:, **)
276
+ ctx[:step_four] = ctx[:step_three]
277
+ end
278
+ end
279
+
280
+ class DecouplioStepFive
281
+ def self.call(ctx:, **)
282
+ ctx[:step_five] = ctx[:step_four]
283
+ end
284
+ end
285
+
286
+ class DecouplioStepSix
287
+ def self.call(ctx:, **)
288
+ ctx[:step_six] = ctx[:step_five]
289
+ end
290
+ end
291
+
292
+ class DecouplioStepSeven
293
+ def self.call(ctx:, **)
294
+ ctx[:step_seven] = ctx[:step_six]
295
+ end
296
+ end
297
+
298
+ class DecouplioStepEight
299
+ def self.call(ctx:, **)
300
+ ctx[:step_eight] = ctx[:step_seven]
301
+ end
302
+ end
303
+
304
+ class DecouplioStepNine
305
+ def self.call(ctx:, **)
306
+ ctx[:step_nine] = ctx[:step_eight]
307
+ end
308
+ end
309
+
310
+ class DecouplioServiceStepsTest < Decouplio::Action
311
+ logic do
312
+ step DecouplioStepOne
313
+ step DecouplioStepTwo
314
+ step DecouplioStepThree
315
+ step DecouplioStepFour
316
+ step DecouplioStepFive
317
+ step DecouplioStepSix
318
+ step DecouplioStepSeven
319
+ step DecouplioStepEight
320
+ step DecouplioStepNine
321
+ end
322
+ end
323
+
324
+ iteration_count = 100_00
325
+
326
+ Benchmark.ips do |x|
327
+ x.report('RegularService') { iteration_count.times { RegularServiceTest.call(param1: 'param1') } }
328
+ x.report('Decouplio several steps') { iteration_count.times { DecouplioTestSeveralSteps.call(param1: 'param1') } }
329
+ x.report('Decouplio service steps') { iteration_count.times { DecouplioServiceStepsTest.call(param1: 'param1') } }
330
+ x.report('Trailblazer several steps') { iteration_count.times { TrailblazerTestSeveralSteps.call(param1: 'param1') } }
331
+ x.report('Interactor several interactions with organizer') do
332
+ iteration_count.times { InteractorTestOrganizer.call(param1: 'param1') }
333
+ end
334
+
335
+ x.compare!
336
+ end
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_interaction'
4
+ require 'interactor'
5
+ require 'mutations'
6
+ require 'trailblazer'
7
+ require 'decouplio'
8
+ require 'benchmark/ips'
9
+
10
+ class MutationTest < Mutations::Command
11
+ optional do
12
+ string :param1
13
+ end
14
+
15
+ def execute
16
+ @context = {}
17
+ @context[:step_one] = param1
18
+ @context[:step_two] = @context[:step_one]
19
+ @context[:step_three] = @context[:step_two]
20
+ @context[:step_four] = @context[:step_three]
21
+ @context[:step_five] = @context[:step_four]
22
+ @context[:step_six] = @context[:step_five]
23
+ @context[:step_seven] = @context[:step_six]
24
+ @context[:step_eight] = @context[:step_seven]
25
+ @context[:step_nine] = @context[:step_eight]
26
+
27
+ @context
28
+ end
29
+ end
30
+
31
+ class ActiveInteractionTest < ActiveInteraction::Base
32
+ string :param1
33
+
34
+ def execute
35
+ @context = {}
36
+ @context[:step_one] = param1
37
+ @context[:step_two] = @context[:step_one]
38
+ @context[:step_three] = @context[:step_two]
39
+ @context[:step_four] = @context[:step_three]
40
+ @context[:step_five] = @context[:step_four]
41
+ @context[:step_six] = @context[:step_five]
42
+ @context[:step_seven] = @context[:step_six]
43
+ @context[:step_eight] = @context[:step_seven]
44
+ @context[:step_nine] = @context[:step_eight]
45
+
46
+ @context
47
+ end
48
+ end
49
+
50
+ class DecouplioTestOneStep < Decouplio::Action
51
+ logic do
52
+ step :step_one
53
+ end
54
+
55
+ def step_one(param1:, **)
56
+ ctx[:step_one] = param1
57
+ ctx[:step_two] = ctx[:step_one]
58
+ ctx[:step_three] = ctx[:step_two]
59
+ ctx[:step_four] = ctx[:step_three]
60
+ ctx[:step_five] = ctx[:step_four]
61
+ ctx[:step_six] = ctx[:step_five]
62
+ ctx[:step_seven] = ctx[:step_six]
63
+ ctx[:step_eight] = ctx[:step_seven]
64
+ ctx[:step_nine] = ctx[:step_eight]
65
+ end
66
+ end
67
+
68
+ class InteractorWithoutOrganizer
69
+ include Interactor
70
+
71
+ def call
72
+ context.step_one = context.param1
73
+ context.step_two = context.step_one
74
+ context.step_three = context.step_two
75
+ context.step_four = context.step_three
76
+ context.step_five = context.step_four
77
+ context.step_six = context.step_five
78
+ context.step_seven = context.step_six
79
+ context.step_eight = context.step_seven
80
+ context.step_nine = context.step_eight
81
+ end
82
+ end
83
+
84
+ class RegularServiceTest
85
+ attr_accessor :ctx, :param1
86
+
87
+ def self.call(param1:)
88
+ new(param1: param1).call
89
+ end
90
+
91
+ def initialize(param1:)
92
+ @param1 = param1
93
+ @ctx = {}
94
+ end
95
+
96
+ def call
97
+ ctx[:step_one] = param1
98
+ ctx[:step_two] = ctx[:step_one]
99
+ ctx[:step_three] = ctx[:step_two]
100
+ ctx[:step_four] = ctx[:step_three]
101
+ ctx[:step_five] = ctx[:step_four]
102
+ ctx[:step_six] = ctx[:step_five]
103
+ ctx[:step_seven] = ctx[:step_six]
104
+ ctx[:step_eight] = ctx[:step_seven]
105
+ ctx[:step_nine] = ctx[:step_eight]
106
+ end
107
+ end
108
+
109
+ class TrailblazerTestOneStep < Trailblazer::Activity::Railway
110
+ step :step_one
111
+
112
+ def step_one(ctx, param1:, **)
113
+ ctx[:step_one] = param1
114
+ ctx[:step_two] = ctx[:step_one]
115
+ ctx[:step_three] = ctx[:step_two]
116
+ ctx[:step_four] = ctx[:step_three]
117
+ ctx[:step_five] = ctx[:step_four]
118
+ ctx[:step_six] = ctx[:step_five]
119
+ ctx[:step_seven] = ctx[:step_six]
120
+ ctx[:step_eight] = ctx[:step_seven]
121
+ ctx[:step_nine] = ctx[:step_eight]
122
+ end
123
+ end
124
+
125
+ class ServiceAsStep
126
+ def self.call(ctx:, **)
127
+ ctx[:step_one] = ctx[:param1]
128
+ ctx[:step_two] = ctx[:step_one]
129
+ ctx[:step_three] = ctx[:step_two]
130
+ ctx[:step_four] = ctx[:step_three]
131
+ ctx[:step_five] = ctx[:step_four]
132
+ ctx[:step_six] = ctx[:step_five]
133
+ ctx[:step_seven] = ctx[:step_six]
134
+ ctx[:step_eight] = ctx[:step_seven]
135
+ ctx[:step_nine] = ctx[:step_eight]
136
+ end
137
+ end
138
+
139
+ class DecouplioTestOneStepAsService < Decouplio::Action
140
+ logic do
141
+ step ServiceAsStep
142
+ end
143
+ end
144
+
145
+ iteration_count = 100_000
146
+
147
+ Benchmark.ips do |x|
148
+ x.report('Mutation') { iteration_count.times { MutationTest.run(param1: 'param1') } }
149
+ x.report('ActiveInteraction') { iteration_count.times { ActiveInteractionTest.run(param1: 'param1') } }
150
+ x.report('Trailblazer one step') { iteration_count.times { TrailblazerTestOneStep.call(param1: 'param1') } }
151
+ x.report('Interactor one interactor') { iteration_count.times { InteractorWithoutOrganizer.call(param1: 'param1') } }
152
+ x.report('RegularService') { iteration_count.times { RegularServiceTest.call(param1: 'param1') } }
153
+ x.report('Decouplio one step') { iteration_count.times { DecouplioTestOneStep.call(param1: 'param1') } }
154
+ x.report('Decouplio one step as service') do
155
+ iteration_count.times { DecouplioTestOneStepAsService.call(param1: 'param1') }
156
+ end
157
+
158
+ x.compare!
159
+ end
data/decouplio.gemspec CHANGED
@@ -12,13 +12,13 @@ Gem::Specification.new do |spec|
12
12
 
13
13
  spec.summary = 'Gem for business logic encapsulation'
14
14
  spec.description = "Decouplio is a zero dependency, thread safe and framework agnostic gem designed to encapsulate application business logic. It's reverse engineered through TDD and inspired by such frameworks and gems like Trailblazer, Interactor."
15
- spec.homepage = 'https://github.com/differencialx/decouplio'
15
+ spec.homepage = 'https://github.com/differencialx/decouplio/blob/master/docs'
16
16
  spec.license = 'MIT'
17
17
 
18
18
  if spec.respond_to?(:metadata)
19
19
  spec.metadata['homepage_uri'] = spec.homepage
20
- spec.metadata['source_code_uri'] = 'https://github.com/differencialx/decouplio'
21
- spec.metadata['changelog_uri'] = 'https://github.com/differencialx/decouplio/CHANGELOG.md'
20
+ spec.metadata['source_code_uri'] = 'https://github.com/differencialx/decouplio/blob/master/docs'
21
+ spec.metadata['changelog_uri'] = 'https://github.com/differencialx/decouplio/blob/master/docs/CHANGELOG.md'
22
22
  else
23
23
  raise 'RubyGems 2.0 or newer is required to protect against ' \
24
24
  'public gem pushes.'
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency 'bundler', '~> 2'
35
35
  spec.add_development_dependency 'pry-byebug'
36
36
  spec.add_development_dependency 'rake', '>= 12.3.2'
37
- spec.add_development_dependency 'rspec', '~> 3.0'
37
+ spec.add_development_dependency 'rspec', '3.10'
38
38
  spec.add_development_dependency 'rubocop'
39
39
  spec.add_development_dependency 'rubocop-rspec'
40
40
  end
data/docker-compose.yml CHANGED
@@ -1,11 +1,22 @@
1
1
  version: "3.7"
2
2
 
3
3
  services:
4
- benchmark:
4
+ benchmark_single_step:
5
5
  build:
6
6
  dockerfile: benchmarks/Dockerfile
7
7
  context: .
8
- command: "ruby benchmarks.rb"
8
+ command: "ruby single_step_benchmark.rb"
9
+ deploy:
10
+ resources:
11
+ limits:
12
+ cpus: '1'
13
+ memory: 400M
14
+
15
+ benchmark_multi_step:
16
+ build:
17
+ dockerfile: benchmarks/Dockerfile
18
+ context: .
19
+ command: "ruby multi_step_benchmark.rb"
9
20
  deploy:
10
21
  resources:
11
22
  limits:
@@ -7,15 +7,19 @@ require_relative 'default_error_handler'
7
7
  require_relative 'errors/logic_redefinition_error'
8
8
  require_relative 'errors/logic_is_not_defined_error'
9
9
  require_relative 'errors/error_store_error'
10
+ require_relative 'errors/execution_error'
11
+ require_relative 'const/results'
10
12
 
11
13
  module Decouplio
12
14
  class Action
15
+ PREVIOUS_STEP_INDEX = -2
16
+
13
17
  extend Forwardable
14
18
  def_delegators :@error_store, :errors, :add_error
15
19
  attr_reader :railway_flow, :ctx, :error_store
16
20
 
17
21
  def initialize(
18
- parent_railway_flow: nil, parent_ctx: nil, wrapper: false, error_store:, **params
22
+ parent_railway_flow: nil, parent_ctx: nil, error_store:, **params
19
23
  )
20
24
  @error_store = error_store
21
25
  @ctx = parent_ctx || params
@@ -43,6 +47,10 @@ module Decouplio
43
47
  @failure = false
44
48
  end
45
49
 
50
+ def previous_step
51
+ railway_flow[PREVIOUS_STEP_INDEX]
52
+ end
53
+
46
54
  def append_railway_flow(stp)
47
55
  railway_flow << stp
48
56
  end
@@ -55,10 +63,22 @@ module Decouplio
55
63
  #{railway_flow.join(' -> ')}
56
64
 
57
65
  Context:
58
- #{ctx}
66
+ #{ctx.map { |k, v| "#{k.inspect} => #{v.inspect}" }.join("\n ")}
59
67
 
60
68
  Errors:
61
- #{errors}
69
+ #{
70
+ if errors.is_a?(Hash)
71
+ if errors.empty?
72
+ 'None'
73
+ else
74
+ errors.map do |k, v|
75
+ "#{k.inspect} => #{v.inspect}"
76
+ end.join("\n ")
77
+ end
78
+ else
79
+ errors
80
+ end
81
+ }
62
82
  INSPECT
63
83
  end
64
84
 
@@ -80,6 +100,17 @@ module Decouplio
80
100
  instance
81
101
  end
82
102
 
103
+ def call!(**params)
104
+ instance = call(**params)
105
+ if instance.failure?
106
+ raise Decouplio::Errors::ExecutionError.new(
107
+ action: instance
108
+ )
109
+ else
110
+ instance
111
+ end
112
+ end
113
+
83
114
  private
84
115
 
85
116
  def inherited(child_class)