decouplio 1.0.0alpha1 → 1.0.0alpha2

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/README.md +26 -2
  4. data/benchmarks/Gemfile +2 -1
  5. data/benchmarks/multi_step_benchmark.rb +335 -0
  6. data/benchmarks/single_step_benchmark.rb +159 -0
  7. data/docker-compose.yml +13 -2
  8. data/docs/deny.rb +59 -0
  9. data/docs/doby.rb +1 -1
  10. data/docs/doby_deny.md +171 -0
  11. data/docs/fail.md +143 -0
  12. data/docs/fail.rb +126 -29
  13. data/docs/resq.md +2 -2
  14. data/docs/step.md +148 -0
  15. data/docs/step.rb +119 -18
  16. data/docs/step_as_a_service.md +25 -11
  17. data/docs/step_as_a_service.rb +2 -2
  18. data/docs/wrap.md +8 -0
  19. data/lib/decouplio/action.rb +22 -3
  20. data/lib/decouplio/composer.rb +78 -12
  21. data/lib/decouplio/const/reserved_methods.rb +13 -9
  22. data/lib/decouplio/const/results.rb +2 -0
  23. data/lib/decouplio/const/types.rb +11 -5
  24. data/lib/decouplio/const/validations/deny.rb +11 -0
  25. data/lib/decouplio/const/validations/fail.rb +1 -1
  26. data/lib/decouplio/errors/deny_can_not_be_first_step_error.rb +18 -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/logic_dsl.rb +14 -2
  29. data/lib/decouplio/options_validator.rb +8 -3
  30. data/lib/decouplio/steps/deny.rb +31 -0
  31. data/lib/decouplio/steps/doby.rb +5 -1
  32. data/lib/decouplio/steps/fail.rb +7 -22
  33. data/lib/decouplio/steps/inner_action_fail.rb +7 -22
  34. data/lib/decouplio/steps/inner_action_step.rb +7 -18
  35. data/lib/decouplio/steps/service_fail.rb +11 -23
  36. data/lib/decouplio/steps/service_pass.rb +4 -1
  37. data/lib/decouplio/steps/service_step.rb +11 -19
  38. data/lib/decouplio/steps/shared/fail_resolver.rb +40 -0
  39. data/lib/decouplio/steps/shared/step_resolver.rb +43 -0
  40. data/lib/decouplio/steps/step.rb +7 -18
  41. data/lib/decouplio/steps/wrap.rb +7 -18
  42. data/lib/decouplio/version.rb +1 -1
  43. metadata +12 -5
  44. data/benchmarks/benchmarks.rb +0 -527
  45. data/docs/doby.md +0 -80
@@ -1,527 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_interaction'
4
- require 'interactor'
5
- require 'mutations'
6
- require 'trailblazer'
7
- require_relative '../lib/decouplio'
8
- require 'pry'
9
- require 'benchmark'
10
- require 'ruby-prof'
11
-
12
- class MutationTest < Mutations::Command
13
- required do
14
- string :param1
15
- end
16
-
17
- def execute
18
- @param1 = 'param1'
19
- @context = {}
20
- step_one
21
- step_two
22
- step_three
23
- step_four
24
- step_five
25
- step_six
26
- step_seven
27
- step_eight
28
- step_nine
29
-
30
- @context
31
- end
32
-
33
- def step_one
34
- @context[:step_one] = @param1
35
- end
36
-
37
- def step_two
38
- @context[:step_two] = @context[:step_one]
39
- end
40
-
41
- def step_three
42
- @context[:step_three] = @context[:step_two]
43
- end
44
-
45
- def step_four
46
- @context[:step_four] = @context[:step_three]
47
- end
48
-
49
- def step_five
50
- @context[:step_five] = @context[:step_four]
51
- end
52
-
53
- def step_six
54
- @context[:step_six] = @context[:step_five]
55
- end
56
-
57
- def step_seven
58
- @context[:step_seven] = @context[:step_six]
59
- end
60
-
61
- def step_eight
62
- @context[:step_eight] = @context[:step_seven]
63
- end
64
-
65
- def step_nine
66
- @context[:step_nine] = @context[:step_eight]
67
- end
68
- end
69
-
70
- class ActiveInteractionTest < ActiveInteraction::Base
71
- string :param1
72
-
73
- def execute
74
- @context = {}
75
- step_one
76
- step_two
77
- step_three
78
- step_four
79
- step_five
80
- step_six
81
- step_seven
82
- step_eight
83
- step_nine
84
-
85
- @context
86
- end
87
-
88
- def step_one
89
- @context[:step_one] = param1
90
- end
91
-
92
- def step_two
93
- @context[:step_two] = @context[:step_one]
94
- end
95
-
96
- def step_three
97
- @context[:step_three] = @context[:step_two]
98
- end
99
-
100
- def step_four
101
- @context[:step_four] = @context[:step_three]
102
- end
103
-
104
- def step_five
105
- @context[:step_five] = @context[:step_four]
106
- end
107
-
108
- def step_six
109
- @context[:step_six] = @context[:step_five]
110
- end
111
-
112
- def step_seven
113
- @context[:step_seven] = @context[:step_six]
114
- end
115
-
116
- def step_eight
117
- @context[:step_eight] = @context[:step_seven]
118
- end
119
-
120
- def step_nine
121
- @context[:step_nine] = @context[:step_eight]
122
- end
123
- end
124
-
125
- class DecouplioTestSeveralSteps < Decouplio::Action
126
- logic do
127
- step :step_one
128
- step :step_two
129
- step :step_three
130
- step :step_four
131
- step :step_five
132
- step :step_six
133
- step :step_seven
134
- step :step_eight
135
- step :step_nine
136
- end
137
-
138
- def step_one(param1:, **)
139
- ctx[:step_one] = param1
140
- end
141
-
142
- def step_two(step_one:, **)
143
- ctx[:step_two] = step_one
144
- end
145
-
146
- def step_three(step_two:, **)
147
- ctx[:step_three] = step_two
148
- end
149
-
150
- def step_four(step_three:, **)
151
- ctx[:step_four] = step_three
152
- end
153
-
154
- def step_five(step_four:, **)
155
- ctx[:step_five] = step_four
156
- end
157
-
158
- def step_six(step_five:, **)
159
- ctx[:step_six] = step_five
160
- end
161
-
162
- def step_seven(step_six:, **)
163
- ctx[:step_seven] = step_six
164
- end
165
-
166
- def step_eight(step_seven:, **)
167
- ctx[:step_eight] = step_seven
168
- end
169
-
170
- def step_nine(step_eight:, **)
171
- ctx[:step_nine] = step_eight
172
- end
173
- end
174
-
175
- class DecouplioTestOneStep < Decouplio::Action
176
- logic do
177
- step :step_one
178
- end
179
-
180
- def step_one(param1:, **)
181
- ctx[:step_one] = param1
182
- ctx[:step_two] = ctx[:step_one]
183
- ctx[:step_three] = ctx[:step_two]
184
- ctx[:step_four] = ctx[:step_three]
185
- ctx[:step_five] = ctx[:step_four]
186
- ctx[:step_six] = ctx[:step_five]
187
- ctx[:step_seven] = ctx[:step_six]
188
- ctx[:step_eight] = ctx[:step_seven]
189
- ctx[:step_nine] = ctx[:step_eight]
190
- end
191
- end
192
-
193
- class StepOne
194
- include Interactor
195
-
196
- def call
197
- context.step_one = context.param1
198
- end
199
- end
200
-
201
- class StepTwo
202
- include Interactor
203
-
204
- def call
205
- context.step_two = context.step_one
206
- end
207
- end
208
-
209
- class StepThree
210
- include Interactor
211
-
212
- def call
213
- context.step_three = context.step_two
214
- end
215
- end
216
-
217
- class StepFour
218
- include Interactor
219
-
220
- def call
221
- context.step_four = context.step_three
222
- end
223
- end
224
-
225
- class StepFive
226
- include Interactor
227
-
228
- def call
229
- context.step_five = context.step_four
230
- end
231
- end
232
-
233
- class StepSix
234
- include Interactor
235
-
236
- def call
237
- context.step_six = context.step_five
238
- end
239
- end
240
-
241
- class StepSeven
242
- include Interactor
243
-
244
- def call
245
- context.step_seven = context.step_six
246
- end
247
- end
248
-
249
- class StepEight
250
- include Interactor
251
-
252
- def call
253
- context.step_eight = context.step_seven
254
- end
255
- end
256
-
257
- class StepNine
258
- include Interactor
259
-
260
- def call
261
- context.step_nine = context.step_eight
262
- end
263
- end
264
-
265
- class InteractorTestOrganizer
266
- include Interactor::Organizer
267
-
268
- organize StepOne,
269
- StepTwo,
270
- StepThree,
271
- StepFour,
272
- StepFive,
273
- StepSix,
274
- StepSeven,
275
- StepEight,
276
- StepNine
277
- end
278
-
279
- class InteractorWithoutOrganizer
280
- include Interactor
281
-
282
- def call
283
- step_one
284
- step_two
285
- step_three
286
- step_four
287
- step_five
288
- step_six
289
- step_seven
290
- step_eight
291
- step_nine
292
- end
293
-
294
- def step_one
295
- context.step_one = context.param1
296
- end
297
-
298
- def step_two
299
- context.step_two = context.step_one
300
- end
301
-
302
- def step_three
303
- context.step_three = context.step_two
304
- end
305
-
306
- def step_four
307
- context.step_four = context.step_three
308
- end
309
-
310
- def step_five
311
- context.step_five = context.step_four
312
- end
313
-
314
- def step_six
315
- context.step_six = context.step_five
316
- end
317
-
318
- def step_seven
319
- context.step_seven = context.step_six
320
- end
321
-
322
- def step_eight
323
- context.step_eight = context.step_seven
324
- end
325
-
326
- def step_nine
327
- context.step_nine = context.step_eight
328
- end
329
- end
330
-
331
- class RegularServiceTest
332
- attr_accessor :ctx, :param1
333
-
334
- def self.call(param1:)
335
- new(param1: param1).call
336
- end
337
-
338
- def initialize(param1:)
339
- @param1 = param1
340
- @ctx = {}
341
- end
342
-
343
- def call
344
- step_one
345
- step_two
346
- step_three
347
- step_four
348
- step_five
349
- step_six
350
- step_seven
351
- step_eight
352
- step_nine
353
- end
354
-
355
- def step_one
356
- ctx[:step_one] = param1
357
- end
358
-
359
- def step_two
360
- ctx[:step_two] = ctx[:step_one]
361
- end
362
-
363
- def step_three
364
- ctx[:step_three] = ctx[:step_two]
365
- end
366
-
367
- def step_four
368
- ctx[:step_four] = ctx[:step_three]
369
- end
370
-
371
- def step_five
372
- ctx[:step_five] = ctx[:step_four]
373
- end
374
-
375
- def step_six
376
- ctx[:step_six] = ctx[:step_five]
377
- end
378
-
379
- def step_seven
380
- ctx[:step_seven] = ctx[:step_six]
381
- end
382
-
383
- def step_eight
384
- ctx[:step_eight] = ctx[:step_seven]
385
- end
386
-
387
- def step_nine
388
- ctx[:step_nine] = ctx[:step_eight]
389
- end
390
- end
391
-
392
- class TrailblazerTestSeveralSteps < Trailblazer::Activity::Railway
393
- step :step_one
394
- step :step_two
395
- step :step_three
396
- step :step_four
397
- step :step_five
398
- step :step_six
399
- step :step_seven
400
- step :step_eight
401
- step :step_nine
402
-
403
- def step_one(ctx, param1:, **)
404
- ctx[:step_one] = param1
405
- end
406
-
407
- def step_two(ctx, step_one:, **)
408
- ctx[:step_two] = step_one
409
- end
410
-
411
- def step_three(ctx, step_two:, **)
412
- ctx[:step_three] = step_two
413
- end
414
-
415
- def step_four(ctx, step_three:, **)
416
- ctx[:step_four] = step_three
417
- end
418
-
419
- def step_five(ctx, step_four:, **)
420
- ctx[:step_five] = step_four
421
- end
422
-
423
- def step_six(ctx, step_five:, **)
424
- ctx[:step_six] = step_five
425
- end
426
-
427
- def step_seven(ctx, step_six:, **)
428
- ctx[:step_seven] = step_six
429
- end
430
-
431
- def step_eight(ctx, step_seven:, **)
432
- ctx[:step_eight] = step_seven
433
- end
434
-
435
- def step_nine(ctx, step_eight:, **)
436
- ctx[:step_nine] = step_eight
437
- end
438
- end
439
-
440
- class TrailblazerTestOneStep < Trailblazer::Activity::Railway
441
- step :step_one
442
-
443
- def step_one(ctx, param1:, **)
444
- ctx[:step_one] = param1
445
- ctx[:step_two] = ctx[:step_one]
446
- ctx[:step_three] = ctx[:step_two]
447
- ctx[:step_four] = ctx[:step_three]
448
- ctx[:step_five] = ctx[:step_four]
449
- ctx[:step_six] = ctx[:step_five]
450
- ctx[:step_seven] = ctx[:step_six]
451
- ctx[:step_eight] = ctx[:step_seven]
452
- ctx[:step_nine] = ctx[:step_eight]
453
- end
454
- end
455
-
456
- iteration_count = 1_000_000
457
-
458
- # result = RubyProf.profile do
459
- # iteration_count.times { InteractorTestOrganizer.call(param1: 'param1') }
460
- # end
461
-
462
- # class Two
463
- # def initialize
464
- # @ctx = {}
465
- # end
466
-
467
- # def one
468
- # @ctx[:one] = 'one'
469
- # end
470
-
471
- # def two
472
- # @ctx[:two] = @ctx[:one]
473
- # end
474
-
475
- # def three
476
- # @ctx[:three] = @ctx[:two]
477
- # end
478
- # end
479
-
480
- # instance = Two.new
481
-
482
- # Benchmark.bmbm do |x|
483
- # x.report("PublicSend") { iteration_count.times { instance.public_send(:one) } }
484
- # x.report("Send") { iteration_count.times { instance.send(:one) } }
485
- # x.report("call instance method") { iteration_count.times { instance.one } }
486
- # end
487
-
488
- # array_one = []
489
- # array_two = []
490
-
491
- # Benchmark.bmbm do |x|
492
- # x.report("<<") { iteration_count.times { array_one << 1 } }
493
- # x.report("push") { iteration_count.times { array_two << 1 } }
494
- # end
495
-
496
- # result = RubyProf.profile do
497
- # iteration_count.times { DecouplioTest.call(param1: 'param1') }
498
- # end
499
- # result = RubyProf.profile do
500
- # iteration_count.times { RegularServiceTest.call(param1: 'param1') }
501
- # end
502
- # result = RubyProf.profile do
503
- # iteration_count.times { TrailblazerTest.call(param1: 'param1') }
504
- # end
505
- # result = RubyProf.profile do
506
- # iteration_count.times { ActiveInteractionTest.run(param1: 'param1') }
507
- # end
508
- # result = RubyProf.profile do
509
- # iteration_count.times { MutationTest.run(param1: 'param1') }
510
- # end
511
-
512
- # printer = RubyProf::GraphPrinter.new(result)
513
- # printer.print(STDOUT, {})
514
-
515
- Benchmark.bmbm do |x|
516
- x.report('RegularService') { iteration_count.times { RegularServiceTest.call(param1: 'param1') } }
517
- x.report('Mutation') { iteration_count.times { MutationTest.run(param1: 'param1') } }
518
- x.report('ActiveInteraction') { iteration_count.times { ActiveInteractionTest.run(param1: 'param1') } }
519
- x.report('Trailblazer one step') { iteration_count.times { TrailblazerTestOneStep.call(param1: 'param1') } }
520
- x.report('Interactor one interactor') { iteration_count.times { InteractorWithoutOrganizer.call(param1: 'param1') } }
521
- x.report('Decouplio one step') { iteration_count.times { DecouplioTestOneStep.call(param1: 'param1') } }
522
- x.report('Trailblazer several steps') { iteration_count.times { TrailblazerTestSeveralSteps.call(param1: 'param1') } }
523
- x.report('Interactor several interactions with organizer') do
524
- iteration_count.times { InteractorTestOrganizer.call(param1: 'param1') }
525
- end
526
- x.report('Decouplio several steps') { iteration_count.times { DecouplioTestSeveralSteps.call(param1: 'param1') } }
527
- end
data/docs/doby.md DELETED
@@ -1,80 +0,0 @@
1
- # Doby
2
-
3
- It's a step type to make configurable manipulations with action context.
4
-
5
-
6
- ## Signature
7
-
8
- ```ruby
9
- doby(class_constant, **options)
10
- ```
11
-
12
- ## How to use?
13
-
14
- Create the ruby class which has `.call` class method.
15
-
16
- `.call` method signature:
17
- ```ruby
18
- # :ctx - is the required kwarg
19
- # ** - kwargs passed from action
20
- def self.call(ctx:, **)
21
- end
22
- ```
23
-
24
- ```ruby
25
- class AssignDoby
26
- def self.call(ctx:, to:, from: nil, value: nil)
27
- raise 'from/value is empty' unless from || value
28
-
29
- ctx[to] = value || ctx[from]
30
- end
31
- end
32
- ```
33
-
34
- Now you can use `AssignDoby` class inside action
35
- ```ruby
36
- require 'decouplio'
37
-
38
- class AssignDoby
39
- def self.call(ctx:, to:, from: nil, value: nil)
40
- raise 'from/value is empty' unless from || value
41
-
42
- ctx[to] = value || ctx[from]
43
- end
44
- end
45
-
46
- class SomeAction < Decouplio::Action
47
- logic do
48
- step :user
49
- step AssignDoby, to: :current_user, from: :user
50
- end
51
-
52
- def user(id:, **)
53
- ctx[:user] = "User with id: #{id}"
54
- end
55
- end
56
-
57
- action = SomeAction.call(id: 1)
58
-
59
- action[:user] # => "User with id: 1"
60
-
61
- action[:current_user] # => "User with id: 1"
62
-
63
- action # =>
64
- # Result: success
65
-
66
- # Railway Flow:
67
- # user -> AssignDoby
68
-
69
- # Context:
70
- # {:id=>1, :user=>"User with id: 1", :current_user=>"User with id: 1"}
71
-
72
- # Errors:
73
- # {}
74
- ```
75
-
76
- ## Behavior
77
-
78
- - `doby` behaves similar to `step`, depending on `.call` method returning value(truthy or falsy) the execution will be moved to `success or failure` track accordingly.
79
- - `doby` doesn't have `on_success, on_failure, if, unless, finish_him` options.
80
- - All options passed after class constant will be passed as kwargs for `.call` method.