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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +11 -1
- data/.rubocop.yml +7 -0
- data/README.md +12 -3
- data/benchmarks/Gemfile +2 -1
- data/benchmarks/multi_step_benchmark.rb +336 -0
- data/benchmarks/single_step_benchmark.rb +159 -0
- data/decouplio.gemspec +4 -4
- data/docker-compose.yml +13 -2
- data/lib/decouplio/action.rb +34 -3
- data/lib/decouplio/composer.rb +111 -22
- data/lib/decouplio/const/doby_aide_options.rb +15 -0
- data/lib/decouplio/const/error_messages.rb +9 -0
- data/lib/decouplio/const/reserved_methods.rb +13 -9
- data/lib/decouplio/const/results.rb +2 -0
- data/lib/decouplio/const/types.rb +19 -5
- data/lib/decouplio/const/validations/aide.rb +38 -0
- data/lib/decouplio/const/validations/doby.rb +36 -0
- data/lib/decouplio/const/validations/fail.rb +5 -1
- data/lib/decouplio/const/validations/octo.rb +2 -1
- data/lib/decouplio/errors/aide_can_not_be_first_step_error.rb +18 -0
- data/lib/decouplio/errors/aide_controversial_keys_error.rb +26 -0
- data/lib/decouplio/errors/aide_finish_him_error.rb +26 -0
- data/lib/decouplio/errors/doby_controversial_keys_error.rb +26 -0
- data/lib/decouplio/errors/doby_finish_him_error.rb +26 -0
- data/lib/decouplio/errors/execution_error.rb +20 -0
- data/lib/decouplio/errors/{fail_is_first_step_error.rb → fail_can_not_be_first_step_error.rb} +1 -1
- data/lib/decouplio/errors/step_is_not_defined_for_aide_error.rb +26 -0
- data/lib/decouplio/errors/step_is_not_defined_for_doby_error.rb +27 -0
- data/lib/decouplio/errors/step_is_not_defined_for_pass_error.rb +27 -0
- data/lib/decouplio/logic_dsl.rb +30 -3
- data/lib/decouplio/options_validator.rb +162 -13
- data/lib/decouplio/steps/aide.rb +37 -0
- data/lib/decouplio/steps/base_resq.rb +13 -3
- data/lib/decouplio/steps/doby.rb +14 -9
- data/lib/decouplio/steps/fail.rb +7 -22
- data/lib/decouplio/steps/inner_action_fail.rb +7 -22
- data/lib/decouplio/steps/inner_action_step.rb +7 -18
- data/lib/decouplio/steps/octo.rb +7 -2
- data/lib/decouplio/steps/service_fail.rb +11 -23
- data/lib/decouplio/steps/service_pass.rb +4 -1
- data/lib/decouplio/steps/service_step.rb +11 -19
- data/lib/decouplio/steps/shared/fail_resolver.rb +40 -0
- data/lib/decouplio/steps/shared/step_resolver.rb +43 -0
- data/lib/decouplio/steps/step.rb +7 -18
- data/lib/decouplio/steps/wrap.rb +7 -18
- data/lib/decouplio/validators/condition.rb +10 -0
- data/lib/decouplio/version.rb +1 -1
- metadata +30 -41
- data/benchmarks/benchmarks.rb +0 -527
- data/docs/_config.yml +0 -1
- data/docs/benchmarks.md +0 -1
- data/docs/context.md +0 -74
- data/docs/context.rb +0 -62
- data/docs/doby.md +0 -80
- data/docs/doby.rb +0 -38
- data/docs/error_store.md +0 -347
- data/docs/error_store.rb +0 -202
- data/docs/fail.md +0 -1016
- data/docs/fail.rb +0 -762
- data/docs/index.md +0 -25
- data/docs/inner_action.md +0 -63
- data/docs/inner_action.rb +0 -43
- data/docs/logic_block.md +0 -25
- data/docs/octo.md +0 -269
- data/docs/octo.rb +0 -164
- data/docs/pass.md +0 -309
- data/docs/pass.rb +0 -213
- data/docs/quick_start.md +0 -71
- data/docs/quick_start.rb +0 -38
- data/docs/resq.md +0 -263
- data/docs/resq.rb +0 -176
- data/docs/step.md +0 -737
- data/docs/step.rb +0 -526
- data/docs/step_as_a_service.md +0 -109
- data/docs/step_as_a_service.rb +0 -77
- data/docs/wrap.md +0 -232
- data/docs/wrap.rb +0 -137
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 837f903aec27c7a95ab61c92f4072e040fa4c2dfc74ebcafe0f740428b3cce59
|
4
|
+
data.tar.gz: faeef52b5bc5f8f1abdd419c13cd7871576c86a23e9d5d00c8aa9ab12a150b05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:
|
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
data/README.md
CHANGED
@@ -14,15 +14,24 @@ And then execute:
|
|
14
14
|
|
15
15
|
$ bundle
|
16
16
|
|
17
|
-
Or install it yourself
|
17
|
+
Or install it by yourself:
|
18
18
|
|
19
19
|
$ gem install decouplio
|
20
20
|
|
21
|
-
|
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
@@ -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', '
|
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
|
-
|
4
|
+
benchmark_single_step:
|
5
5
|
build:
|
6
6
|
dockerfile: benchmarks/Dockerfile
|
7
7
|
context: .
|
8
|
-
command: "ruby
|
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:
|
data/lib/decouplio/action.rb
CHANGED
@@ -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,
|
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
|
-
#{
|
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)
|