flor 0.16.1 → 0.16.2
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/CHANGELOG.md +8 -0
- data/CREDITS.md +1 -0
- data/Makefile +1 -1
- data/README.md +82 -6
- data/lib/flor.rb +1 -1
- data/lib/flor/conf.rb +19 -6
- data/lib/flor/core/executor.rb +45 -16
- data/lib/flor/core/node.rb +4 -4
- data/lib/flor/core/procedure.rb +40 -0
- data/lib/flor/djan.rb +5 -2
- data/lib/flor/flor.rb +92 -7
- data/lib/flor/id.rb +19 -0
- data/lib/flor/migrations/0001_tables.rb +6 -6
- data/lib/flor/migrations/0005_pointer_content.rb +20 -0
- data/lib/flor/pcore/_apply.rb +103 -57
- data/lib/flor/pcore/_att.rb +15 -1
- data/lib/flor/pcore/_ref.rb +2 -1
- data/lib/flor/pcore/arith.rb +46 -9
- data/lib/flor/pcore/break.rb +1 -1
- data/lib/flor/pcore/case.rb +41 -0
- data/lib/flor/pcore/collect.rb +1 -1
- data/lib/flor/pcore/cursor.rb +1 -1
- data/lib/flor/pcore/define.rb +32 -6
- data/lib/flor/pcore/iterator.rb +12 -0
- data/lib/flor/pcore/on_cancel.rb +1 -1
- data/lib/flor/pcore/set.rb +14 -4
- data/lib/flor/punit/{ccollect.rb → c_collect.rb} +2 -2
- data/lib/flor/punit/c_each.rb +11 -0
- data/lib/flor/punit/c_for_each.rb +41 -0
- data/lib/flor/punit/c_iterator.rb +160 -0
- data/lib/flor/punit/c_map.rb +43 -0
- data/lib/flor/punit/concurrence.rb +43 -200
- data/lib/flor/punit/graft.rb +3 -2
- data/lib/flor/punit/m_ram.rb +281 -0
- data/lib/flor/unit.rb +1 -0
- data/lib/flor/unit/caller.rb +6 -1
- data/lib/flor/unit/executor.rb +17 -4
- data/lib/flor/unit/ganger.rb +12 -1
- data/lib/flor/unit/hloader.rb +251 -0
- data/lib/flor/unit/hook.rb +74 -15
- data/lib/flor/unit/hooker.rb +9 -12
- data/lib/flor/unit/loader.rb +41 -17
- data/lib/flor/unit/models.rb +54 -18
- data/lib/flor/unit/models/execution.rb +15 -4
- data/lib/flor/unit/models/pointer.rb +11 -0
- data/lib/flor/unit/scheduler.rb +126 -30
- data/lib/flor/unit/spooler.rb +5 -3
- data/lib/flor/unit/storage.rb +40 -13
- data/lib/flor/unit/waiter.rb +165 -26
- data/lib/flor/unit/wlist.rb +98 -5
- metadata +10 -4
- data/lib/flor/punit/cmap.rb +0 -112
data/lib/flor/unit/hook.rb
CHANGED
@@ -14,21 +14,13 @@ module Flor
|
|
14
14
|
|
15
15
|
def to_hook
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#correct_points(opts)
|
26
|
-
#
|
27
|
-
# Necessary since "cancel" gets interpreted as
|
28
|
-
# [ '_proc', { 'proc' => 'cancel' }, @line ]
|
29
|
-
# ...
|
30
|
-
|
31
|
-
[ "hook#{object_id}", opts, self, nil ]
|
17
|
+
if @h['class']
|
18
|
+
class_to_hook
|
19
|
+
elsif @h['instance']
|
20
|
+
instance_to_hook
|
21
|
+
else
|
22
|
+
classical_to_hook
|
23
|
+
end
|
32
24
|
end
|
33
25
|
|
34
26
|
def notify(executor, message)
|
@@ -56,6 +48,73 @@ module Flor
|
|
56
48
|
# return point[1]['proc'] if point.is_a?(Array) && point[0] == '_proc'
|
57
49
|
# point
|
58
50
|
# end
|
51
|
+
|
52
|
+
def extract_filters(h)
|
53
|
+
|
54
|
+
r = {}
|
55
|
+
r[:consumed] = h['consumed']
|
56
|
+
r[:point] = Flor.h_fetch_a(h, 'points', 'point', nil)
|
57
|
+
r[:nid] = Flor.h_fetch_a(h, 'nids', 'nid', nil)
|
58
|
+
r[:heap] = Flor.h_fetch_a(h, 'heaps', 'heap', nil)
|
59
|
+
r[:heat] = Flor.h_fetch_a(h, 'heats', 'heat', nil)
|
60
|
+
#opts[:name] = data['names']
|
61
|
+
|
62
|
+
r
|
63
|
+
end
|
64
|
+
|
65
|
+
def class_to_hook
|
66
|
+
|
67
|
+
i = Flor::Hook.instantiate(@unit, @h['class'])
|
68
|
+
|
69
|
+
h = @h.dup
|
70
|
+
h.merge!(Flor.to_string_keyed_hash(i.opts)) if i.respond_to?(:opts)
|
71
|
+
opts = extract_filters(h)
|
72
|
+
|
73
|
+
[ "hooc#{object_id}", opts, i, nil ]
|
74
|
+
end
|
75
|
+
|
76
|
+
def instance_to_hook
|
77
|
+
|
78
|
+
i = @h['instance']
|
79
|
+
|
80
|
+
h = @h.dup
|
81
|
+
h.merge!(Flor.to_string_keyed_hash(i.opts)) if i.respond_to?(:opts)
|
82
|
+
opts = extract_filters(h)
|
83
|
+
|
84
|
+
[ "hooi#{object_id}", opts, i, nil ]
|
85
|
+
end
|
86
|
+
|
87
|
+
def classical_to_hook
|
88
|
+
|
89
|
+
opts = extract_filters(@h)
|
90
|
+
|
91
|
+
#correct_points(opts)
|
92
|
+
#
|
93
|
+
# Necessary since "cancel" gets interpreted as
|
94
|
+
# [ '_proc', { 'proc' => 'cancel' }, @line ]
|
95
|
+
# ...
|
96
|
+
|
97
|
+
[ "hook#{object_id}", opts, self, nil ]
|
98
|
+
end
|
99
|
+
|
100
|
+
class << self
|
101
|
+
|
102
|
+
def instantiate(unit, hook_class)
|
103
|
+
|
104
|
+
c =
|
105
|
+
case hook_class
|
106
|
+
when String then Flor.const_get(hook_class)
|
107
|
+
else hook_class
|
108
|
+
end
|
109
|
+
a =
|
110
|
+
case i = c.instance_method(:initialize).arity
|
111
|
+
when 0, 1 then [ unit ][0, i]
|
112
|
+
else []
|
113
|
+
end
|
114
|
+
|
115
|
+
c.new(*a)
|
116
|
+
end
|
117
|
+
end
|
59
118
|
end
|
60
119
|
end
|
61
120
|
|
data/lib/flor/unit/hooker.rb
CHANGED
@@ -9,6 +9,14 @@ module Flor
|
|
9
9
|
|
10
10
|
@unit = unit
|
11
11
|
|
12
|
+
class << unit
|
13
|
+
|
14
|
+
def hook(*args, &block)
|
15
|
+
|
16
|
+
@hooker.add(*args, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
12
20
|
@hooks = []
|
13
21
|
end
|
14
22
|
|
@@ -46,7 +54,7 @@ module Flor
|
|
46
54
|
end
|
47
55
|
end
|
48
56
|
|
49
|
-
hook =
|
57
|
+
hook = Flor::Hook.instantiate(@unit, hook) if hook.is_a?(Class)
|
50
58
|
|
51
59
|
@hooks << [ name, opts, hook, block ]
|
52
60
|
end
|
@@ -73,17 +81,6 @@ module Flor
|
|
73
81
|
|
74
82
|
protected
|
75
83
|
|
76
|
-
def instantiate_hook(hook_class)
|
77
|
-
|
78
|
-
a =
|
79
|
-
case i = hook_class.instance_method(:initialize).arity
|
80
|
-
when 0, 1 then [ @unit ][0, i]
|
81
|
-
else []
|
82
|
-
end
|
83
|
-
|
84
|
-
hook_class.new(*a)
|
85
|
-
end
|
86
|
-
|
87
84
|
def o(opts, *keys)
|
88
85
|
|
89
86
|
array = false
|
data/lib/flor/unit/loader.rb
CHANGED
@@ -23,7 +23,7 @@ module Flor
|
|
23
23
|
Dir[File.join(@root, '**/*.json')]
|
24
24
|
.select { |f| f.index('/etc/variables/') }
|
25
25
|
.collect { |pa| [ pa, expose_d(pa, {}) ] }
|
26
|
-
.select { |pa, d|
|
26
|
+
.select { |pa, d| Flor.sub_domain?(d, domain) }
|
27
27
|
.sort_by { |pa, d| d.count('.') }
|
28
28
|
.inject({}) { |vars, (pa, _)| vars.merge!(eval(pa, {})) }
|
29
29
|
end
|
@@ -48,7 +48,7 @@ module Flor
|
|
48
48
|
path, _, _ = (Dir[File.join(@root, '**/*.{flo,flor}')])
|
49
49
|
.select { |f| f.index('/lib/') }
|
50
50
|
.collect { |pa| [ pa, *expose_dn(pa, opts) ] }
|
51
|
-
.select { |pa, d, n| n == name &&
|
51
|
+
.select { |pa, d, n| n == name && Flor.sub_domain?(d, domain) }
|
52
52
|
.sort_by { |pa, d, n| d.count('.') }
|
53
53
|
.last
|
54
54
|
|
@@ -62,12 +62,12 @@ module Flor
|
|
62
62
|
|
63
63
|
domain, name = split_dn(domain, name)
|
64
64
|
|
65
|
-
pat, _, nam = Dir[File.join(@root, '**/*.json')]
|
65
|
+
pat, _, nam = Dir[File.join(@root, '**/*.{json,rb}')]
|
66
66
|
.select { |pa| pa.index('/lib/taskers/') }
|
67
67
|
.collect { |pa| [ pa, *expose_dn(pa, {}) ] }
|
68
68
|
.select { |pa, d, n|
|
69
|
-
|
70
|
-
(n == name &&
|
69
|
+
Flor.sub_domain?([ d, n ].join('.'), domain) ||
|
70
|
+
(n == name && Flor.sub_domain?(d, domain)) }
|
71
71
|
.sort_by { |pa, d, n| d.count('.') }
|
72
72
|
.last
|
73
73
|
|
@@ -87,7 +87,7 @@ module Flor
|
|
87
87
|
conf
|
88
88
|
end
|
89
89
|
|
90
|
-
def hooks(domain
|
90
|
+
def hooks(domain)
|
91
91
|
|
92
92
|
# NB: do not relativize path, because Ruby load path != cwd,
|
93
93
|
# stay absolute for `require` and `load`
|
@@ -95,7 +95,7 @@ module Flor
|
|
95
95
|
Dir[File.join(@root, '**/*.json')]
|
96
96
|
.select { |f| f.index('/lib/hooks/') }
|
97
97
|
.collect { |pa| [ pa, expose_d(pa, {}) ] }
|
98
|
-
.select { |pa, d|
|
98
|
+
.select { |pa, d| Flor.sub_domain?(d, domain) }
|
99
99
|
.sort_by { |pa, d| d.count('.') }
|
100
100
|
.collect { |pa, d|
|
101
101
|
eval(pa, {}).each_with_index { |h, i|
|
@@ -111,15 +111,6 @@ module Flor
|
|
111
111
|
|
112
112
|
protected
|
113
113
|
|
114
|
-
# is da a subdomain of db?
|
115
|
-
#
|
116
|
-
def is_subdomain?(da, db)
|
117
|
-
|
118
|
-
da == db ||
|
119
|
-
db == '' ||
|
120
|
-
da[0, db.length + 1] == db + '.'
|
121
|
-
end
|
122
|
-
|
123
114
|
def split_dn(domain, name)
|
124
115
|
|
125
116
|
if name
|
@@ -145,7 +136,7 @@ module Flor
|
|
145
136
|
.sub(libregex, '/')
|
146
137
|
.sub(/\/\z/, '')
|
147
138
|
.sub(/\/(flo|flor|dot|hooks)\.json\z/, '')
|
148
|
-
.sub(/\.(flo|flor|json)\z/, '')
|
139
|
+
.sub(/\.(flo|flor|json|rb)\z/, '')
|
149
140
|
.sub(/\A\//, '')
|
150
141
|
.gsub(/\//, '.')
|
151
142
|
end
|
@@ -163,6 +154,9 @@ module Flor
|
|
163
154
|
|
164
155
|
def eval(path, context)
|
165
156
|
|
157
|
+
ext =
|
158
|
+
File.extname(path)
|
159
|
+
|
166
160
|
src =
|
167
161
|
@mutex.synchronize do
|
168
162
|
|
@@ -171,13 +165,43 @@ module Flor
|
|
171
165
|
|
172
166
|
if val && mt1 == mt0
|
173
167
|
val
|
168
|
+
elsif ext == '.rb'
|
169
|
+
(@cache[path] = [ File.read(path), mt1 ]).first
|
174
170
|
else
|
175
171
|
(@cache[path] = [ Flor::ConfExecutor.load(path), mt1 ]).first
|
176
172
|
end
|
177
173
|
end
|
178
174
|
|
175
|
+
case ext
|
176
|
+
when '.rb' then eval_ruby(path, src, context)
|
177
|
+
else eval_json(path, src, context)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def eval_json(path, src, context)
|
182
|
+
|
179
183
|
Flor::ConfExecutor.interpret(path, src, context)
|
180
184
|
end
|
185
|
+
|
186
|
+
def eval_ruby(path, src, context)
|
187
|
+
|
188
|
+
ks = context.keys.select { |k| k.match(/\A[a-z][a-zA-Z0-9_]+\z/) }
|
189
|
+
|
190
|
+
s = StringIO.new
|
191
|
+
s << "lambda {\n"
|
192
|
+
ks.each { |k| s << k << " = " << context[k].inspect << "\n" }
|
193
|
+
s << src
|
194
|
+
s << "\n}.call\n"
|
195
|
+
|
196
|
+
r = Kernel.module_eval(s.string, path, - ks.size)
|
197
|
+
|
198
|
+
r = JSON.parse(JSON.dump(r)) #if r.keys.find { |k| k.is_a?(Symbol) }
|
199
|
+
#
|
200
|
+
# so that symbols may be used in the .rb file, but plain JSON-like
|
201
|
+
# string keys are on the output
|
202
|
+
|
203
|
+
r.merge!('_path' => path)
|
204
|
+
end
|
181
205
|
end
|
182
206
|
end
|
183
207
|
|
data/lib/flor/unit/models.rb
CHANGED
@@ -28,10 +28,46 @@ module Flor
|
|
28
28
|
|
29
29
|
self.require_valid_table = false
|
30
30
|
|
31
|
+
class << self
|
32
|
+
|
33
|
+
attr_accessor :unit
|
34
|
+
end
|
35
|
+
|
36
|
+
def unit; self.class.unit; end
|
37
|
+
def storage; unit.storage; end
|
38
|
+
|
39
|
+
# Return a Flor::Execution instance linked to this model
|
40
|
+
#
|
41
|
+
def execution(reload=false)
|
42
|
+
|
43
|
+
exid = @values[:exid]; return nil unless exid
|
44
|
+
|
45
|
+
@execution = nil if reload
|
46
|
+
|
47
|
+
@execution ||= unit.executions[exid: exid]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the node hash linked to this model
|
51
|
+
#
|
52
|
+
def node(reload=false)
|
53
|
+
|
54
|
+
nid = @values[:nid]; return nil unless nid
|
55
|
+
exe = execution(reload); return nil unless exe
|
56
|
+
|
57
|
+
nodes = exe.data['nodes']; return nil unless nodes
|
58
|
+
nodes[nid]
|
59
|
+
end
|
60
|
+
|
61
|
+
def payload(reload=false)
|
62
|
+
|
63
|
+
nod = node(reload)
|
64
|
+
nod ? nod['payload'] : nil
|
65
|
+
end
|
66
|
+
|
31
67
|
def _data
|
32
68
|
|
33
69
|
d = Flor::Storage.from_blob(content)
|
34
|
-
d['id'] = id
|
70
|
+
d['id'] = id if d.is_a?(Hash)
|
35
71
|
|
36
72
|
d
|
37
73
|
end
|
@@ -59,31 +95,31 @@ module Flor
|
|
59
95
|
dir = File.dirname(__FILE__)
|
60
96
|
MODELS.each { |m| require File.join(dir, 'models', "#{m.to_s[0..-2]}.rb") }
|
61
97
|
|
62
|
-
|
98
|
+
def self.add_model(key, parent_module=Flor, table_prefix='flor_')
|
63
99
|
|
64
|
-
|
100
|
+
Flor::Storage.send(:define_method, key) do
|
65
101
|
|
66
|
-
|
102
|
+
s = self
|
103
|
+
c = Flor.to_camel_case(key.to_s[0..-2])
|
67
104
|
|
68
|
-
|
69
|
-
|
105
|
+
@models[key] ||=
|
106
|
+
parent_module.const_set(
|
107
|
+
"#{c}#{@db.object_id.to_s.gsub('-', 'M')}",
|
108
|
+
Class.new(parent_module.const_get(c)) do
|
109
|
+
self.dataset = s.db["#{table_prefix}#{key}".to_sym]
|
110
|
+
self.unit = s.unit
|
111
|
+
end)
|
112
|
+
end
|
70
113
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
Class.new(Flor.const_get(c)) do
|
75
|
-
self.dataset = s.db["flor_#{k}".to_sym]
|
76
|
-
end)
|
77
|
-
end
|
114
|
+
Flor::Scheduler.send(:define_method, key) do
|
115
|
+
|
116
|
+
@storage.send(key)
|
78
117
|
end
|
79
118
|
end
|
80
119
|
|
81
|
-
|
120
|
+
MODELS.each do |k|
|
82
121
|
|
83
|
-
|
84
|
-
|
85
|
-
define_method(k) { @storage.send(k) }
|
86
|
-
end
|
122
|
+
add_model(k)
|
87
123
|
end
|
88
124
|
end
|
89
125
|
|
@@ -20,6 +20,9 @@ module Flor
|
|
20
20
|
|
21
21
|
def nodes; data['nodes']; end
|
22
22
|
def zero_node; nodes['0']; end
|
23
|
+
def closing_messages; data['closing_messages']; end
|
24
|
+
|
25
|
+
def execution(reload=false); self; end
|
23
26
|
|
24
27
|
def tags
|
25
28
|
|
@@ -45,14 +48,22 @@ module Flor
|
|
45
48
|
|
46
49
|
tree = nodes['0']['tree']
|
47
50
|
|
48
|
-
nodes.each do |nid, n|
|
49
|
-
|
50
|
-
|
51
|
-
end
|
51
|
+
#nodes.each do |nid, n|
|
52
|
+
# next if nid == '0'
|
53
|
+
# t = n['tree']; next unless t
|
54
|
+
#end
|
55
|
+
#
|
56
|
+
# FIXME
|
52
57
|
|
53
58
|
tree
|
54
59
|
end
|
55
60
|
|
61
|
+
def lookup_tree(nid)
|
62
|
+
|
63
|
+
Flor::Node.new(self.data, nodes[nid], nil)
|
64
|
+
.lookup_tree(nid)
|
65
|
+
end
|
66
|
+
|
56
67
|
def zero_variables
|
57
68
|
|
58
69
|
zero_node['vars']
|
@@ -12,6 +12,7 @@ module Flor
|
|
12
12
|
# String :type, null: false # task, tasked, tag, var
|
13
13
|
# String :name, null: false # task name, tasked name, tag name, var name
|
14
14
|
# String :value
|
15
|
+
# File :content
|
15
16
|
# String :ctime, null: false
|
16
17
|
#
|
17
18
|
# # no :status, no :mtime
|
@@ -26,6 +27,16 @@ module Flor
|
|
26
27
|
# #unique [ :exid, :type, :name, :value ]
|
27
28
|
# # we don't care, pointers are cleaned anyway when the flow dies
|
28
29
|
#end
|
30
|
+
|
31
|
+
# If the pointer is a "var" pointer, returns the full value
|
32
|
+
# for the variable, as fund in the execution's node "0".
|
33
|
+
#
|
34
|
+
def full_value
|
35
|
+
|
36
|
+
return nil unless type == 'var'
|
37
|
+
|
38
|
+
node['vars'][name]
|
39
|
+
end
|
29
40
|
end
|
30
41
|
end
|
31
42
|
|
data/lib/flor/unit/scheduler.rb
CHANGED
@@ -111,11 +111,6 @@ module Flor
|
|
111
111
|
@ganger.shutdown
|
112
112
|
end
|
113
113
|
|
114
|
-
def hook(*args, &block)
|
115
|
-
|
116
|
-
@hooker.add(*args, &block)
|
117
|
-
end
|
118
|
-
|
119
114
|
def on_start_exc(e)
|
120
115
|
|
121
116
|
io = StringIO.new
|
@@ -182,13 +177,9 @@ module Flor
|
|
182
177
|
|
183
178
|
source, domain, flow_name =
|
184
179
|
if df = Flor.split_flow_name(source_or_path)
|
185
|
-
[ source_or_path,
|
186
|
-
opts[:domain] || df[0],
|
187
|
-
df[1] ]
|
180
|
+
[ source_or_path, opts[:domain] || df[0], df[1] ]
|
188
181
|
else
|
189
|
-
[ source_or_path,
|
190
|
-
opts[:domain] || @conf['domain'] || 'domain0',
|
191
|
-
nil ]
|
182
|
+
[ source_or_path, opts[:domain] || @conf['domain'] || 'domain0', nil ]
|
192
183
|
end
|
193
184
|
|
194
185
|
fail ArgumentError.new(
|
@@ -280,6 +271,68 @@ module Flor
|
|
280
271
|
end
|
281
272
|
alias reapply re_apply
|
282
273
|
|
274
|
+
def add_branches(exid, *as)
|
275
|
+
|
276
|
+
m = prepare_message('add-branches', [ exid, *as ]).first
|
277
|
+
|
278
|
+
exe = @storage.executions[exid: m['exid']]
|
279
|
+
pnid = m['nid']
|
280
|
+
ptree = exe.lookup_tree(pnid)
|
281
|
+
|
282
|
+
fail ArgumentError.new(
|
283
|
+
"parent #{pnid} is a leaf, cannot add branch at #{tnid}"
|
284
|
+
) unless ptree[1].is_a?(Array)
|
285
|
+
#
|
286
|
+
# not likely to happen, since leaves reply immediately
|
287
|
+
|
288
|
+
size = ptree[1].size
|
289
|
+
tnid = (m['tnid'] ||= Flor.make_child_nid(pnid, size))
|
290
|
+
|
291
|
+
cid = Flor.child_id(tnid)
|
292
|
+
|
293
|
+
tide, tcid = nil
|
294
|
+
(0..size - 1).reverse_each do |i|
|
295
|
+
tcid = Flor.make_child_nid(pnid, i)
|
296
|
+
next unless exe.nodes[tcid]
|
297
|
+
tide = i; break
|
298
|
+
end
|
299
|
+
|
300
|
+
fail ArgumentError.new(
|
301
|
+
"target #{tnid} too low, execution has already reached #{tcid}"
|
302
|
+
) if tide && cid < tide
|
303
|
+
|
304
|
+
fail ArgumentError.new(
|
305
|
+
"target #{tnid} is off by #{cid - size}, " +
|
306
|
+
"node #{pnid} has #{size} branch#{size == 1 ? '' : 'es'}"
|
307
|
+
) if cid > size
|
308
|
+
|
309
|
+
queue(m)
|
310
|
+
end
|
311
|
+
alias add_branch add_branches
|
312
|
+
|
313
|
+
def add_iterations(exid, *as)
|
314
|
+
|
315
|
+
m = prepare_message('add-iterations', [ exid, *as ]).first
|
316
|
+
|
317
|
+
exe = @storage.executions[exid: m['exid']]
|
318
|
+
nid = m['nid']
|
319
|
+
|
320
|
+
fail ArgumentError.new(
|
321
|
+
"cannot add iteration to missing execution #{m['exid'].inspect}"
|
322
|
+
) unless exe
|
323
|
+
|
324
|
+
fail ArgumentError.new(
|
325
|
+
"missing nid: or pnid:"
|
326
|
+
) unless nid
|
327
|
+
|
328
|
+
fail ArgumentError.new(
|
329
|
+
"cannot add iteration to missing node #{nid.inspect}"
|
330
|
+
) unless exe.lookup_tree(nid)
|
331
|
+
|
332
|
+
queue(m)
|
333
|
+
end
|
334
|
+
alias add_iteration add_iterations
|
335
|
+
|
283
336
|
def schedule(message)
|
284
337
|
|
285
338
|
@storage.put_timer(message)
|
@@ -367,20 +420,6 @@ module Flor
|
|
367
420
|
puts on_start_exc(ex)
|
368
421
|
end
|
369
422
|
|
370
|
-
def prepare_re_apply_messages(msg, opts)
|
371
|
-
|
372
|
-
fail ArgumentError.new("missing 'payload' to re_apply") \
|
373
|
-
unless msg['payload']
|
374
|
-
|
375
|
-
t = Flor.parse(opts[:tree], 're_apply', {})
|
376
|
-
|
377
|
-
[ { 'point' => 'execute',
|
378
|
-
'exid' => msg['exid'], 'nid' => msg['nid'],
|
379
|
-
'from' => 'parent',
|
380
|
-
'tree' => t,
|
381
|
-
'payload' => msg['payload'] } ]
|
382
|
-
end
|
383
|
-
|
384
423
|
def prepare_message(point, args)
|
385
424
|
|
386
425
|
h =
|
@@ -394,11 +433,6 @@ module Flor
|
|
394
433
|
msg = { 'point' => point }
|
395
434
|
opts = {}
|
396
435
|
|
397
|
-
if point == 'kill'
|
398
|
-
msg['point'] = 'cancel'
|
399
|
-
msg['flavour'] = 'kill'
|
400
|
-
end
|
401
|
-
|
402
436
|
h.each do |k, v|
|
403
437
|
if %w[ exid name nid payload on_receive_last ].include?(k)
|
404
438
|
msg[k] = v
|
@@ -407,7 +441,30 @@ module Flor
|
|
407
441
|
end
|
408
442
|
end
|
409
443
|
|
444
|
+
if point == 'kill'
|
445
|
+
|
446
|
+
msg['point'] = 'cancel'
|
447
|
+
msg['flavour'] = 'kill'
|
448
|
+
|
449
|
+
elsif point == 'add-branches'
|
450
|
+
|
451
|
+
msg['point'] = 'add'
|
452
|
+
msg['trees'] = prepare_trees(opts)
|
453
|
+
|
454
|
+
msg['tnid'] = tnid =
|
455
|
+
opts.delete(:tnid) || msg.delete('nid')
|
456
|
+
msg['nid'] =
|
457
|
+
msg.delete('nid') || opts.delete(:pnid) || Flor.parent_nid(tnid)
|
458
|
+
|
459
|
+
elsif point == 'add-iterations'
|
460
|
+
|
461
|
+
msg['point'] = 'add'
|
462
|
+
msg['elements'] = prepare_elements(opts)
|
463
|
+
msg['nid'] = msg.delete('nid') || opts.delete(:pnid)
|
464
|
+
end
|
465
|
+
|
410
466
|
if opts[:re_apply]
|
467
|
+
|
411
468
|
msg['on_receive_last'] = prepare_re_apply_messages(msg, opts)
|
412
469
|
end
|
413
470
|
|
@@ -419,6 +476,45 @@ module Flor
|
|
419
476
|
[ msg, opts ]
|
420
477
|
end
|
421
478
|
|
479
|
+
def prepare_trees(opts)
|
480
|
+
|
481
|
+
fname = Flor.caller_fname
|
482
|
+
|
483
|
+
ts = (opts[:trees] || [ opts[:tree] ].compact)
|
484
|
+
.collect { |t| Flor.parse(t, fname, {}) }
|
485
|
+
|
486
|
+
fail ArgumentError.new('missing trees: or tree:') if ts.empty?
|
487
|
+
|
488
|
+
ts
|
489
|
+
end
|
490
|
+
|
491
|
+
def prepare_elements(opts)
|
492
|
+
|
493
|
+
elts =
|
494
|
+
opts[:elements] || opts[:elts] ||
|
495
|
+
opts[:element] || opts[:elt]
|
496
|
+
|
497
|
+
fail ArgumentError.new('missing elements: or element:') unless elts
|
498
|
+
|
499
|
+
elts = [ elts ] unless elts.is_a?(Array)
|
500
|
+
|
501
|
+
elts
|
502
|
+
end
|
503
|
+
|
504
|
+
def prepare_re_apply_messages(msg, opts)
|
505
|
+
|
506
|
+
fail ArgumentError.new("missing 'payload' to re_apply") \
|
507
|
+
unless msg['payload']
|
508
|
+
|
509
|
+
t = Flor.parse(opts[:tree], Flor.caller_fname, {})
|
510
|
+
|
511
|
+
[ { 'point' => 'execute',
|
512
|
+
'exid' => msg['exid'], 'nid' => msg['nid'],
|
513
|
+
'from' => 'parent',
|
514
|
+
'tree' => t,
|
515
|
+
'payload' => msg['payload'] } ]
|
516
|
+
end
|
517
|
+
|
422
518
|
def make_idle_message
|
423
519
|
|
424
520
|
m = {}
|