attr-gather 1.0.0 → 1.2.0
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/.github/dependabot.yml +7 -0
- data/.github/mergify.yml +19 -0
- data/.github/workflows/deploy.yml +1 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +47 -42
- data/Rakefile +20 -6
- data/attr-gather.gemspec +1 -1
- data/lib/attr/gather/aggregators.rb +4 -4
- data/lib/attr/gather/aggregators/base.rb +11 -9
- data/lib/attr/gather/aggregators/deep_merge.rb +6 -3
- data/lib/attr/gather/aggregators/shallow_merge.rb +2 -4
- data/lib/attr/gather/concerns/registrable.rb +2 -2
- data/lib/attr/gather/version.rb +1 -1
- data/lib/attr/gather/workflow/callable.rb +16 -22
- data/lib/attr/gather/workflow/dsl.rb +21 -17
- data/lib/attr/gather/workflow/task.rb +15 -2
- data/lib/attr/gather/workflow/task_graph.rb +14 -2
- metadata +6 -7
- data/lib/attr/gather/workflow/async_task_executor.rb +0 -17
- data/lib/attr/gather/workflow/task_execution_result.rb +0 -58
- data/lib/attr/gather/workflow/task_executor.rb +0 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ee9b30fd44bd8931964b53b904815224fa6a5a592ac1f22d19605a982a326d42
|
|
4
|
+
data.tar.gz: 7954a71a61dc89266358909ce189312b3b3164e4092d62ae4fae973712efca9d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 040b490aba781f8f851b617a365d2aea061f9d2afb189bcdf4e0e086effebc2135109a648b0f116d4be7000cbe4d3e10e369fadcb38d9e2910114c36957cce68
|
|
7
|
+
data.tar.gz: 59a93d0d6e16f9b2433822c4faf7ef4cda25f3e9e37da8a5fae816e313e1d6e0b86906a1d652b3c64125eae888607c9117ade38fc17ff11b84c361add21f4c62
|
data/.github/mergify.yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
pull_request_rules:
|
|
3
|
+
- name: Automatic approval for Dependabot pull requests
|
|
4
|
+
conditions:
|
|
5
|
+
- author~=^dependabot(|-preview)\[bot\]$
|
|
6
|
+
- "check-success=build-test-lint"
|
|
7
|
+
actions:
|
|
8
|
+
review:
|
|
9
|
+
type: APPROVE
|
|
10
|
+
message: ✅ Auto-approved passing Dependabot PR with [Mergify.io](https://doc.mergify.io/actions.html#review)
|
|
11
|
+
|
|
12
|
+
- name: Automatic merge for Dependabot pull requests
|
|
13
|
+
conditions:
|
|
14
|
+
- author~=^dependabot(|-preview)\[bot\]$
|
|
15
|
+
- "#approved-reviews-by>=1"
|
|
16
|
+
- "check-success=build-test-lint"
|
|
17
|
+
actions:
|
|
18
|
+
merge:
|
|
19
|
+
method: squash
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
attr-gather (1.
|
|
4
|
+
attr-gather (1.2.0)
|
|
5
5
|
dry-container (~> 0.7)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
@@ -9,80 +9,83 @@ GEM
|
|
|
9
9
|
specs:
|
|
10
10
|
addressable (2.7.0)
|
|
11
11
|
public_suffix (>= 2.0.2, < 5.0)
|
|
12
|
-
ast (2.4.
|
|
12
|
+
ast (2.4.1)
|
|
13
13
|
backport (1.1.2)
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
benchmark (0.1.0)
|
|
15
|
+
coderay (1.1.3)
|
|
16
|
+
concurrent-ruby (1.1.7)
|
|
16
17
|
diff-lcs (1.3)
|
|
17
18
|
domain_name (0.5.20190701)
|
|
18
19
|
unf (>= 0.0.5, < 1.0.0)
|
|
19
|
-
dry-configurable (0.
|
|
20
|
+
dry-configurable (0.11.6)
|
|
20
21
|
concurrent-ruby (~> 1.0)
|
|
21
22
|
dry-core (~> 0.4, >= 0.4.7)
|
|
23
|
+
dry-equalizer (~> 0.2)
|
|
22
24
|
dry-container (0.7.2)
|
|
23
25
|
concurrent-ruby (~> 1.0)
|
|
24
26
|
dry-configurable (~> 0.1, >= 0.1.3)
|
|
25
27
|
dry-core (0.4.9)
|
|
26
28
|
concurrent-ruby (~> 1.0)
|
|
27
|
-
dry-equalizer (0.
|
|
29
|
+
dry-equalizer (0.3.0)
|
|
28
30
|
dry-inflector (0.2.0)
|
|
29
|
-
dry-initializer (3.0.
|
|
30
|
-
dry-logic (1.0.
|
|
31
|
+
dry-initializer (3.0.4)
|
|
32
|
+
dry-logic (1.0.8)
|
|
31
33
|
concurrent-ruby (~> 1.0)
|
|
32
34
|
dry-core (~> 0.2)
|
|
33
35
|
dry-equalizer (~> 0.2)
|
|
34
|
-
dry-schema (1.
|
|
36
|
+
dry-schema (1.5.5)
|
|
35
37
|
concurrent-ruby (~> 1.0)
|
|
36
38
|
dry-configurable (~> 0.8, >= 0.8.3)
|
|
37
39
|
dry-core (~> 0.4)
|
|
38
40
|
dry-equalizer (~> 0.2)
|
|
39
41
|
dry-initializer (~> 3.0)
|
|
40
42
|
dry-logic (~> 1.0)
|
|
41
|
-
dry-types (~> 1.
|
|
42
|
-
dry-types (1.
|
|
43
|
+
dry-types (~> 1.4)
|
|
44
|
+
dry-types (1.4.0)
|
|
43
45
|
concurrent-ruby (~> 1.0)
|
|
44
46
|
dry-container (~> 0.3)
|
|
45
47
|
dry-core (~> 0.4, >= 0.4.4)
|
|
46
|
-
dry-equalizer (~> 0.
|
|
48
|
+
dry-equalizer (~> 0.3)
|
|
47
49
|
dry-inflector (~> 0.1, >= 0.1.2)
|
|
48
50
|
dry-logic (~> 1.0, >= 1.0.2)
|
|
49
|
-
dry-validation (1.
|
|
51
|
+
dry-validation (1.5.6)
|
|
50
52
|
concurrent-ruby (~> 1.0)
|
|
51
53
|
dry-container (~> 0.7, >= 0.7.1)
|
|
52
54
|
dry-core (~> 0.4)
|
|
53
55
|
dry-equalizer (~> 0.2)
|
|
54
56
|
dry-initializer (~> 3.0)
|
|
55
|
-
dry-schema (~> 1.
|
|
56
|
-
|
|
57
|
+
dry-schema (~> 1.5, >= 1.5.2)
|
|
58
|
+
e2mmap (0.1.0)
|
|
59
|
+
ffi (1.13.1)
|
|
57
60
|
ffi-compiler (1.0.1)
|
|
58
61
|
ffi (>= 1.0.0)
|
|
59
62
|
rake
|
|
60
|
-
|
|
61
|
-
http (4.2.0)
|
|
63
|
+
http (4.4.1)
|
|
62
64
|
addressable (~> 2.3)
|
|
63
65
|
http-cookie (~> 1.0)
|
|
64
|
-
http-form_data (~> 2.
|
|
66
|
+
http-form_data (~> 2.2)
|
|
65
67
|
http-parser (~> 1.2.0)
|
|
66
68
|
http-cookie (1.0.3)
|
|
67
69
|
domain_name (~> 0.5)
|
|
68
|
-
http-form_data (2.
|
|
70
|
+
http-form_data (2.3.0)
|
|
69
71
|
http-parser (1.2.1)
|
|
70
72
|
ffi-compiler (>= 1.0, < 2.0)
|
|
71
|
-
jaro_winkler (1.5.
|
|
72
|
-
|
|
73
|
+
jaro_winkler (1.5.4)
|
|
74
|
+
maruku (0.7.3)
|
|
75
|
+
method_source (1.0.0)
|
|
73
76
|
mini_portile2 (2.4.0)
|
|
74
|
-
nokogiri (1.10.
|
|
77
|
+
nokogiri (1.10.10)
|
|
75
78
|
mini_portile2 (~> 2.4.0)
|
|
76
|
-
parallel (1.
|
|
77
|
-
parser (2.
|
|
78
|
-
ast (~> 2.4.
|
|
79
|
-
pry (0.
|
|
80
|
-
coderay (~> 1.1
|
|
81
|
-
method_source (~>
|
|
82
|
-
public_suffix (4.0.
|
|
79
|
+
parallel (1.19.2)
|
|
80
|
+
parser (2.7.2.0)
|
|
81
|
+
ast (~> 2.4.1)
|
|
82
|
+
pry (0.13.1)
|
|
83
|
+
coderay (~> 1.1)
|
|
84
|
+
method_source (~> 1.0)
|
|
85
|
+
public_suffix (4.0.6)
|
|
83
86
|
rainbow (3.0.0)
|
|
84
|
-
rake (
|
|
85
|
-
reverse_markdown (
|
|
87
|
+
rake (13.0.1)
|
|
88
|
+
reverse_markdown (2.0.0)
|
|
86
89
|
nokogiri
|
|
87
90
|
rspec (3.9.0)
|
|
88
91
|
rspec-core (~> 3.9.0)
|
|
@@ -107,25 +110,27 @@ GEM
|
|
|
107
110
|
rubocop-performance (1.5.1)
|
|
108
111
|
rubocop (>= 0.71.0)
|
|
109
112
|
ruby-progressbar (1.10.1)
|
|
110
|
-
solargraph (0.
|
|
113
|
+
solargraph (0.39.17)
|
|
111
114
|
backport (~> 1.1)
|
|
115
|
+
benchmark
|
|
112
116
|
bundler (>= 1.17.2)
|
|
113
|
-
|
|
117
|
+
e2mmap
|
|
114
118
|
jaro_winkler (~> 1.5)
|
|
119
|
+
maruku (~> 0.7, >= 0.7.3)
|
|
115
120
|
nokogiri (~> 1.9, >= 1.9.1)
|
|
116
121
|
parser (~> 2.3)
|
|
117
|
-
reverse_markdown (
|
|
122
|
+
reverse_markdown (>= 1.0.5, < 3)
|
|
118
123
|
rubocop (~> 0.52)
|
|
119
|
-
thor (~>
|
|
124
|
+
thor (~> 1.0)
|
|
120
125
|
tilt (~> 2.0)
|
|
121
|
-
yard (~> 0.9)
|
|
122
|
-
thor (0.
|
|
126
|
+
yard (~> 0.9, >= 0.9.24)
|
|
127
|
+
thor (1.0.1)
|
|
123
128
|
tilt (2.0.10)
|
|
124
129
|
unf (0.1.4)
|
|
125
130
|
unf_ext
|
|
126
|
-
unf_ext (0.0.7.
|
|
127
|
-
unicode-display_width (1.6.
|
|
128
|
-
yard (0.9.
|
|
131
|
+
unf_ext (0.0.7.7)
|
|
132
|
+
unicode-display_width (1.6.1)
|
|
133
|
+
yard (0.9.25)
|
|
129
134
|
|
|
130
135
|
PLATFORMS
|
|
131
136
|
ruby
|
|
@@ -133,10 +138,10 @@ PLATFORMS
|
|
|
133
138
|
DEPENDENCIES
|
|
134
139
|
attr-gather!
|
|
135
140
|
bundler (~> 2.0)
|
|
136
|
-
dry-validation (~> 1.
|
|
141
|
+
dry-validation (~> 1.5)
|
|
137
142
|
http
|
|
138
143
|
pry
|
|
139
|
-
rake (~>
|
|
144
|
+
rake (~> 13.0)
|
|
140
145
|
rspec (~> 3.0)
|
|
141
146
|
rubocop
|
|
142
147
|
rubocop-performance
|
data/Rakefile
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'bundler/gem_tasks'
|
|
4
|
-
require 'rspec/core/rake_task'
|
|
5
|
-
require 'rubocop/rake_task'
|
|
6
|
-
require 'yard'
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
begin
|
|
6
|
+
require 'rspec/core/rake_task'
|
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
8
|
+
rescue LoadError
|
|
9
|
+
warn 'Could not load rspec rake task'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
begin
|
|
13
|
+
require 'rubocop/rake_task'
|
|
14
|
+
RuboCop::RakeTask.new(:lint)
|
|
15
|
+
rescue LoadError
|
|
16
|
+
warn 'Could not load rubocop rake task'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
begin
|
|
20
|
+
require 'yard'
|
|
21
|
+
YARD::Rake::YardocTask.new(:doc)
|
|
22
|
+
rescue LoadError
|
|
23
|
+
warn 'Could not load yarddoc rake task'
|
|
24
|
+
end
|
|
11
25
|
|
|
12
26
|
task default: %i[spec lint]
|
|
13
27
|
|
data/attr-gather.gemspec
CHANGED
|
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
|
31
31
|
spec.require_paths = ['lib']
|
|
32
32
|
|
|
33
33
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
34
|
-
spec.add_development_dependency 'rake', '~>
|
|
34
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
35
35
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
36
36
|
|
|
37
37
|
spec.add_dependency 'dry-container', '~> 0.7'
|
|
@@ -15,16 +15,16 @@ module Attr
|
|
|
15
15
|
@default = resolve(:deep_merge)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
register(:deep_merge) do |*args|
|
|
18
|
+
register(:deep_merge) do |*args, **opts|
|
|
19
19
|
require 'attr/gather/aggregators/deep_merge'
|
|
20
20
|
|
|
21
|
-
DeepMerge.new(*args)
|
|
21
|
+
DeepMerge.new(*args, **opts)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
register(:shallow_merge) do |*args|
|
|
24
|
+
register(:shallow_merge) do |*args, **opts|
|
|
25
25
|
require 'attr/gather/aggregators/shallow_merge'
|
|
26
26
|
|
|
27
|
-
ShallowMerge.new(*args)
|
|
27
|
+
ShallowMerge.new(*args, **opts)
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'attr/gather/filters/noop'
|
|
4
|
+
|
|
3
5
|
module Attr
|
|
4
6
|
module Gather
|
|
5
7
|
module Aggregators
|
|
@@ -11,8 +13,14 @@ module Attr
|
|
|
11
13
|
class Base
|
|
12
14
|
attr_accessor :filter
|
|
13
15
|
|
|
16
|
+
NOOP_FILTER ||= Filters::Noop.new
|
|
17
|
+
|
|
14
18
|
def initialize(**opts)
|
|
15
|
-
@filter = opts.delete(:filter)
|
|
19
|
+
@filter = opts.delete(:filter) || NOOP_FILTER
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def with(**opts)
|
|
23
|
+
self.class.new(filter: @filter, **opts)
|
|
16
24
|
end
|
|
17
25
|
|
|
18
26
|
def call(_original_input, _results_array)
|
|
@@ -21,16 +29,10 @@ module Attr
|
|
|
21
29
|
|
|
22
30
|
private
|
|
23
31
|
|
|
24
|
-
def wrap_result(result)
|
|
25
|
-
Concurrent::Promise.fulfill(result)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
32
|
def unwrap_result(res)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return unvalidated if filter.nil?
|
|
33
|
+
return res if filter.nil?
|
|
32
34
|
|
|
33
|
-
filter.call(
|
|
35
|
+
filter.call(res).value
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
end
|
|
@@ -21,16 +21,19 @@ module Attr
|
|
|
21
21
|
|
|
22
22
|
def call(input, execution_results)
|
|
23
23
|
execution_results = execution_results.reverse_each if reverse?
|
|
24
|
+
initial = unwrap_initial_input(input)
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
execution_results.reduce(initial) do |memo, res|
|
|
26
27
|
deep_merge(memo, unwrap_result(res))
|
|
27
28
|
end
|
|
28
|
-
|
|
29
|
-
wrap_result(result)
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
private
|
|
33
32
|
|
|
33
|
+
def unwrap_initial_input(input)
|
|
34
|
+
input
|
|
35
|
+
end
|
|
36
|
+
|
|
34
37
|
def reverse?
|
|
35
38
|
@reverse
|
|
36
39
|
end
|
|
@@ -20,13 +20,11 @@ module Attr
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def call(input, execution_results)
|
|
23
|
-
|
|
23
|
+
execution_results = execution_results.reverse_each if reverse?
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
execution_results.reduce(input) do |memo, res|
|
|
26
26
|
memo.merge(unwrap_result(res))
|
|
27
27
|
end
|
|
28
|
-
|
|
29
|
-
wrap_result(result)
|
|
30
28
|
end
|
|
31
29
|
|
|
32
30
|
private
|
|
@@ -29,13 +29,13 @@ module Attr
|
|
|
29
29
|
# @param name [Symbol]
|
|
30
30
|
#
|
|
31
31
|
# @return [#call]
|
|
32
|
-
def resolve(name, *args)
|
|
32
|
+
def resolve(name, *args, **opts)
|
|
33
33
|
block = @__storage__.fetch(name) do
|
|
34
34
|
raise NotFoundError,
|
|
35
35
|
"no item with name #{name} registered"
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
block.call(*args)
|
|
38
|
+
block.call(*args, **opts)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
# @api private
|
data/lib/attr/gather/version.rb
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'attr/gather/workflow/task_executor'
|
|
4
|
-
require 'attr/gather/workflow/async_task_executor'
|
|
5
|
-
|
|
6
3
|
module Attr
|
|
7
4
|
module Gather
|
|
8
5
|
module Workflow
|
|
@@ -21,42 +18,39 @@ module Attr
|
|
|
21
18
|
#
|
|
22
19
|
# @param input [Hash]
|
|
23
20
|
#
|
|
24
|
-
# @return [Concurrent::Promise]
|
|
21
|
+
# @return [Concurrent::Promise<Hash>]
|
|
25
22
|
#
|
|
26
23
|
# @note For more information, check out {https://dry-rb.org/gems/dry-monads/1.0/result}
|
|
27
24
|
#
|
|
28
25
|
# @api public
|
|
29
26
|
def call(input)
|
|
30
|
-
|
|
27
|
+
task_promises = {}
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
final_results << executor_results
|
|
35
|
-
aggregator.call(aggregated_input, executor_results).value!
|
|
29
|
+
final_results = self.class.tasks.to_a.map do |task|
|
|
30
|
+
task_promises[task] = execute_task(input, task, task_promises)
|
|
36
31
|
end
|
|
37
32
|
|
|
38
|
-
|
|
33
|
+
Concurrent::Promise.zip(*final_results).then do |results|
|
|
34
|
+
aggregator.call(input, results)
|
|
35
|
+
end
|
|
39
36
|
end
|
|
40
37
|
|
|
41
38
|
private
|
|
42
39
|
|
|
43
|
-
# Enumator for task batches
|
|
44
|
-
#
|
|
45
|
-
# @return [Enumerator]
|
|
46
|
-
#
|
|
47
|
-
# @api private
|
|
48
|
-
def each_task_batch
|
|
49
|
-
self.class.tasks.each_batch
|
|
50
|
-
end
|
|
51
|
-
|
|
52
40
|
# Executes a batch of tasks
|
|
53
41
|
#
|
|
54
42
|
# @return [Array<TaskExecutionResult>]
|
|
55
43
|
#
|
|
56
44
|
# @api private
|
|
57
|
-
def
|
|
58
|
-
|
|
59
|
-
|
|
45
|
+
def execute_task(initial_input, task, task_promises)
|
|
46
|
+
task_proc = container.resolve(task.name)
|
|
47
|
+
dep_promises = task.depends_on.map { |t| task_promises[t] }
|
|
48
|
+
input_promise = Concurrent::Promise.zip(*dep_promises)
|
|
49
|
+
|
|
50
|
+
input_promise.then do |results|
|
|
51
|
+
dep_input = aggregator.call(initial_input, results)
|
|
52
|
+
task_proc.call(dep_input)
|
|
53
|
+
end
|
|
60
54
|
end
|
|
61
55
|
|
|
62
56
|
# @api private
|
|
@@ -36,9 +36,9 @@ module Attr
|
|
|
36
36
|
#
|
|
37
37
|
# @api public
|
|
38
38
|
def task(task_name, opts = EMPTY_HASH)
|
|
39
|
-
|
|
40
|
-
yield
|
|
41
|
-
tasks <<
|
|
39
|
+
conf = OpenStruct.new
|
|
40
|
+
yield conf
|
|
41
|
+
tasks << Hash[name: task_name, **opts, **conf.to_h]
|
|
42
42
|
self
|
|
43
43
|
end
|
|
44
44
|
|
|
@@ -88,13 +88,13 @@ module Attr
|
|
|
88
88
|
#
|
|
89
89
|
# @api public
|
|
90
90
|
def aggregator(agg = nil, opts = EMPTY_HASH)
|
|
91
|
-
if agg.nil? && !defined?(@aggregator)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
@aggregator = if agg.nil? && !defined?(@aggregator)
|
|
92
|
+
Aggregators.default
|
|
93
|
+
elsif agg
|
|
94
|
+
Aggregators.resolve(agg, filter: filter, **opts)
|
|
95
|
+
else
|
|
96
|
+
@aggregator
|
|
97
|
+
end
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
# Defines a filter for filtering out invalid values
|
|
@@ -130,12 +130,16 @@ module Attr
|
|
|
130
130
|
# @param args [Array<Object>] arguments for initializing the filter
|
|
131
131
|
#
|
|
132
132
|
# @api public
|
|
133
|
-
def filter(filt =
|
|
134
|
-
if filt
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
def filter(filt = nil, *args, **opts)
|
|
134
|
+
@filter = if filt.nil? && !defined?(@filter)
|
|
135
|
+
Filters.default
|
|
136
|
+
elsif filt
|
|
137
|
+
Filters.resolve(filt, *args, **opts)
|
|
138
|
+
else
|
|
139
|
+
@filter
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
aggregator.filter = @filter
|
|
139
143
|
|
|
140
144
|
@filter
|
|
141
145
|
end
|
|
@@ -169,7 +173,7 @@ module Attr
|
|
|
169
173
|
# @api public
|
|
170
174
|
def filter_with_contract(arg = nil, &blk)
|
|
171
175
|
contract = block_given? ? build_inline_contract_filter(&blk) : arg
|
|
172
|
-
|
|
176
|
+
filter(:contract, contract)
|
|
173
177
|
end
|
|
174
178
|
|
|
175
179
|
private
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'dry-equalizer'
|
|
4
|
+
|
|
3
5
|
module Attr
|
|
4
6
|
module Gather
|
|
5
7
|
module Workflow
|
|
6
8
|
# @api private
|
|
7
9
|
class Task
|
|
8
|
-
|
|
10
|
+
send :include, Dry::Equalizer(:name, :depends_on)
|
|
11
|
+
|
|
12
|
+
attr_accessor :name, :depends_on
|
|
9
13
|
|
|
14
|
+
# Initialize a new DeepMerge aggregator
|
|
15
|
+
#
|
|
16
|
+
# @param name [String] name of the task
|
|
17
|
+
# @param depends_on [Array<Task>] tasks needed before running this task
|
|
18
|
+
#
|
|
19
|
+
# @api private
|
|
10
20
|
def initialize(name:, depends_on: [])
|
|
11
21
|
@name = name
|
|
12
22
|
@depends_on = depends_on
|
|
13
23
|
end
|
|
14
24
|
|
|
25
|
+
# Check if this task depends on a given task
|
|
26
|
+
#
|
|
27
|
+
# @param other_task [Task] task to check
|
|
15
28
|
def depends_on?(other_task)
|
|
16
|
-
depends_on.include?(other_task
|
|
29
|
+
depends_on.include?(other_task)
|
|
17
30
|
end
|
|
18
31
|
|
|
19
32
|
def fullfilled_given_remaining_tasks?(task_list)
|
|
@@ -20,7 +20,9 @@ module Attr
|
|
|
20
20
|
tasks.each { |t| self << t }
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def <<(
|
|
23
|
+
def <<(hash)
|
|
24
|
+
name, depends_on = hash.values_at :name, :depends_on
|
|
25
|
+
task = build_task(name, depends_on)
|
|
24
26
|
validate_for_insert!(task)
|
|
25
27
|
|
|
26
28
|
registered_tasks.each do |t|
|
|
@@ -68,6 +70,16 @@ module Attr
|
|
|
68
70
|
|
|
69
71
|
private
|
|
70
72
|
|
|
73
|
+
def build_task(name, depends_on)
|
|
74
|
+
deps = depends_on.map do |dep_name|
|
|
75
|
+
registered_tasks.find do |task|
|
|
76
|
+
task.name == dep_name
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
Task.new(name: name, depends_on: deps)
|
|
81
|
+
end
|
|
82
|
+
|
|
71
83
|
def tsort_each_child(node, &blk)
|
|
72
84
|
to_h[node].each(&blk)
|
|
73
85
|
end
|
|
@@ -99,7 +111,7 @@ module Attr
|
|
|
99
111
|
end
|
|
100
112
|
|
|
101
113
|
def depended_on_tasks_exist?(task)
|
|
102
|
-
task.depends_on.all? { |t| registered_tasks.
|
|
114
|
+
task.depends_on.all? { |t| registered_tasks.include?(t) }
|
|
103
115
|
end
|
|
104
116
|
end
|
|
105
117
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: attr-gather
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ian Ker-Seymer
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-10-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -30,14 +30,14 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
33
|
+
version: '13.0'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
40
|
+
version: '13.0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rspec
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -73,6 +73,8 @@ executables: []
|
|
|
73
73
|
extensions: []
|
|
74
74
|
extra_rdoc_files: []
|
|
75
75
|
files:
|
|
76
|
+
- ".github/dependabot.yml"
|
|
77
|
+
- ".github/mergify.yml"
|
|
76
78
|
- ".github/workflows/deploy.yml"
|
|
77
79
|
- ".github/workflows/doc.yml"
|
|
78
80
|
- ".github/workflows/ruby.yml"
|
|
@@ -113,14 +115,11 @@ files:
|
|
|
113
115
|
- lib/attr/gather/filters/result.rb
|
|
114
116
|
- lib/attr/gather/version.rb
|
|
115
117
|
- lib/attr/gather/workflow.rb
|
|
116
|
-
- lib/attr/gather/workflow/async_task_executor.rb
|
|
117
118
|
- lib/attr/gather/workflow/callable.rb
|
|
118
119
|
- lib/attr/gather/workflow/dot_serializer.rb
|
|
119
120
|
- lib/attr/gather/workflow/dsl.rb
|
|
120
121
|
- lib/attr/gather/workflow/graphable.rb
|
|
121
122
|
- lib/attr/gather/workflow/task.rb
|
|
122
|
-
- lib/attr/gather/workflow/task_execution_result.rb
|
|
123
|
-
- lib/attr/gather/workflow/task_executor.rb
|
|
124
123
|
- lib/attr/gather/workflow/task_graph.rb
|
|
125
124
|
homepage: https://github.com/ianks/attr-gather
|
|
126
125
|
licenses:
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'attr/gather/workflow/task_executor'
|
|
4
|
-
|
|
5
|
-
module Attr
|
|
6
|
-
module Gather
|
|
7
|
-
module Workflow
|
|
8
|
-
# @api private
|
|
9
|
-
class AsyncTaskExecutor < TaskExecutor
|
|
10
|
-
def initialize(*)
|
|
11
|
-
super
|
|
12
|
-
@executor = :io
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Attr
|
|
4
|
-
module Gather
|
|
5
|
-
module Workflow
|
|
6
|
-
# A wrapper containing information and results of a task execution
|
|
7
|
-
#
|
|
8
|
-
# @!attribute [r] started_at
|
|
9
|
-
# @return [Time] time which the execution occured
|
|
10
|
-
#
|
|
11
|
-
# @!attribute [r] task
|
|
12
|
-
# @return [Attr::Gather::Workflow::Task] task that was run
|
|
13
|
-
#
|
|
14
|
-
# @!attribute [r] result
|
|
15
|
-
# @return [Concurrent::Promise] the result promise of the the task
|
|
16
|
-
#
|
|
17
|
-
# @api public
|
|
18
|
-
class TaskExecutionResult
|
|
19
|
-
include Concerns::Identifiable
|
|
20
|
-
|
|
21
|
-
attr_reader :task, :result, :started_at, :uuid
|
|
22
|
-
|
|
23
|
-
def initialize(task, result)
|
|
24
|
-
@started_at = Time.now
|
|
25
|
-
@uuid = SecureRandom.uuid
|
|
26
|
-
@task = task
|
|
27
|
-
@result = result
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# @!attribute [r] state
|
|
31
|
-
# @return [:unscheduled, :pending, :processing, :rejected, :fulfilled]
|
|
32
|
-
def state
|
|
33
|
-
result.state
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Extracts the result, this is an unsafe operation that blocks the
|
|
37
|
-
# operation, and returns either the value or an exception.
|
|
38
|
-
#
|
|
39
|
-
# @note For more information, check out {https://ruby-concurrency.github.io/concurrent-ruby/1.1.5/Concurrent/Concern/Obligation.html#value!-instance_method}
|
|
40
|
-
def value!
|
|
41
|
-
result.value!
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Represents the TaskExecutionResult as a hash
|
|
45
|
-
#
|
|
46
|
-
# @return [Hash]
|
|
47
|
-
def as_json
|
|
48
|
-
value = result.value
|
|
49
|
-
|
|
50
|
-
{ started_at: started_at,
|
|
51
|
-
task: task.as_json,
|
|
52
|
-
state: state,
|
|
53
|
-
value: value }
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'concurrent'
|
|
4
|
-
require 'attr/gather/workflow/task_execution_result'
|
|
5
|
-
|
|
6
|
-
module Attr
|
|
7
|
-
module Gather
|
|
8
|
-
module Workflow
|
|
9
|
-
# @api private
|
|
10
|
-
class TaskExecutor
|
|
11
|
-
attr_reader :batch, :container, :executor
|
|
12
|
-
|
|
13
|
-
def initialize(batch, container:)
|
|
14
|
-
@batch = batch
|
|
15
|
-
@container = container
|
|
16
|
-
@executor = :immediate
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def call(input)
|
|
20
|
-
batch.map do |task|
|
|
21
|
-
task_proc = container.resolve(task.name)
|
|
22
|
-
result = Concurrent::Promise.execute(executor: executor) do
|
|
23
|
-
task_proc.call(input)
|
|
24
|
-
end
|
|
25
|
-
TaskExecutionResult.new(task, result)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|