u-service 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -0
- data/benchmarks/interactor/pipeline_failure.rb +134 -0
- data/benchmarks/interactor/pipeline_success.rb +134 -0
- data/benchmarks/interactor/service_failure.rb +93 -0
- data/benchmarks/interactor/service_success.rb +93 -0
- data/lib/micro/service.rb +0 -4
- data/lib/micro/service/base.rb +32 -1
- data/lib/micro/service/pipeline.rb +10 -9
- data/lib/micro/service/result.rb +7 -14
- data/lib/micro/service/version.rb +1 -1
- metadata +6 -5
- data/lib/micro/service/result/failure.rb +0 -11
- data/lib/micro/service/result/helpers.rb +0 -19
- data/lib/micro/service/result/success.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 020c6ab3c508004af1b58aa443ed52b67ec587fbc23ce11c4c410dd2806af3cc
|
4
|
+
data.tar.gz: 4b528fe880ce14dadf398a1491cd9ae7b36a6a08a1d4a8cf0e8d9de48f6a0bf8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ece16f4c64119f8485ebbf1dbfe23f82c3a7cda4bd4e60da2f92fb0992d192ecf59383a5d8624f8d0fd125dd4c7e88f37ffebab51182c366bc29fac6e85f40f
|
7
|
+
data.tar.gz: 16abd91aa04f7db43b9ff21e2f0ed8d2cb6fdeb6605d6356cd24cadc4feba78090f7236533b5572923e2ae5b186827216f496bdeda7353edc68554aed4bae82a
|
data/README.md
CHANGED
@@ -23,6 +23,8 @@ The main goals of this project are:
|
|
23
23
|
- [What is a strict Service Object?](#what-is-a-strict-service-object)
|
24
24
|
- [How to validate Service Object attributes?](#how-to-validate-service-object-attributes)
|
25
25
|
- [It's possible to compose pipelines with other pipelines?](#its-possible-to-compose-pipelines-with-other-pipelines)
|
26
|
+
- [Comparisons](#comparisons)
|
27
|
+
- [Benchmarks](#benchmarks)
|
26
28
|
- [Development](#development)
|
27
29
|
- [Contributing](#contributing)
|
28
30
|
- [License](#license)
|
@@ -345,6 +347,20 @@ SquareAllNumbersAndDoubleThem
|
|
345
347
|
|
346
348
|
Note: You can blend any of the [syntaxes/approaches to create the pipelines](#how-to-create-a-pipeline-of-service-objects)) - [examples](https://github.com/serradura/u-service/blob/master/test/micro/service/pipeline/blend_test.rb#L7-L34).
|
347
349
|
|
350
|
+
## Comparisons
|
351
|
+
|
352
|
+
Check it out implementations of the same use case with different libs (abstractions).
|
353
|
+
|
354
|
+
* [interactor](https://github.com/serradura/u-service/blob/master/comparisons/interactor.rb)
|
355
|
+
* [u-service](https://github.com/serradura/u-service/blob/master/comparisons/u-service.rb)
|
356
|
+
|
357
|
+
## Benchmarks
|
358
|
+
|
359
|
+
**[interactor](https://github.com/collectiveidea/interactor)** VS **[u-service](https://github.com/serradura/u-service)**
|
360
|
+
|
361
|
+
https://github.com/serradura/u-service/tree/master/benchmarks/interactor
|
362
|
+
|
363
|
+
|
348
364
|
## Development
|
349
365
|
|
350
366
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `./test.sh` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'bundler/inline'
|
2
|
+
|
3
|
+
gemfile do
|
4
|
+
source 'https://rubygems.org'
|
5
|
+
|
6
|
+
gem 'benchmark-ips', '~> 2.7', '>= 2.7.2'
|
7
|
+
gem 'interactor', '~> 3.1', '>= 3.1.1'
|
8
|
+
gem 'u-service', '~> 0.11.0'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'benchmark/ips'
|
12
|
+
|
13
|
+
module MSB
|
14
|
+
class ConvertToNumbers < Micro::Service::Base
|
15
|
+
attribute :numbers
|
16
|
+
|
17
|
+
def call!
|
18
|
+
if numbers.all? { |value| String(value) =~ /\d+/ }
|
19
|
+
Success(numbers: numbers.map(&:to_i))
|
20
|
+
else
|
21
|
+
Failure(numbers: 'must contain only numeric types')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Add2 < Micro::Service::Base
|
27
|
+
attribute :numbers
|
28
|
+
|
29
|
+
def call!
|
30
|
+
Success(numbers: numbers.map { |number| number + 2 })
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Add2ToAllNumbers = ConvertToNumbers >> Add2
|
35
|
+
end
|
36
|
+
|
37
|
+
module MSS
|
38
|
+
class ConvertToNumbers < Micro::Service::Strict
|
39
|
+
attribute :numbers
|
40
|
+
|
41
|
+
def call!
|
42
|
+
if numbers.all? { |value| String(value) =~ /\d+/ }
|
43
|
+
Success(numbers: numbers.map(&:to_i))
|
44
|
+
else
|
45
|
+
Failure(numbers: 'must contain only numeric types')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Add2 < Micro::Service::Strict
|
51
|
+
attribute :numbers
|
52
|
+
|
53
|
+
def call!
|
54
|
+
Success(numbers: numbers.map { |number| number + 2 })
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Add2ToAllNumbers = ConvertToNumbers >> Add2
|
59
|
+
end
|
60
|
+
|
61
|
+
module IT
|
62
|
+
class ConvertToNumbers
|
63
|
+
include Interactor
|
64
|
+
|
65
|
+
def call
|
66
|
+
numbers = context.numbers
|
67
|
+
|
68
|
+
if numbers.all? { |value| String(value) =~ /\d+/ }
|
69
|
+
context.numbers = numbers.map(&:to_i)
|
70
|
+
else
|
71
|
+
context.fail! numbers: 'must contain only numeric types'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Add2
|
77
|
+
include Interactor
|
78
|
+
|
79
|
+
def call
|
80
|
+
numbers = context.numbers
|
81
|
+
|
82
|
+
context.numbers = numbers.map { |number| number + 2 }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class Add2ToAllNumbers
|
87
|
+
include Interactor::Organizer
|
88
|
+
|
89
|
+
organize ConvertToNumbers, Add2
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
NUMBERS = {numbers: %w[1 1 2 2 c 4]}
|
94
|
+
|
95
|
+
Benchmark.ips do |x|
|
96
|
+
x.config(:time => 5, :warmup => 2)
|
97
|
+
|
98
|
+
x.time = 5
|
99
|
+
x.warmup = 2
|
100
|
+
|
101
|
+
x.report('Pipeline of Micro::Service::Base') do
|
102
|
+
MSB::Add2ToAllNumbers.call(NUMBERS)
|
103
|
+
end
|
104
|
+
|
105
|
+
x.report('Pipeline of Micro::Service::Strict') do
|
106
|
+
MSS::Add2ToAllNumbers.call(NUMBERS)
|
107
|
+
end
|
108
|
+
|
109
|
+
x.report('Interactor::Organizer') do
|
110
|
+
IT::Add2ToAllNumbers.call(NUMBERS)
|
111
|
+
end
|
112
|
+
|
113
|
+
x.compare!
|
114
|
+
end
|
115
|
+
|
116
|
+
# Warming up --------------------------------------
|
117
|
+
# Pipeline of Micro::Service::Base
|
118
|
+
# 5.437k i/100ms
|
119
|
+
# Pipeline of Micro::Service::Strict
|
120
|
+
# 5.192k i/100ms
|
121
|
+
# Interactor::Organizer
|
122
|
+
# 2.236k i/100ms
|
123
|
+
# Calculating -------------------------------------
|
124
|
+
# Pipeline of Micro::Service::Base
|
125
|
+
# 56.665k (± 1.9%) i/s - 288.161k in 5.087185s
|
126
|
+
# Pipeline of Micro::Service::Strict
|
127
|
+
# 52.914k (± 2.0%) i/s - 264.792k in 5.006157s
|
128
|
+
# Interactor::Organizer
|
129
|
+
# 22.940k (± 2.9%) i/s - 116.272k in 5.072931s
|
130
|
+
|
131
|
+
# Comparison:
|
132
|
+
# Pipeline of Micro::Service::Base: 56665.3 i/s
|
133
|
+
# Pipeline of Micro::Service::Strict: 52914.3 i/s - 1.07x slower
|
134
|
+
# Interactor::Organizer: 22940.3 i/s - 2.47x slower
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'bundler/inline'
|
2
|
+
|
3
|
+
gemfile do
|
4
|
+
source 'https://rubygems.org'
|
5
|
+
|
6
|
+
gem 'benchmark-ips', '~> 2.7', '>= 2.7.2'
|
7
|
+
gem 'interactor', '~> 3.1', '>= 3.1.1'
|
8
|
+
gem 'u-service', '~> 0.11.0'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'benchmark/ips'
|
12
|
+
|
13
|
+
module MSB
|
14
|
+
class ConvertToNumbers < Micro::Service::Base
|
15
|
+
attribute :numbers
|
16
|
+
|
17
|
+
def call!
|
18
|
+
if numbers.all? { |value| String(value) =~ /\d+/ }
|
19
|
+
Success(numbers: numbers.map(&:to_i))
|
20
|
+
else
|
21
|
+
Failure(numbers: 'must contain only numeric types')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Add2 < Micro::Service::Base
|
27
|
+
attribute :numbers
|
28
|
+
|
29
|
+
def call!
|
30
|
+
Success(numbers: numbers.map { |number| number + 2 })
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Add2ToAllNumbers = ConvertToNumbers >> Add2
|
35
|
+
end
|
36
|
+
|
37
|
+
module MSS
|
38
|
+
class ConvertToNumbers < Micro::Service::Strict
|
39
|
+
attribute :numbers
|
40
|
+
|
41
|
+
def call!
|
42
|
+
if numbers.all? { |value| String(value) =~ /\d+/ }
|
43
|
+
Success(numbers: numbers.map(&:to_i))
|
44
|
+
else
|
45
|
+
Failure(numbers: 'must contain only numeric types')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Add2 < Micro::Service::Strict
|
51
|
+
attribute :numbers
|
52
|
+
|
53
|
+
def call!
|
54
|
+
Success(numbers: numbers.map { |number| number + 2 })
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Add2ToAllNumbers = ConvertToNumbers >> Add2
|
59
|
+
end
|
60
|
+
|
61
|
+
module IT
|
62
|
+
class ConvertToNumbers
|
63
|
+
include Interactor
|
64
|
+
|
65
|
+
def call
|
66
|
+
numbers = context.numbers
|
67
|
+
|
68
|
+
if numbers.all? { |value| String(value) =~ /\d+/ }
|
69
|
+
context.numbers = numbers.map(&:to_i)
|
70
|
+
else
|
71
|
+
context.fail! numbers: 'must contain only numeric types'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Add2
|
77
|
+
include Interactor
|
78
|
+
|
79
|
+
def call
|
80
|
+
numbers = context.numbers
|
81
|
+
|
82
|
+
context.numbers = numbers.map { |number| number + 2 }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class Add2ToAllNumbers
|
87
|
+
include Interactor::Organizer
|
88
|
+
|
89
|
+
organize ConvertToNumbers, Add2
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
NUMBERS = {numbers: %w[1 1 2 2 3 4]}
|
94
|
+
|
95
|
+
Benchmark.ips do |x|
|
96
|
+
x.config(:time => 5, :warmup => 2)
|
97
|
+
|
98
|
+
x.time = 5
|
99
|
+
x.warmup = 2
|
100
|
+
|
101
|
+
x.report('Pipeline of Micro::Service::Base') do
|
102
|
+
MSB::Add2ToAllNumbers.call(NUMBERS)
|
103
|
+
end
|
104
|
+
|
105
|
+
x.report('Pipeline of Micro::Service::Strict') do
|
106
|
+
MSS::Add2ToAllNumbers.call(NUMBERS)
|
107
|
+
end
|
108
|
+
|
109
|
+
x.report('Interactor::Organizer') do
|
110
|
+
IT::Add2ToAllNumbers.call(NUMBERS)
|
111
|
+
end
|
112
|
+
|
113
|
+
x.compare!
|
114
|
+
end
|
115
|
+
|
116
|
+
# Warming up --------------------------------------
|
117
|
+
# Pipeline of Micro::Service::Base
|
118
|
+
# 3.578k i/100ms
|
119
|
+
# Pipeline of Micro::Service::Strict
|
120
|
+
# 3.177k i/100ms
|
121
|
+
# Interactor::Organizer
|
122
|
+
# 4.695k i/100ms
|
123
|
+
# Calculating -------------------------------------
|
124
|
+
# Pipeline of Micro::Service::Base
|
125
|
+
# 36.087k (± 6.9%) i/s - 182.478k in 5.084835s
|
126
|
+
# Pipeline of Micro::Service::Strict
|
127
|
+
# 31.329k (± 6.7%) i/s - 158.850k in 5.094012s
|
128
|
+
# Interactor::Organizer
|
129
|
+
# 46.294k (± 6.6%) i/s - 234.750k in 5.093117s
|
130
|
+
|
131
|
+
# Comparison:
|
132
|
+
# Interactor::Organizer: 46293.6 i/s
|
133
|
+
# Pipeline of Micro::Service::Base: 36086.5 i/s - 1.28x slower
|
134
|
+
# Pipeline of Micro::Service::Strict: 31328.5 i/s - 1.48x slower
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'bundler/inline'
|
2
|
+
|
3
|
+
gemfile do
|
4
|
+
source 'https://rubygems.org'
|
5
|
+
|
6
|
+
gem 'benchmark-ips', '~> 2.7', '>= 2.7.2'
|
7
|
+
gem 'interactor', '~> 3.1', '>= 3.1.1'
|
8
|
+
gem 'u-service', '~> 0.11.0'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'benchmark/ips'
|
12
|
+
|
13
|
+
class MSB_Multiply < Micro::Service::Base
|
14
|
+
attributes :a, :b
|
15
|
+
|
16
|
+
def call!
|
17
|
+
if a.is_a?(Numeric) && b.is_a?(Numeric)
|
18
|
+
Success(a * b)
|
19
|
+
else
|
20
|
+
Failure(:invalid_data)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class MSS_Multiply < Micro::Service::Strict
|
26
|
+
attributes :a, :b
|
27
|
+
|
28
|
+
def call!
|
29
|
+
if a.is_a?(Numeric) && b.is_a?(Numeric)
|
30
|
+
Success(a * b)
|
31
|
+
else
|
32
|
+
Failure(:invalid_data)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class IT_Multiply
|
38
|
+
include Interactor
|
39
|
+
|
40
|
+
def call
|
41
|
+
a = context.a
|
42
|
+
b = context.b
|
43
|
+
|
44
|
+
if a.is_a?(Numeric) && b.is_a?(Numeric)
|
45
|
+
context.number = a * b
|
46
|
+
else
|
47
|
+
context.fail!(type: :invalid_data)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
SYMBOL_KEYS = { a: nil, b: 2 }
|
53
|
+
STRING_KEYS = { 'a' => 1, 'b' => '' }
|
54
|
+
|
55
|
+
Benchmark.ips do |x|
|
56
|
+
x.config(:time => 5, :warmup => 2)
|
57
|
+
|
58
|
+
x.time = 5
|
59
|
+
x.warmup = 2
|
60
|
+
|
61
|
+
x.report('Micro::Service::Base') do
|
62
|
+
MSB_Multiply.call(SYMBOL_KEYS)
|
63
|
+
MSB_Multiply.call(STRING_KEYS)
|
64
|
+
end
|
65
|
+
|
66
|
+
x.report('Micro::Service::Strict') do
|
67
|
+
MSS_Multiply.call(SYMBOL_KEYS)
|
68
|
+
MSS_Multiply.call(STRING_KEYS)
|
69
|
+
end
|
70
|
+
|
71
|
+
x.report('Interactor') do
|
72
|
+
IT_Multiply.call(SYMBOL_KEYS)
|
73
|
+
IT_Multiply.call(STRING_KEYS)
|
74
|
+
end
|
75
|
+
|
76
|
+
x.compare!
|
77
|
+
end
|
78
|
+
|
79
|
+
# Warming up --------------------------------------
|
80
|
+
# Micro::Service::Base 5.304k i/100ms
|
81
|
+
# Micro::Service::Strict
|
82
|
+
# 4.516k i/100ms
|
83
|
+
# Interactor 1.507k i/100ms
|
84
|
+
# Calculating -------------------------------------
|
85
|
+
# Micro::Service::Base 54.444k (± 2.8%) i/s - 275.808k in 5.070215s
|
86
|
+
# Micro::Service::Strict
|
87
|
+
# 45.996k (± 1.8%) i/s - 230.316k in 5.008931s
|
88
|
+
# Interactor 15.363k (± 2.2%) i/s - 76.857k in 5.005209s
|
89
|
+
|
90
|
+
# Comparison:
|
91
|
+
# Micro::Service::Base: 54444.5 i/s
|
92
|
+
# Micro::Service::Strict: 45995.8 i/s - 1.18x slower
|
93
|
+
# Interactor: 15363.0 i/s - 3.54x slower
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'bundler/inline'
|
2
|
+
|
3
|
+
gemfile do
|
4
|
+
source 'https://rubygems.org'
|
5
|
+
|
6
|
+
gem 'benchmark-ips', '~> 2.7', '>= 2.7.2'
|
7
|
+
gem 'interactor', '~> 3.1', '>= 3.1.1'
|
8
|
+
gem 'u-service', '~> 0.11.0'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'benchmark/ips'
|
12
|
+
|
13
|
+
class MSB_Multiply < Micro::Service::Base
|
14
|
+
attributes :a, :b
|
15
|
+
|
16
|
+
def call!
|
17
|
+
if a.is_a?(Numeric) && b.is_a?(Numeric)
|
18
|
+
Success(a * b)
|
19
|
+
else
|
20
|
+
Failure(:invalid_data)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class MSS_Multiply < Micro::Service::Strict
|
26
|
+
attributes :a, :b
|
27
|
+
|
28
|
+
def call!
|
29
|
+
if a.is_a?(Numeric) && b.is_a?(Numeric)
|
30
|
+
Success(a * b)
|
31
|
+
else
|
32
|
+
Failure(:invalid_data)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class IT_Multiply
|
38
|
+
include Interactor
|
39
|
+
|
40
|
+
def call
|
41
|
+
a = context.a
|
42
|
+
b = context.b
|
43
|
+
|
44
|
+
if a.is_a?(Numeric) && b.is_a?(Numeric)
|
45
|
+
context.number = a * b
|
46
|
+
else
|
47
|
+
context.fail!(:invalid_data)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
SYMBOL_KEYS = { a: 2, b: 2 }
|
53
|
+
STRING_KEYS = { 'a' => 1, 'b' => 1 }
|
54
|
+
|
55
|
+
Benchmark.ips do |x|
|
56
|
+
x.config(:time => 5, :warmup => 2)
|
57
|
+
|
58
|
+
x.time = 5
|
59
|
+
x.warmup = 2
|
60
|
+
|
61
|
+
x.report('Micro::Service::Base') do
|
62
|
+
MSB_Multiply.call(SYMBOL_KEYS)
|
63
|
+
MSB_Multiply.call(STRING_KEYS)
|
64
|
+
end
|
65
|
+
|
66
|
+
x.report('Micro::Service::Strict') do
|
67
|
+
MSS_Multiply.call(SYMBOL_KEYS)
|
68
|
+
MSS_Multiply.call(STRING_KEYS)
|
69
|
+
end
|
70
|
+
|
71
|
+
x.report('Interactor') do
|
72
|
+
IT_Multiply.call(SYMBOL_KEYS)
|
73
|
+
IT_Multiply.call(STRING_KEYS)
|
74
|
+
end
|
75
|
+
|
76
|
+
x.compare!
|
77
|
+
end
|
78
|
+
|
79
|
+
# Warming up --------------------------------------
|
80
|
+
# Micro::Service::Base 5.365k i/100ms
|
81
|
+
# Micro::Service::Strict
|
82
|
+
# 4.535k i/100ms
|
83
|
+
# Interactor 2.620k i/100ms
|
84
|
+
# Calculating -------------------------------------
|
85
|
+
# Micro::Service::Base 51.795k (± 4.7%) i/s - 262.885k in 5.086671s
|
86
|
+
# Micro::Service::Strict
|
87
|
+
# 46.253k (± 1.6%) i/s - 231.285k in 5.001748s
|
88
|
+
# Interactor 29.561k (± 3.3%) i/s - 149.340k in 5.057720s
|
89
|
+
|
90
|
+
# Comparison:
|
91
|
+
# Micro::Service::Base: 51794.5 i/s
|
92
|
+
# Micro::Service::Strict: 46253.0 i/s - 1.12x slower
|
93
|
+
# Interactor: 29561.5 i/s - 1.75x slower
|
data/lib/micro/service.rb
CHANGED
@@ -5,10 +5,6 @@ require 'micro/attributes'
|
|
5
5
|
require 'micro/service/version'
|
6
6
|
|
7
7
|
require 'micro/service/result'
|
8
|
-
require 'micro/service/result/success'
|
9
|
-
require 'micro/service/result/failure'
|
10
|
-
require 'micro/service/result/helpers'
|
11
|
-
|
12
8
|
require 'micro/service/base'
|
13
9
|
require 'micro/service/strict'
|
14
10
|
require 'micro/service/pipeline'
|
data/lib/micro/service/base.rb
CHANGED
@@ -4,10 +4,13 @@ module Micro
|
|
4
4
|
module Service
|
5
5
|
class Base
|
6
6
|
include Micro::Attributes.without(:strict_initialize)
|
7
|
-
include Result::Helpers
|
8
7
|
|
9
8
|
INVALID_RESULT = '#call! must return a Micro::Service::Result instance'.freeze
|
10
9
|
|
10
|
+
ResultIsAlreadyDefined = ArgumentError.new('result is already defined'.freeze)
|
11
|
+
|
12
|
+
private_constant :INVALID_RESULT, :ResultIsAlreadyDefined
|
13
|
+
|
11
14
|
def self.>>(service)
|
12
15
|
Micro::Service::Pipeline[self, service]
|
13
16
|
end
|
@@ -16,6 +19,13 @@ module Micro
|
|
16
19
|
new(options).call
|
17
20
|
end
|
18
21
|
|
22
|
+
def self.__new__(result, arg)
|
23
|
+
instance = allocate
|
24
|
+
instance.__set_result__(result)
|
25
|
+
instance.send(:initialize, arg)
|
26
|
+
instance
|
27
|
+
end
|
28
|
+
|
19
29
|
def call!
|
20
30
|
raise NotImplementedError
|
21
31
|
end
|
@@ -25,6 +35,27 @@ module Micro
|
|
25
35
|
return result if result.is_a?(Service::Result)
|
26
36
|
raise TypeError, self.class.name + INVALID_RESULT
|
27
37
|
end
|
38
|
+
|
39
|
+
def __set_result__(result)
|
40
|
+
raise ResultIsAlreadyDefined if @__result
|
41
|
+
@__result = result
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def __get_result__
|
47
|
+
@__result ||= Result.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def Success(arg=nil)
|
51
|
+
value, type = block_given? ? [yield, arg] : [arg, nil]
|
52
|
+
__get_result__.__set__(true, value, type)
|
53
|
+
end
|
54
|
+
|
55
|
+
def Failure(arg=nil)
|
56
|
+
value, type = block_given? ? [yield, arg] : [arg, nil]
|
57
|
+
__get_result__.__set__(false, value, type)
|
58
|
+
end
|
28
59
|
end
|
29
60
|
end
|
30
61
|
end
|
@@ -6,8 +6,9 @@ module Micro
|
|
6
6
|
class Reducer
|
7
7
|
attr_reader :services
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
InvalidServices = ArgumentError.new('argument must be a collection of `Micro::Service::Base` classes'.freeze)
|
10
|
+
|
11
|
+
private_constant :InvalidServices
|
11
12
|
|
12
13
|
def self.map_services(arg)
|
13
14
|
return arg.services if arg.is_a?(Reducer)
|
@@ -18,7 +19,7 @@ module Micro
|
|
18
19
|
def self.build(args)
|
19
20
|
services = Array(args).flat_map { |arg| map_services(arg) }
|
20
21
|
|
21
|
-
raise
|
22
|
+
raise InvalidServices if services.any? { |klass| !(klass < ::Micro::Service::Base) }
|
22
23
|
|
23
24
|
new(services)
|
24
25
|
end
|
@@ -30,7 +31,7 @@ module Micro
|
|
30
31
|
def call(arg={})
|
31
32
|
@services.reduce(initial_result(arg)) do |result, service|
|
32
33
|
break result if result.failure?
|
33
|
-
service.
|
34
|
+
service.__new__(result, result.value).call
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
@@ -43,8 +44,8 @@ module Micro
|
|
43
44
|
def initial_result(arg)
|
44
45
|
return arg.call if arg_to_call?(arg)
|
45
46
|
return arg if arg.is_a?(Micro::Service::Result)
|
46
|
-
|
47
|
-
|
47
|
+
result = Micro::Service::Result.new
|
48
|
+
result.__set__(true, arg, nil)
|
48
49
|
end
|
49
50
|
|
50
51
|
def arg_to_call?(arg)
|
@@ -74,9 +75,9 @@ module Micro
|
|
74
75
|
Reducer.build(args)
|
75
76
|
end
|
76
77
|
|
77
|
-
|
78
|
+
UndefinedPipeline = ArgumentError.new("This class hasn't declared its pipeline. Please, use the `pipeline()` macro to define one.".freeze)
|
78
79
|
|
79
|
-
private_constant :
|
80
|
+
private_constant :UndefinedPipeline
|
80
81
|
|
81
82
|
def self.included(base)
|
82
83
|
base.extend(ClassMethods)
|
@@ -84,7 +85,7 @@ module Micro
|
|
84
85
|
def initialize(options)
|
85
86
|
@options = options
|
86
87
|
pipeline = self.class.__pipeline__
|
87
|
-
raise
|
88
|
+
raise UndefinedPipeline unless pipeline
|
88
89
|
end
|
89
90
|
RUBY
|
90
91
|
end
|
data/lib/micro/service/result.rb
CHANGED
@@ -3,27 +3,20 @@
|
|
3
3
|
module Micro
|
4
4
|
module Service
|
5
5
|
class Result
|
6
|
-
|
7
|
-
INVALID = 'type must be nil or a symbol'.freeze
|
6
|
+
InvalidType = TypeError.new('type must be nil or a symbol'.freeze)
|
8
7
|
|
9
|
-
|
10
|
-
return arg if arg.nil? || arg.is_a?(Symbol)
|
11
|
-
raise TypeError, INVALID
|
12
|
-
end
|
13
|
-
end
|
8
|
+
attr_reader :value, :type
|
14
9
|
|
15
|
-
|
10
|
+
def __set__(is_success, value, type)
|
11
|
+
raise InvalidType unless type.nil? || type.is_a?(Symbol)
|
16
12
|
|
17
|
-
|
13
|
+
@success, @value, @type = is_success, value, type
|
18
14
|
|
19
|
-
|
20
|
-
new(value: value, type: Type[type])
|
15
|
+
self
|
21
16
|
end
|
22
17
|
|
23
|
-
attributes :type, :value
|
24
|
-
|
25
18
|
def success?
|
26
|
-
|
19
|
+
@success
|
27
20
|
end
|
28
21
|
|
29
22
|
def failure?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: u-service
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo Serradura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: u-attributes
|
@@ -68,6 +68,10 @@ files:
|
|
68
68
|
- LICENSE.txt
|
69
69
|
- README.md
|
70
70
|
- Rakefile
|
71
|
+
- benchmarks/interactor/pipeline_failure.rb
|
72
|
+
- benchmarks/interactor/pipeline_success.rb
|
73
|
+
- benchmarks/interactor/service_failure.rb
|
74
|
+
- benchmarks/interactor/service_success.rb
|
71
75
|
- bin/console
|
72
76
|
- bin/setup
|
73
77
|
- comparisons/interactor.rb
|
@@ -76,9 +80,6 @@ files:
|
|
76
80
|
- lib/micro/service/base.rb
|
77
81
|
- lib/micro/service/pipeline.rb
|
78
82
|
- lib/micro/service/result.rb
|
79
|
-
- lib/micro/service/result/failure.rb
|
80
|
-
- lib/micro/service/result/helpers.rb
|
81
|
-
- lib/micro/service/result/success.rb
|
82
83
|
- lib/micro/service/strict.rb
|
83
84
|
- lib/micro/service/version.rb
|
84
85
|
- lib/micro/service/with_validation.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Micro
|
4
|
-
module Service
|
5
|
-
class Result
|
6
|
-
module Helpers
|
7
|
-
private def Success(arg=nil)
|
8
|
-
value, type = block_given? ? [yield, arg] : [arg, nil]
|
9
|
-
Result::Success[value: value, type: type]
|
10
|
-
end
|
11
|
-
|
12
|
-
private def Failure(arg=nil)
|
13
|
-
value, type = block_given? ? [yield, arg] : [arg, nil]
|
14
|
-
Result::Failure[value: value, type: type]
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|