scout-gear 10.7.5 → 10.7.7
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/.vimproject +8 -0
- data/VERSION +1 -1
- data/lib/scout/association/index.rb +2 -2
- data/lib/scout/knowledge_base/description.rb +108 -0
- data/lib/scout/knowledge_base/entity.rb +6 -1
- data/lib/scout/knowledge_base/registry.rb +43 -15
- data/lib/scout/knowledge_base.rb +3 -2
- data/lib/scout/tsv/annotation.rb +3 -3
- data/lib/scout/tsv/change_id/translate.rb +1 -0
- data/lib/scout/tsv/open.rb +8 -0
- data/lib/scout/tsv/parser.rb +14 -3
- data/lib/scout/workflow/definition.rb +2 -2
- data/lib/scout/workflow/deployment/orchestrator.rb +9 -1
- data/lib/scout/workflow/deployment/queue.rb +26 -0
- data/lib/scout/workflow/export.rb +6 -0
- data/lib/scout/workflow/persist.rb +6 -0
- data/lib/scout/workflow/step/info.rb +1 -0
- data/lib/scout/workflow/step/inputs.rb +11 -1
- data/lib/scout/workflow/task.rb +2 -1
- data/lib/scout/workflow.rb +7 -1
- data/scout-gear.gemspec +11 -3
- data/scout_commands/kb/config +3 -0
- data/scout_commands/kb/list +1 -0
- data/scout_commands/kb/query +2 -1
- data/scout_commands/kb/register +3 -1
- data/scout_commands/kb/show +4 -2
- data/scout_commands/resource/sync +33 -0
- data/scout_commands/workflow/cmd +116 -0
- data/scout_commands/workflow/process +82 -0
- data/scout_commands/workflow/task +15 -3
- data/test/data/person/README.md +17 -0
- data/test/scout/knowledge_base/test_description.rb +59 -0
- data/test/scout/workflow/test_entity.rb +3 -3
- data/test/test_helper.rb +2 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27ef5b8aa113a998b4dde3d2eba3b8129e29b47b5a96af51e1bb8080d82cb671
|
4
|
+
data.tar.gz: 6e4cba134a145b426024f03d247550573f4dbf879cc600ad951a2729255ce2f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c31507a2e82ca6d1b308661f586633f08a917dcd8b794cb7902d86e4c022f1f6ad1d4e423da0e3d8633464feeda0fd938b1e58779f72ad12e9685c67d244b4bc
|
7
|
+
data.tar.gz: 1bc95a9439b34ce670ebdbd893c79793c03d339c49b4e7e6877b24dd18e05f189875e95779e8bc3caea9abd3fb8491ec73888c74a03ffb1a859c7d35e397a0c9
|
data/.vimproject
CHANGED
@@ -10,6 +10,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
10
10
|
exceptions.rb
|
11
11
|
export.rb
|
12
12
|
definition.rb
|
13
|
+
persist.rb
|
13
14
|
documentation.rb
|
14
15
|
usage.rb
|
15
16
|
util.rb
|
@@ -36,6 +37,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
36
37
|
}
|
37
38
|
deployment.rb
|
38
39
|
deployment=deployment{
|
40
|
+
queue.rb
|
39
41
|
trace.rb
|
40
42
|
orchestrator.rb
|
41
43
|
}
|
@@ -123,6 +125,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
123
125
|
traverse.rb
|
124
126
|
enrichment.rb
|
125
127
|
list.rb
|
128
|
+
description.rb
|
126
129
|
}
|
127
130
|
semaphore.rb
|
128
131
|
}
|
@@ -157,6 +160,9 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
157
160
|
install
|
158
161
|
trace
|
159
162
|
prov
|
163
|
+
queue
|
164
|
+
process
|
165
|
+
cmd
|
160
166
|
}
|
161
167
|
batch=batch{
|
162
168
|
list
|
@@ -164,6 +170,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
164
170
|
}
|
165
171
|
resource=resource{
|
166
172
|
produce
|
173
|
+
sync
|
167
174
|
}
|
168
175
|
}
|
169
176
|
test=test {
|
@@ -172,6 +179,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
172
179
|
test_scout.rb
|
173
180
|
data=data filter="*"{
|
174
181
|
person=person{
|
182
|
+
README.md
|
175
183
|
brothers
|
176
184
|
identifiers
|
177
185
|
marriages
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
10.7.
|
1
|
+
10.7.7
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'scout/annotation'
|
2
2
|
module Association
|
3
3
|
|
4
|
-
def self.index(file, source: nil, target: nil, source_format: nil, target_format: nil, format: nil, **kwargs)
|
4
|
+
def self.index(file, source: nil, target: nil, source_format: nil, target_format: nil, format: nil, database: nil, **kwargs)
|
5
5
|
IndiferentHash.setup(kwargs)
|
6
6
|
source = kwargs.delete :source if kwargs.include?(:source)
|
7
7
|
target = kwargs.delete :target if kwargs.include?(:target)
|
@@ -14,7 +14,7 @@ module Association
|
|
14
14
|
index = Persist.tsv(file, kwargs, engine: "BDB", persist_options: index_persist_options) do |data|
|
15
15
|
recycle, undirected = IndiferentHash.process_options kwargs, :recycle, :undirected
|
16
16
|
|
17
|
-
database
|
17
|
+
database ||= Association.open(file, source: source, target: target, source_format: source_format, target_format: target_format, **kwargs.merge(persist_prefix: "Association::Database"))
|
18
18
|
|
19
19
|
source_field = database.key_field
|
20
20
|
target_field, *fields = database.fields
|
@@ -0,0 +1,108 @@
|
|
1
|
+
class KnowledgeBase
|
2
|
+
def self.doc_parse_up_to(str, pattern, keep = false)
|
3
|
+
pre, _pat, _post = str.partition pattern
|
4
|
+
if _pat
|
5
|
+
[pre, (keep ? _pat << _post : _post)]
|
6
|
+
else
|
7
|
+
_post
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.doc_parse_chunks(str, pattern)
|
12
|
+
parts = str.split(pattern)
|
13
|
+
return {} if parts.length < 2
|
14
|
+
databases = Hash[*parts[1..-1].collect{|v| v.strip }]
|
15
|
+
databases.delete_if{|t,d| d.empty?}
|
16
|
+
databases.transform_keys!(&:downcase)
|
17
|
+
databases
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.parse_knowledge_base_doc(doc)
|
21
|
+
description, db_description = doc_parse_up_to doc, /^#/, true
|
22
|
+
databases = doc_parse_chunks db_description, /^# (.*)/
|
23
|
+
IndiferentHash.setup({:description => description.strip, :databases => databases})
|
24
|
+
end
|
25
|
+
|
26
|
+
def documentation_markdown
|
27
|
+
return "" if @libdir.nil?
|
28
|
+
file = @libdir['README.md'].find unless file.exists?
|
29
|
+
if file.exists?
|
30
|
+
file.read
|
31
|
+
else
|
32
|
+
""
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def database_description_file(name)
|
37
|
+
dir[name.to_s + '.md']
|
38
|
+
end
|
39
|
+
|
40
|
+
def knowledge_base_description_file(name)
|
41
|
+
file = dir['README.md']
|
42
|
+
return file if file.exists?
|
43
|
+
|
44
|
+
file, options = registry[name]
|
45
|
+
file = Path.setup(file.dup) unless file.nil? or Path === file
|
46
|
+
source_readme = file.dirname['README.md'] if file
|
47
|
+
return source_readme if source_readme && source_readme.exists?
|
48
|
+
end
|
49
|
+
|
50
|
+
def description(name)
|
51
|
+
return registered_options(name)[:description] if registered_options(name)[:description]
|
52
|
+
|
53
|
+
return database_description_file(name).read if database_description_file(name).exist?
|
54
|
+
|
55
|
+
if knowledge_base_description_file(name)
|
56
|
+
KnowledgeBase.parse_knowledge_base_doc(knowledge_base_description_file(name).read)[:databases][name.to_s.downcase]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def markdown(name)
|
61
|
+
description = description(name)
|
62
|
+
source_type = source_type(name)
|
63
|
+
target_type = target_type(name)
|
64
|
+
|
65
|
+
full_description = []
|
66
|
+
empty_line = ''
|
67
|
+
full_description << ("# " << Misc.humanize(name))
|
68
|
+
full_description << empty_line
|
69
|
+
|
70
|
+
source_formats = begin
|
71
|
+
source_index(name).key_field.split(',')
|
72
|
+
rescue
|
73
|
+
[]
|
74
|
+
end
|
75
|
+
|
76
|
+
target_formats = begin
|
77
|
+
target_index(name).key_field.split(',')
|
78
|
+
rescue
|
79
|
+
[]
|
80
|
+
end
|
81
|
+
|
82
|
+
if source_type
|
83
|
+
full_description << "Source: #{source_type} - #{source(name)}"
|
84
|
+
else
|
85
|
+
full_description << "Source: #{source(name)}"
|
86
|
+
end
|
87
|
+
#full_description.last << ". Accepted formats: #{source_formats*", "}" if source_formats.any?
|
88
|
+
|
89
|
+
if target_type
|
90
|
+
full_description << "Target: #{target_type} - #{target(name)}"
|
91
|
+
else
|
92
|
+
full_description << "Target: #{target(name)}"
|
93
|
+
end
|
94
|
+
#full_description.last << ". Accepted formats: #{target_formats*", "}" if target_formats.any?
|
95
|
+
|
96
|
+
if undirected?(name)
|
97
|
+
full_description << "Undirected database, source and target can be reversed."
|
98
|
+
end
|
99
|
+
|
100
|
+
if description
|
101
|
+
full_description << empty_line
|
102
|
+
full_description << description
|
103
|
+
full_description << empty_line
|
104
|
+
end
|
105
|
+
|
106
|
+
full_description * "\n"
|
107
|
+
end
|
108
|
+
end
|
@@ -80,6 +80,7 @@ class KnowledgeBase
|
|
80
80
|
end
|
81
81
|
identifier_files.concat Entity.identifier_files(source(name)) if defined? Entity
|
82
82
|
identifier_files.uniq!
|
83
|
+
identifier_files.collect!{|f| (Path === f) ? f : Path.setup(f.dup) }
|
83
84
|
identifier_files.collect!{|f| f.annotate(f.gsub(/\bNAMESPACE\b/, namespace))} if namespace
|
84
85
|
identifier_files.collect!{|f| f.annotate(f.gsub(/\bNAMESPACE\b/, db_namespace(name)))} if not namespace and db_namespace(name)
|
85
86
|
identifier_files.reject!{|f| f.match(/\bNAMESPACE\b/)}
|
@@ -89,7 +90,11 @@ class KnowledgeBase
|
|
89
90
|
|
90
91
|
def target_index(name)
|
91
92
|
Persist.memory("Target index #{name}: KB directory #{dir}") do
|
92
|
-
identifier_files
|
93
|
+
if @identifier_files && @identifier_files.any?
|
94
|
+
identifier_files = @identifier_files
|
95
|
+
else
|
96
|
+
identifier_files = database_identifier_files(name)
|
97
|
+
end
|
93
98
|
identifier_files.concat Entity.identifier_files(target(name)) if defined? Entity
|
94
99
|
identifier_files.uniq!
|
95
100
|
identifier_files.collect!{|f| f.annotate(f.gsub(/\bNAMESPACE\b/, namespace))} if self.namespace
|
@@ -15,9 +15,29 @@ class KnowledgeBase
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
def present_databases
|
19
|
+
dir.glob("*.database").collect{|file| File.basename(file, '.database')}
|
20
|
+
end
|
21
|
+
|
18
22
|
def all_databases
|
19
23
|
return [] unless @registry
|
20
|
-
@registry.keys
|
24
|
+
(@registry.keys + present_databases).uniq
|
25
|
+
end
|
26
|
+
|
27
|
+
def database_file(name)
|
28
|
+
if @registry[name].nil?
|
29
|
+
nil
|
30
|
+
else
|
31
|
+
@registry[name].first
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def registered_options(name)
|
36
|
+
if @registry[name].nil?
|
37
|
+
IndiferentHash.setup({})
|
38
|
+
else
|
39
|
+
IndiferentHash.setup(@registry[name].last)
|
40
|
+
end
|
21
41
|
end
|
22
42
|
|
23
43
|
def include?(name)
|
@@ -29,21 +49,21 @@ class KnowledgeBase
|
|
29
49
|
@fields[name] ||= get_index(name).fields
|
30
50
|
end
|
31
51
|
|
32
|
-
def
|
33
|
-
@
|
34
|
-
@
|
52
|
+
def pair(name)
|
53
|
+
@pairs ||= {}
|
54
|
+
@pairs[name] ||= get_index(name).key_field.split("~")
|
35
55
|
end
|
36
56
|
|
37
57
|
def source(name)
|
38
|
-
|
58
|
+
pair(name)[0]
|
39
59
|
end
|
40
60
|
|
41
61
|
def target(name)
|
42
|
-
|
62
|
+
pair(name)[1]
|
43
63
|
end
|
44
64
|
|
45
65
|
def undirected(name)
|
46
|
-
|
66
|
+
pair(name).length == 3
|
47
67
|
end
|
48
68
|
|
49
69
|
alias undirected? undirected
|
@@ -69,7 +89,12 @@ class KnowledgeBase
|
|
69
89
|
|
70
90
|
persist_dir = dir
|
71
91
|
persist_path = persist_dir[key].find
|
72
|
-
|
92
|
+
|
93
|
+
file = database_file(name)
|
94
|
+
registered_options = registered_options(name)
|
95
|
+
registered_options = IndiferentHash.setup(registered_options).except(:description)
|
96
|
+
|
97
|
+
registered_options = IndiferentHash.add_defaults registered_options, identifiers: self.identifier_files if registered_options
|
73
98
|
|
74
99
|
options = IndiferentHash.add_defaults options, registered_options if registered_options and registered_options.any?
|
75
100
|
options = IndiferentHash.add_defaults options, :persist_path => persist_path, :persist_dir => persist_dir, :persist => true
|
@@ -89,11 +114,11 @@ class KnowledgeBase
|
|
89
114
|
Log.low "Re-opening index #{ name } from #{ Log.fingerprint persist_path }. #{options}"
|
90
115
|
Association.index(file, **options, persist_options: persist_options.dup)
|
91
116
|
else
|
92
|
-
|
93
|
-
raise "Repo #{ name } not found and not registered" if file.nil?
|
94
|
-
Log.medium "Opening index #{ name } from #{ Log.fingerprint file }. #{options}"
|
117
|
+
database = get_database name if file.nil?
|
95
118
|
file = file.call if Proc === file
|
96
|
-
|
119
|
+
Log.medium "Opening index #{ name } from #{ Log.fingerprint database }. #{options}"
|
120
|
+
options = IndiferentHash.add_defaults options, registered_options if registered_options
|
121
|
+
Association.index(file, **options, persist_options: persist_options.dup, database: database)
|
97
122
|
end
|
98
123
|
|
99
124
|
index.namespace = self.namespace unless self.namespace
|
@@ -128,7 +153,12 @@ class KnowledgeBase
|
|
128
153
|
|
129
154
|
persist_dir = dir
|
130
155
|
persist_path = persist_dir[key].find
|
131
|
-
|
156
|
+
|
157
|
+
file = database_file(name)
|
158
|
+
registered_options = registered_options(name)
|
159
|
+
registered_options = IndiferentHash.setup(registered_options).except(:description)
|
160
|
+
|
161
|
+
registered_options = IndiferentHash.add_defaults registered_options, identifiers: self.identifier_files if registered_options
|
132
162
|
|
133
163
|
options = IndiferentHash.add_defaults options, registered_options if registered_options and registered_options.any?
|
134
164
|
options = IndiferentHash.add_defaults options, :persist_path => persist_path, :persist => true
|
@@ -145,7 +175,6 @@ class KnowledgeBase
|
|
145
175
|
|
146
176
|
database = if persist_path.exists? and persist_options[:persist] and not persist_options[:update]
|
147
177
|
Log.low "Re-opening database #{ name } from #{ Log.fingerprint persist_path }. #{options}"
|
148
|
-
#Association.database(file, **options, persist_options: persist_options)
|
149
178
|
Association.database(file, **options.merge(persist_options: persist_options))
|
150
179
|
else
|
151
180
|
options = IndiferentHash.add_defaults options, registered_options if registered_options
|
@@ -153,7 +182,6 @@ class KnowledgeBase
|
|
153
182
|
raise "Repo #{ name } not found and not registered" if file.nil?
|
154
183
|
Log.medium "Opening database #{ name } from #{ Log.fingerprint file }. #{options}"
|
155
184
|
file = file.call if Proc === file
|
156
|
-
#Association.database(file, **options, persist_options: persist_options)
|
157
185
|
Association.database(file, **options.merge(persist_options: persist_options))
|
158
186
|
end
|
159
187
|
|
data/lib/scout/knowledge_base.rb
CHANGED
@@ -5,6 +5,7 @@ require_relative 'knowledge_base/entity'
|
|
5
5
|
require_relative 'knowledge_base/query'
|
6
6
|
require_relative 'knowledge_base/traverse'
|
7
7
|
require_relative 'knowledge_base/list'
|
8
|
+
require_relative 'knowledge_base/description'
|
8
9
|
#require 'scout/knowledge_base/query'
|
9
10
|
#require 'scout/knowledge_base/syndicate'
|
10
11
|
|
@@ -23,12 +24,12 @@ class KnowledgeBase
|
|
23
24
|
@entity_options ||= IndiferentHash.setup({})
|
24
25
|
|
25
26
|
@format ||= IndiferentHash.setup({})
|
26
|
-
|
27
|
+
pairs ||= IndiferentHash.setup({})
|
27
28
|
@indices ||= IndiferentHash.setup({})
|
28
29
|
end
|
29
30
|
|
30
31
|
def config_file(name)
|
31
|
-
@dir
|
32
|
+
@dir['config'][name.to_s]
|
32
33
|
end
|
33
34
|
|
34
35
|
def save_variable(name)
|
data/lib/scout/tsv/annotation.rb
CHANGED
@@ -75,17 +75,17 @@ module Annotation
|
|
75
75
|
when Annotation.is_annotated?(objs)
|
76
76
|
tsv.key_field = "List"
|
77
77
|
|
78
|
-
tsv[objs.
|
78
|
+
tsv[objs.id] = self.list_tsv_values(objs, fields).dup
|
79
79
|
when Array === objs
|
80
80
|
tsv.key_field = "ID"
|
81
81
|
|
82
82
|
if Annotation.is_annotated?(objs.compact.first)
|
83
83
|
objs.compact.each_with_index do |obj,i|
|
84
|
-
tsv[obj.
|
84
|
+
tsv[obj.id + "#" << i.to_s] = self.obj_tsv_values(obj, fields).dup
|
85
85
|
end
|
86
86
|
elsif (objs.any? && Annotation.is_annotated?(objs.compact.first.compact.first))
|
87
87
|
objs.flatten.compact.each_with_index do |obj,i|
|
88
|
-
tsv[obj.
|
88
|
+
tsv[obj.id + "#" << i.to_s] = self.obj_tsv_values(obj, fields).dup
|
89
89
|
end
|
90
90
|
end
|
91
91
|
else
|
data/lib/scout/tsv/open.rb
CHANGED
@@ -153,6 +153,14 @@ module Open
|
|
153
153
|
end
|
154
154
|
obj.close
|
155
155
|
obj.join if obj.respond_to? :join
|
156
|
+
elsif options[:type] == :matrix
|
157
|
+
Log.low "Traverse stream by lines #{Log.fingerprint obj}"
|
158
|
+
parser = options[:sep].nil? ? TSV::Parser.new(obj) : TSV::Parser.new(obj, sep: options[:sep])
|
159
|
+
parser.traverse **options do |parts|
|
160
|
+
res = block.call parts
|
161
|
+
callback.call res if callback
|
162
|
+
nil
|
163
|
+
end
|
156
164
|
else
|
157
165
|
Log.low "Traverse stream with parser #{Log.fingerprint obj}"
|
158
166
|
parser = options[:sep].nil? ? TSV::Parser.new(obj) : TSV::Parser.new(obj, sep: options[:sep])
|
data/lib/scout/tsv/parser.rb
CHANGED
@@ -31,6 +31,12 @@ module TSV
|
|
31
31
|
|
32
32
|
return nil if select && ! TSV.select(items[0], items[1..-1], select, fields: field_names, type: type, sep: sep2)
|
33
33
|
|
34
|
+
if String === key
|
35
|
+
raise "Key by name, but no field names" if field_names.nil?
|
36
|
+
key = field_names.index key
|
37
|
+
raise "Key #{key} not found in field names #{Log.fingerprint field_names}" if key.nil?
|
38
|
+
end
|
39
|
+
|
34
40
|
if positions.nil? && key == 0
|
35
41
|
key = items.shift
|
36
42
|
elsif positions.nil?
|
@@ -65,7 +71,7 @@ module TSV
|
|
65
71
|
[key, items]
|
66
72
|
end
|
67
73
|
|
68
|
-
def self.parse_stream(stream, data: nil, source_type: nil, type: :list, merge: true, one2one: false, fix: true, bar: false, first_line: nil, field_names: nil, head: nil, **kwargs, &block)
|
74
|
+
def self.parse_stream(stream, data: nil, source_type: nil, sep: "\t", type: :list, merge: true, one2one: false, fix: true, bar: false, first_line: nil, field_names: nil, head: nil, **kwargs, &block)
|
69
75
|
begin
|
70
76
|
bar = "Parsing #{Log.fingerprint stream}" if TrueClass === bar
|
71
77
|
bar = Log::ProgressBar.get_obj_bar(stream, bar) if bar
|
@@ -81,7 +87,7 @@ module TSV
|
|
81
87
|
data.serializer.to_s.include?("String") &&
|
82
88
|
same_type &&
|
83
89
|
! (head || kwargs[:cast] || kwargs[:positions] || (kwargs[:key] && kwargs[:key] != 0) || Proc === fix ) &&
|
84
|
-
(
|
90
|
+
(sep.nil? || sep == "\t")
|
85
91
|
|
86
92
|
|
87
93
|
Log.debug "Loading #{Log.fingerprint stream} directly into #{Log.fingerprint data}"
|
@@ -114,12 +120,17 @@ module TSV
|
|
114
120
|
line = Misc.fixutf8(line)
|
115
121
|
end
|
116
122
|
bar.tick if bar
|
123
|
+
|
117
124
|
if type == :array || type == :line
|
118
125
|
block.call line
|
119
126
|
next
|
127
|
+
elsif type == :matrix
|
128
|
+
parts = line.split(sep)
|
129
|
+
block.call parts
|
130
|
+
next
|
120
131
|
end
|
121
132
|
|
122
|
-
key, items = parse_line(line, type: source_type, field_names: field_names, **kwargs)
|
133
|
+
key, items = parse_line(line, type: source_type, field_names: field_names, sep: sep, **kwargs)
|
123
134
|
|
124
135
|
next if key.nil?
|
125
136
|
|
@@ -29,7 +29,7 @@ module Workflow
|
|
29
29
|
if block_given?
|
30
30
|
helpers[name] = block
|
31
31
|
else
|
32
|
-
raise
|
32
|
+
raise ScoutException, "helper #{name} unkown in #{self} workflow" unless helpers[name]
|
33
33
|
o = Object.new
|
34
34
|
o.extend step_module
|
35
35
|
o.send(name, *args, **kwargs)
|
@@ -164,7 +164,7 @@ module Workflow
|
|
164
164
|
type = task_proc.type
|
165
165
|
end
|
166
166
|
task name => type do
|
167
|
-
raise
|
167
|
+
raise ScoutException, "dep_task does not have any dependencies" if dependencies.empty?
|
168
168
|
Step.wait_for_jobs dependencies.select{|d| d.streaming? }
|
169
169
|
dep = dependencies.last
|
170
170
|
dep.join
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Workflow
|
2
2
|
class Orchestrator
|
3
3
|
|
4
|
+
class NoWork < Exception; end
|
5
|
+
|
4
6
|
def self.job_workload(job)
|
5
7
|
workload = {job => []}
|
6
8
|
return workload if job.done? && job.updated?
|
@@ -202,7 +204,7 @@ module Workflow
|
|
202
204
|
|
203
205
|
candidates = resources_used.keys + Orchestrator.candidates(workload, rules)
|
204
206
|
candidates.uniq!
|
205
|
-
raise "No candidates and no running jobs" if candidates.empty?
|
207
|
+
raise NoWork, "No candidates and no running jobs" if candidates.empty?
|
206
208
|
|
207
209
|
candidates.each do |job|
|
208
210
|
case
|
@@ -272,4 +274,10 @@ module Workflow
|
|
272
274
|
orchestrator.process({}, produce_list)
|
273
275
|
produce_list
|
274
276
|
end
|
277
|
+
|
278
|
+
def self.produce(jobs, produce_cpus: Etc.nprocessors, produce_timer: 5)
|
279
|
+
jobs = [jobs] unless Array === jobs
|
280
|
+
orchestrator = Orchestrator.new produce_timer.to_i, cpus: produce_cpus.to_i
|
281
|
+
orchestrator.process({}, jobs)
|
282
|
+
end
|
275
283
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Workflow
|
2
|
+
def self.name2clean_name(name)
|
3
|
+
name.reverse.partition("_").last.reverse
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.queue_job(file)
|
7
|
+
workflow, task, name = file.split("/").values_at(-3, -2, -1) if file
|
8
|
+
workflow = Workflow.require_workflow workflow
|
9
|
+
|
10
|
+
if Open.directory?(file)
|
11
|
+
clean_name = name2clean_name name
|
12
|
+
inputs = workflow.tasks[task].load_inputs(file)
|
13
|
+
workflow.job(task, clean_name, inputs)
|
14
|
+
else
|
15
|
+
workflow.job(task, name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.unqueue(file, &block)
|
20
|
+
Open.lock file do
|
21
|
+
job = queue_job(file)
|
22
|
+
puts job.run
|
23
|
+
Open.rm_rf file
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -18,6 +18,12 @@ module Workflow
|
|
18
18
|
@exec_exports ||= []
|
19
19
|
end
|
20
20
|
|
21
|
+
def clear_exports
|
22
|
+
asynchronous_exports.clear
|
23
|
+
synchronous_exports.clear
|
24
|
+
exec_exports.clear
|
25
|
+
stream_exports.clear
|
26
|
+
end
|
21
27
|
|
22
28
|
def all_exports
|
23
29
|
asynchronous_exports + synchronous_exports + exec_exports + stream_exports
|
@@ -1,5 +1,15 @@
|
|
1
1
|
class Step
|
2
2
|
def save_inputs(inputs_dir)
|
3
|
-
|
3
|
+
if clean_name != name
|
4
|
+
hash = name[clean_name.length..-1]
|
5
|
+
inputs_dir += hash
|
6
|
+
Log.medium "Saving job inputs to: #{Log.fingerprint inputs_dir}"
|
7
|
+
self.task.save_inputs(inputs_dir, provided_inputs)
|
8
|
+
inputs_dir
|
9
|
+
else
|
10
|
+
Log.medium "Saving no input job: #{Log.fingerprint inputs_dir}"
|
11
|
+
Open.touch(inputs_dir)
|
12
|
+
inputs_dir
|
13
|
+
end
|
4
14
|
end
|
5
15
|
end
|
data/lib/scout/workflow/task.rb
CHANGED
@@ -34,6 +34,7 @@ module Task
|
|
34
34
|
def job(id = nil, provided_inputs = nil)
|
35
35
|
|
36
36
|
if Hash === provided_inputs
|
37
|
+
IndiferentHash.setup provided_inputs
|
37
38
|
memory_inputs = provided_inputs.values_at *self.recursive_inputs.collect{|t| t.first }.uniq
|
38
39
|
memory_inputs += provided_inputs.select{|k,v| k.to_s.include?("#") }.collect{|p| p * "=" }
|
39
40
|
memory_inputs << provided_inputs[:load_inputs]
|
@@ -41,7 +42,7 @@ module Task
|
|
41
42
|
memory_inputs = provided_inputs
|
42
43
|
end
|
43
44
|
|
44
|
-
Persist.memory("Task job #{self.name}
|
45
|
+
Persist.memory("Task job #{self.name}", repo: Workflow.job_cache, other: {task: self.name, id: id, provided_inputs: memory_inputs}) do
|
45
46
|
provided_inputs, id = id, nil if (provided_inputs.nil? || provided_inputs.empty?) && (Hash === id || Array === id)
|
46
47
|
provided_inputs = {} if provided_inputs.nil?
|
47
48
|
IndiferentHash.setup(provided_inputs)
|
data/lib/scout/workflow.rb
CHANGED
@@ -9,13 +9,19 @@ require_relative 'workflow/exceptions'
|
|
9
9
|
require_relative 'workflow/path'
|
10
10
|
require_relative 'workflow/entity'
|
11
11
|
require_relative 'workflow/export'
|
12
|
+
require_relative 'workflow/persist'
|
12
13
|
|
13
14
|
require 'scout/resource'
|
14
15
|
require 'scout/resource/scout'
|
15
16
|
|
16
17
|
module Workflow
|
17
18
|
class << self
|
18
|
-
attr_accessor :workflows, :main, :workflow_dir, :autoinstall, :workflow_repo
|
19
|
+
attr_accessor :workflows, :main, :workflow_dir, :autoinstall, :workflow_repo, :job_cache
|
20
|
+
|
21
|
+
def job_cache
|
22
|
+
@job_cache ||={}
|
23
|
+
end
|
24
|
+
|
19
25
|
def workflows
|
20
26
|
@workflows ||= []
|
21
27
|
end
|
data/scout-gear.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: scout-gear 10.7.
|
5
|
+
# stub: scout-gear 10.7.7 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "scout-gear".freeze
|
9
|
-
s.version = "10.7.
|
9
|
+
s.version = "10.7.7".freeze
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Miguel Vazquez".freeze]
|
14
|
-
s.date = "2025-
|
14
|
+
s.date = "2025-04-11"
|
15
15
|
s.description = "Scout gear: workflow, TSVs, persistence, entities, associations, and knowledge_bases.".freeze
|
16
16
|
s.email = "mikisvaz@gmail.com".freeze
|
17
17
|
s.executables = ["scout".freeze]
|
@@ -45,6 +45,7 @@ Gem::Specification.new do |s|
|
|
45
45
|
"lib/scout/entity/object.rb",
|
46
46
|
"lib/scout/entity/property.rb",
|
47
47
|
"lib/scout/knowledge_base.rb",
|
48
|
+
"lib/scout/knowledge_base/description.rb",
|
48
49
|
"lib/scout/knowledge_base/enrichment.rb",
|
49
50
|
"lib/scout/knowledge_base/entity.rb",
|
50
51
|
"lib/scout/knowledge_base/list.rb",
|
@@ -98,12 +99,14 @@ Gem::Specification.new do |s|
|
|
98
99
|
"lib/scout/workflow/definition.rb",
|
99
100
|
"lib/scout/workflow/deployment.rb",
|
100
101
|
"lib/scout/workflow/deployment/orchestrator.rb",
|
102
|
+
"lib/scout/workflow/deployment/queue.rb",
|
101
103
|
"lib/scout/workflow/deployment/trace.rb",
|
102
104
|
"lib/scout/workflow/documentation.rb",
|
103
105
|
"lib/scout/workflow/entity.rb",
|
104
106
|
"lib/scout/workflow/exceptions.rb",
|
105
107
|
"lib/scout/workflow/export.rb",
|
106
108
|
"lib/scout/workflow/path.rb",
|
109
|
+
"lib/scout/workflow/persist.rb",
|
107
110
|
"lib/scout/workflow/step.rb",
|
108
111
|
"lib/scout/workflow/step/archive.rb",
|
109
112
|
"lib/scout/workflow/step/children.rb",
|
@@ -140,11 +143,14 @@ Gem::Specification.new do |s|
|
|
140
143
|
"scout_commands/log",
|
141
144
|
"scout_commands/rbbt",
|
142
145
|
"scout_commands/resource/produce",
|
146
|
+
"scout_commands/resource/sync",
|
143
147
|
"scout_commands/template",
|
144
148
|
"scout_commands/update",
|
149
|
+
"scout_commands/workflow/cmd",
|
145
150
|
"scout_commands/workflow/info",
|
146
151
|
"scout_commands/workflow/install",
|
147
152
|
"scout_commands/workflow/list",
|
153
|
+
"scout_commands/workflow/process",
|
148
154
|
"scout_commands/workflow/prov",
|
149
155
|
"scout_commands/workflow/task",
|
150
156
|
"scout_commands/workflow/trace",
|
@@ -154,6 +160,7 @@ Gem::Specification.new do |s|
|
|
154
160
|
"share/software/install_helpers",
|
155
161
|
"share/templates/command",
|
156
162
|
"share/templates/workflow.rb",
|
163
|
+
"test/data/person/README.md",
|
157
164
|
"test/data/person/brothers",
|
158
165
|
"test/data/person/identifiers",
|
159
166
|
"test/data/person/marriages",
|
@@ -166,6 +173,7 @@ Gem::Specification.new do |s|
|
|
166
173
|
"test/scout/entity/test_named_array.rb",
|
167
174
|
"test/scout/entity/test_object.rb",
|
168
175
|
"test/scout/entity/test_property.rb",
|
176
|
+
"test/scout/knowledge_base/test_description.rb",
|
169
177
|
"test/scout/knowledge_base/test_enrichment.rb",
|
170
178
|
"test/scout/knowledge_base/test_entity.rb",
|
171
179
|
"test/scout/knowledge_base/test_list.rb",
|
data/scout_commands/kb/config
CHANGED
@@ -12,6 +12,7 @@ Configure a knowlege base
|
|
12
12
|
$ #{$0} [<options>] <name> [knowledge_base]
|
13
13
|
|
14
14
|
-h--help Print this help
|
15
|
+
-kb--knowledge_base* Knowlege base name (or :default)
|
15
16
|
-i--identifier_files* Identifier files separated by ','
|
16
17
|
-n--namespace* Namespace
|
17
18
|
EOF
|
@@ -26,8 +27,10 @@ end
|
|
26
27
|
|
27
28
|
knowledge_base_name = ARGV.first
|
28
29
|
|
30
|
+
knowledge_base_name ||= options[:knowledge_base] || :default
|
29
31
|
knowledge_base = KnowledgeBase.load knowledge_base_name || :default
|
30
32
|
|
31
33
|
knowledge_base.namespace = options[:namespace] if options.include? :namespace
|
32
34
|
knowledge_base.identifier_files += options[:identifier_files].split(",") if options.include? :identifier_files
|
35
|
+
knowledge_base.identifier_files.uniq!
|
33
36
|
knowledge_base.save
|
data/scout_commands/kb/list
CHANGED
data/scout_commands/kb/query
CHANGED
@@ -34,7 +34,8 @@ raise MissingParameterException, :name if name.nil?
|
|
34
34
|
raise MissingParameterException, :entity if entity.nil?
|
35
35
|
|
36
36
|
|
37
|
-
knowledge_base =
|
37
|
+
knowledge_base = IndiferentHash.process_options options, :knowledge_base
|
38
|
+
knowledge_base = KnowledgeBase.load knowledge_base || :default
|
38
39
|
|
39
40
|
list = IndiferentHash.process_options options, :list
|
40
41
|
|
data/scout_commands/kb/register
CHANGED
@@ -19,6 +19,7 @@ $ #{$0} [<options>] <name> <filename>
|
|
19
19
|
-n--namespace* Namespace
|
20
20
|
-i--identifiers* Identifiers
|
21
21
|
-u--undirected
|
22
|
+
-d--description* Database description
|
22
23
|
EOF
|
23
24
|
if options.delete :help
|
24
25
|
if defined? scout_usage
|
@@ -35,7 +36,8 @@ name, file = ARGV
|
|
35
36
|
raise MissingParameterException, :name if name.nil?
|
36
37
|
raise MissingParameterException, :file if file.nil?
|
37
38
|
|
38
|
-
knowledge_base =
|
39
|
+
knowledge_base = IndiferentHash.process_options options, :knowledge_base
|
40
|
+
knowledge_base = KnowledgeBase.load knowledge_base || :default
|
39
41
|
|
40
42
|
options[:fields] = options[:fields].split(/,\s*/) if options[:fields]
|
41
43
|
file = Scout.identify(File.expand_path(file))
|
data/scout_commands/kb/show
CHANGED
@@ -23,7 +23,8 @@ if options[:help]
|
|
23
23
|
exit 0
|
24
24
|
end
|
25
25
|
|
26
|
-
knowledge_base =
|
26
|
+
knowledge_base = IndiferentHash.process_options options, :knowledge_base
|
27
|
+
knowledge_base = KnowledgeBase.load knowledge_base || :default
|
27
28
|
|
28
29
|
name = ARGV.first
|
29
30
|
|
@@ -31,7 +32,8 @@ if name.nil?
|
|
31
32
|
puts knowledge_base.all_databases * "\n"
|
32
33
|
else
|
33
34
|
|
34
|
-
raise ParameterException "Database #{name} not found Options: #{Log.fingerprint knowledge_base.all_databases}" unless knowledge_base.include? name
|
35
|
+
raise ParameterException, "Database #{name} not found Options: #{Log.fingerprint knowledge_base.all_databases}" unless knowledge_base.include? name
|
35
36
|
|
37
|
+
puts knowledge_base.markdown(name)
|
36
38
|
Log.tsv knowledge_base.get_database(name, options)
|
37
39
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'scout'
|
4
|
+
|
5
|
+
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
6
|
+
|
7
|
+
options = SOPT.setup <<EOF
|
8
|
+
|
9
|
+
Sync to resources between path maps or between hosts
|
10
|
+
|
11
|
+
$ #{$0} [<options>] <path> [<path_map>]
|
12
|
+
|
13
|
+
Path map defaults to :user
|
14
|
+
|
15
|
+
-h--help Print this help
|
16
|
+
-s--source* Host of source path
|
17
|
+
-t--target* Host of target path
|
18
|
+
EOF
|
19
|
+
if options[:help]
|
20
|
+
if defined? scout_usage
|
21
|
+
scout_usage
|
22
|
+
else
|
23
|
+
puts SOPT.doc
|
24
|
+
end
|
25
|
+
exit 0
|
26
|
+
end
|
27
|
+
|
28
|
+
path, path_map = ARGV
|
29
|
+
|
30
|
+
raise MissingParameterException, :path if path.nil?
|
31
|
+
|
32
|
+
options.keys_to_sym!
|
33
|
+
Resource.sync(Path.setup(path.dup), path_map, **options)
|
@@ -0,0 +1,116 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'scout'
|
4
|
+
|
5
|
+
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
6
|
+
|
7
|
+
options = SOPT.setup <<EOF
|
8
|
+
|
9
|
+
Run a workflow command
|
10
|
+
|
11
|
+
$ #{$0} <workflow> <command> [<subcommands>] [<options>] [<arg> ...]
|
12
|
+
|
13
|
+
-h--help Print this help
|
14
|
+
EOF
|
15
|
+
if options[:help]
|
16
|
+
if defined? scout_usage
|
17
|
+
scout_usage
|
18
|
+
else
|
19
|
+
puts SOPT.doc
|
20
|
+
end
|
21
|
+
exit 0
|
22
|
+
end
|
23
|
+
|
24
|
+
workflow = ARGV.shift
|
25
|
+
|
26
|
+
if workflow == '-h'
|
27
|
+
if defined? scout_usage
|
28
|
+
scout_usage
|
29
|
+
else
|
30
|
+
puts SOPT.doc
|
31
|
+
end
|
32
|
+
exit 0
|
33
|
+
end
|
34
|
+
|
35
|
+
raise ParameterException, "No workflow specified" if workflow.nil?
|
36
|
+
|
37
|
+
require 'scout/workflow'
|
38
|
+
|
39
|
+
wf = Workflow.require_workflow workflow
|
40
|
+
dir = $command_dir = wf.libdir.share.scout_commands.find
|
41
|
+
|
42
|
+
def prev_dir(prev)
|
43
|
+
scout_command_dir = $command_dir
|
44
|
+
|
45
|
+
prev.each do |previous_command|
|
46
|
+
scout_command_dir = scout_command_dir[previous_command]
|
47
|
+
end
|
48
|
+
|
49
|
+
scout_command_dir
|
50
|
+
end
|
51
|
+
|
52
|
+
def commands(prev)
|
53
|
+
scout_command_dir = prev_dir(prev)
|
54
|
+
|
55
|
+
command_file_dirs = scout_command_dir.find_all
|
56
|
+
command_files = command_file_dirs.collect{|d| d.glob('*') }.flatten
|
57
|
+
command_files.collect{|p| File.basename(p) }.uniq.reject{|p| p =~ /\.desc$/}.sort
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
prev = []
|
62
|
+
|
63
|
+
$previous_commands << ' cmd'
|
64
|
+
$previous_commands << ' ' << workflow
|
65
|
+
|
66
|
+
begin
|
67
|
+
while ARGV.any?
|
68
|
+
command = ARGV.shift
|
69
|
+
case
|
70
|
+
when File.directory?(dir[command].find)
|
71
|
+
prev << command
|
72
|
+
$previous_commands << command
|
73
|
+
dir = dir[command]
|
74
|
+
when File.directory?(dir[command].find)
|
75
|
+
prev << command
|
76
|
+
dir = dir[command]
|
77
|
+
when dir[command].exists?
|
78
|
+
load dir[command].find
|
79
|
+
exit 0
|
80
|
+
else
|
81
|
+
if command == 'bootstrap'
|
82
|
+
if wf.libdir["test_workflow.rb"].exists?
|
83
|
+
Log.info "No bootstrap for #{ workflow }, running test_workflow.rb instead"
|
84
|
+
CMD.cmd_log('ruby', wf.libdir["test_workflow.rb"].find)
|
85
|
+
else
|
86
|
+
Log.info "No bootstrap for #{ workflow }, running examples instead"
|
87
|
+
CMD.cmd_log("scout workflow example #{ workflow }")
|
88
|
+
exit 0
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
raise ParameterException, "Error: Command not understood: #{command}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
puts SOPT.doc
|
98
|
+
puts
|
99
|
+
puts Log.color :magenta, "## COMMANDS"
|
100
|
+
puts
|
101
|
+
puts Log.color :magenta, "Command:"
|
102
|
+
puts
|
103
|
+
puts " scout #{$previous_commands * " "} "
|
104
|
+
puts
|
105
|
+
puts Log.color :magenta, "Subcommands:"
|
106
|
+
puts
|
107
|
+
|
108
|
+
commands(prev).each do |command|
|
109
|
+
directory = File.directory? dir[command].find
|
110
|
+
if directory
|
111
|
+
puts " " << Log.color(:blue, command)
|
112
|
+
else
|
113
|
+
puts " " << command
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'scout'
|
4
|
+
require 'scout/workflow/deployment/queue'
|
5
|
+
require 'scout/workflow/deployment/orchestrator'
|
6
|
+
|
7
|
+
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
8
|
+
|
9
|
+
options = SOPT.setup <<EOF
|
10
|
+
|
11
|
+
Process the queue
|
12
|
+
|
13
|
+
$ #{$0} [<options>] ([<workflow>] [<task>] [<name>] | <filename>)
|
14
|
+
|
15
|
+
-h--help Print this help
|
16
|
+
-l--list List queue jobs
|
17
|
+
--continuous Process continuously
|
18
|
+
--produce_timer* Produce timer for sleeping
|
19
|
+
--produce_cpus* Cpus to use concurrently producing jobs
|
20
|
+
EOF
|
21
|
+
if options[:help]
|
22
|
+
if defined? scout_usage
|
23
|
+
scout_usage
|
24
|
+
else
|
25
|
+
puts SOPT.doc
|
26
|
+
end
|
27
|
+
exit 0
|
28
|
+
end
|
29
|
+
list, continuous = IndiferentHash.process_options options, :list, :continuous
|
30
|
+
|
31
|
+
queue_dir = Scout.var.queue
|
32
|
+
|
33
|
+
class TrayAgain < Exception; end
|
34
|
+
|
35
|
+
begin
|
36
|
+
if ARGV.empty?
|
37
|
+
files = queue_dir.glob("*/*/*")
|
38
|
+
if list
|
39
|
+
puts files * "\n"
|
40
|
+
exit
|
41
|
+
end
|
42
|
+
else
|
43
|
+
workflow, task, name = ARGV
|
44
|
+
|
45
|
+
# First deal with fixed files
|
46
|
+
if task.nil?
|
47
|
+
if Open.exists?(workflow)
|
48
|
+
Workflow.unqueue files.first
|
49
|
+
exit
|
50
|
+
|
51
|
+
else
|
52
|
+
files = queue_dir.glob("#{workflow}/*/*")
|
53
|
+
end
|
54
|
+
elsif name.nil?
|
55
|
+
files = queue_dir.glob("#{workflow}/#{task}/*")
|
56
|
+
else
|
57
|
+
files = queue_dir.glob("#{workflow}/#{task}/#{name}*")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
jobs = files.collect{|file| Workflow.queue_job(file) }
|
62
|
+
begin
|
63
|
+
options.keys.each do |key|
|
64
|
+
options[key.to_sym] = options.delete(key)
|
65
|
+
end
|
66
|
+
Workflow.produce(jobs, **options)
|
67
|
+
rescue Workflow::Orchestrator::NoWork
|
68
|
+
end
|
69
|
+
|
70
|
+
files.each do |f| Open.rm_rf f end
|
71
|
+
|
72
|
+
Workflow.job_cache.clear
|
73
|
+
|
74
|
+
if continuous
|
75
|
+
Log.debug "Continuous processing"
|
76
|
+
sleep 1
|
77
|
+
raise Workflow::Orchestrator::NoWork
|
78
|
+
end
|
79
|
+
rescue Workflow::Orchestrator::NoWork
|
80
|
+
retry
|
81
|
+
end
|
82
|
+
|
@@ -20,8 +20,9 @@ $ #{$0} [<options>] <workflow> <task>
|
|
20
20
|
--update Update jobs with newer dependencies
|
21
21
|
--deploy* Deploy mode: serial, local, or SLURM (default 'serial')
|
22
22
|
--fork Fork and return path
|
23
|
+
--load_inputs* Directory or file with inputs files to load
|
24
|
+
--save_inputs* Directory or tar.gz file path to store inputs
|
23
25
|
-jn--jobname* Name to use as job identifier
|
24
|
-
-li--load_inputs* Directory with inputs files to load
|
25
26
|
-pf--printpath Print the file path
|
26
27
|
-prov--provenance Print the step provenance
|
27
28
|
-cl--clean Clean the last step
|
@@ -40,8 +41,8 @@ task = workflow.tasks[task_name.to_sym] if task_name
|
|
40
41
|
|
41
42
|
options[:help] = true if task.nil?
|
42
43
|
|
43
|
-
help, provenance, clean, recursive_clean, clean_task, load_inputs, jobname, printpath, deploy, override_deps, do_fork = IndiferentHash.process_options options,
|
44
|
-
:help, :provenance, :clean, :recursive_clean, :clean_task, :load_inputs, :jobname, :printpath, :deploy, :override_deps, :fork,
|
44
|
+
help, provenance, clean, recursive_clean, clean_task, load_inputs, save_inputs, jobname, printpath, deploy, override_deps, do_fork = IndiferentHash.process_options options,
|
45
|
+
:help, :provenance, :clean, :recursive_clean, :clean_task, :load_inputs, :save_inputs, :jobname, :printpath, :deploy, :override_deps, :fork,
|
45
46
|
:deploy => 'serial'
|
46
47
|
|
47
48
|
if help
|
@@ -93,12 +94,23 @@ end
|
|
93
94
|
|
94
95
|
if provenance
|
95
96
|
puts Step.prov_report(job)
|
97
|
+
|
96
98
|
elsif do_fork
|
97
99
|
job.fork
|
98
100
|
puts job.path
|
99
101
|
exit 0
|
102
|
+
elsif save_inputs
|
103
|
+
puts job.save_inputs(save_inputs)
|
104
|
+
exit 0
|
100
105
|
else
|
106
|
+
|
101
107
|
case deploy
|
108
|
+
when "queue"
|
109
|
+
if ! job.done?
|
110
|
+
save_inputs = Scout.var.queue[workflow.to_s][task_name][job.clean_name].find
|
111
|
+
puts job.save_inputs(save_inputs)
|
112
|
+
exit
|
113
|
+
end
|
102
114
|
when "serial"
|
103
115
|
job.run(true)
|
104
116
|
when "local"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Databases describing people and their relationships.
|
2
|
+
|
3
|
+
# Brothers
|
4
|
+
|
5
|
+
Sibling relationships. The first of the pair is the Older
|
6
|
+
|
7
|
+
# Marriages
|
8
|
+
|
9
|
+
Marriages between people.
|
10
|
+
|
11
|
+
Date: Date when the marriage occurred
|
12
|
+
|
13
|
+
# Parents
|
14
|
+
|
15
|
+
List parents.
|
16
|
+
|
17
|
+
Type of parent: father or mother
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
+
|
4
|
+
require 'scout/knowledge_base'
|
5
|
+
class TestKnowledgebaseDesc < Test::Unit::TestCase
|
6
|
+
def test_brothers_registry
|
7
|
+
TmpFile.with_dir do |dir|
|
8
|
+
brothers = datafile_test(:person).brothers
|
9
|
+
kb = KnowledgeBase.new dir
|
10
|
+
kb.register :brothers, brothers, description: "Sibling relationships."
|
11
|
+
assert_equal "Sibling relationships.", kb.description(:brothers)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_brothers_README
|
16
|
+
TmpFile.with_dir do |dir|
|
17
|
+
brothers = datafile_test(:person).brothers
|
18
|
+
kb = KnowledgeBase.new dir
|
19
|
+
kb.register :brothers, brothers
|
20
|
+
kb.dir['brothers.md'].write "Sibling relationships."
|
21
|
+
assert_equal "Sibling relationships.", kb.description(:brothers)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_broters_kb_README
|
26
|
+
TmpFile.with_dir do |dir|
|
27
|
+
brothers = datafile_test(:person).brothers
|
28
|
+
kb = KnowledgeBase.new dir
|
29
|
+
kb.register :brothers, brothers
|
30
|
+
kb.dir['README.md'].write <<-EOF
|
31
|
+
Databases describing people and their relationships.
|
32
|
+
|
33
|
+
# Brothers
|
34
|
+
|
35
|
+
Sibling relationships.
|
36
|
+
EOF
|
37
|
+
assert_equal "Sibling relationships.", kb.description(:brothers)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_brothers_kb_source_README
|
42
|
+
TmpFile.with_dir do |dir|
|
43
|
+
brothers = datafile_test(:person).brothers
|
44
|
+
kb = KnowledgeBase.new dir
|
45
|
+
kb.register :brothers, brothers
|
46
|
+
assert_include kb.description(:brothers), "Sibling relationships."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_full_description
|
51
|
+
TmpFile.with_dir do |dir|
|
52
|
+
brothers = datafile_test(:person).brothers
|
53
|
+
kb = KnowledgeBase.new dir
|
54
|
+
kb.register :brothers, brothers
|
55
|
+
assert_include kb.markdown(:brothers), "Older"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -12,15 +12,15 @@ class TestWorkflowEntity < Test::Unit::TestCase
|
|
12
12
|
"Mi name is #{self}"
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
entity_task hi: :string do
|
16
16
|
"Hi. #{entity.introduction}"
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
list_task group_hi: :string do
|
20
20
|
"Here is the group: " + entity_list.hi * "; "
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
list_task bye: :array do
|
24
24
|
entity_list.collect do |e|
|
25
25
|
"Bye from #{e}"
|
26
26
|
end
|
data/test/test_helper.rb
CHANGED
@@ -20,6 +20,7 @@ require 'test/unit'
|
|
20
20
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
21
21
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
22
22
|
#require 'scout/helper/misc/development'
|
23
|
+
require 'scout-gear'
|
23
24
|
require 'scout/tmpfile'
|
24
25
|
require 'scout/log'
|
25
26
|
require 'scout/open'
|
@@ -54,6 +55,7 @@ class Test::Unit::TestCase
|
|
54
55
|
|
55
56
|
teardown do
|
56
57
|
Open.rm_rf tmpdir
|
58
|
+
Workflow.job_cache.clear
|
57
59
|
end
|
58
60
|
|
59
61
|
def self.datadir_test
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scout-gear
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 10.7.
|
4
|
+
version: 10.7.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-04-11 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: scout-essentials
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- lib/scout/entity/object.rb
|
115
115
|
- lib/scout/entity/property.rb
|
116
116
|
- lib/scout/knowledge_base.rb
|
117
|
+
- lib/scout/knowledge_base/description.rb
|
117
118
|
- lib/scout/knowledge_base/enrichment.rb
|
118
119
|
- lib/scout/knowledge_base/entity.rb
|
119
120
|
- lib/scout/knowledge_base/list.rb
|
@@ -167,12 +168,14 @@ files:
|
|
167
168
|
- lib/scout/workflow/definition.rb
|
168
169
|
- lib/scout/workflow/deployment.rb
|
169
170
|
- lib/scout/workflow/deployment/orchestrator.rb
|
171
|
+
- lib/scout/workflow/deployment/queue.rb
|
170
172
|
- lib/scout/workflow/deployment/trace.rb
|
171
173
|
- lib/scout/workflow/documentation.rb
|
172
174
|
- lib/scout/workflow/entity.rb
|
173
175
|
- lib/scout/workflow/exceptions.rb
|
174
176
|
- lib/scout/workflow/export.rb
|
175
177
|
- lib/scout/workflow/path.rb
|
178
|
+
- lib/scout/workflow/persist.rb
|
176
179
|
- lib/scout/workflow/step.rb
|
177
180
|
- lib/scout/workflow/step/archive.rb
|
178
181
|
- lib/scout/workflow/step/children.rb
|
@@ -209,11 +212,14 @@ files:
|
|
209
212
|
- scout_commands/log
|
210
213
|
- scout_commands/rbbt
|
211
214
|
- scout_commands/resource/produce
|
215
|
+
- scout_commands/resource/sync
|
212
216
|
- scout_commands/template
|
213
217
|
- scout_commands/update
|
218
|
+
- scout_commands/workflow/cmd
|
214
219
|
- scout_commands/workflow/info
|
215
220
|
- scout_commands/workflow/install
|
216
221
|
- scout_commands/workflow/list
|
222
|
+
- scout_commands/workflow/process
|
217
223
|
- scout_commands/workflow/prov
|
218
224
|
- scout_commands/workflow/task
|
219
225
|
- scout_commands/workflow/trace
|
@@ -223,6 +229,7 @@ files:
|
|
223
229
|
- share/software/install_helpers
|
224
230
|
- share/templates/command
|
225
231
|
- share/templates/workflow.rb
|
232
|
+
- test/data/person/README.md
|
226
233
|
- test/data/person/brothers
|
227
234
|
- test/data/person/identifiers
|
228
235
|
- test/data/person/marriages
|
@@ -235,6 +242,7 @@ files:
|
|
235
242
|
- test/scout/entity/test_named_array.rb
|
236
243
|
- test/scout/entity/test_object.rb
|
237
244
|
- test/scout/entity/test_property.rb
|
245
|
+
- test/scout/knowledge_base/test_description.rb
|
238
246
|
- test/scout/knowledge_base/test_enrichment.rb
|
239
247
|
- test/scout/knowledge_base/test_entity.rb
|
240
248
|
- test/scout/knowledge_base/test_list.rb
|