def trigger(on, workitem)
tree = tree()
err = h.applied_workitem['fields']['__error__']
handler = on == 'on_error' ? local_on_error(err) : h[on]
if on == 'on_error' && handler.to_s.match(/^!(.+)$/)
handler = $1
end
if handler.is_a?(Hash)
wi = handler['workitem']
fi = handler['fields']
me = handler['merge_in_fields']
workitem = if wi == 'applied' || me
h.applied_workitem
elsif wi
wi
else
workitem
end
workitem['fields'] = fi if fi
workitem['fields'].merge!(me) if me
end
if h.trigger && t = workitem['fields']["__#{h.trigger}__"]
handler = t
tree = h.supplanted['original_tree']
workitem = h.supplanted['applied_workitem']
end
if on == 'on_error' && handler.respond_to?(:match) && handler.match(/[,:\*]/)
return schedule_retries(handler, err)
end
new_tree = case handler
when Hash then handler['tree']
when Array then handler
when HandlerEntry then [ handler.action, {}, [] ]
else [ handler.to_s, {}, [] ]
end
handler = handler.action if handler.is_a?(HandlerEntry)
handler = handler.strip if handler.respond_to?(:strip)
if handler =~ /^can(cel|do)$/ && (on == 'on_cancel' || h.on_cancel == nil)
handler = handler == 'cancel' ? 'undo' : 'redo'
end
h.on_reply = nil if on == 'on_reply'
case handler
when 'redo', 'retry'
new_tree = tree
when 'undo', 'pass', ''
h.state = on == 'on_cancel' ? 'cancelled' : 'failed'
reply_to_parent(workitem); return
when 'cancel'
trigger('on_cancel', workitem); return
when 'cando'
h.on_reply = tree
trigger('on_cancel', workitem); return
when 'raise'
raise Ruote.constantize(err['class']), err['message'], err['trace']
when CommandExpression::REGEXP
hh = handler.split(' ')
command = hh.first
step = hh.last
h.state = nil
workitem['fields'][CommandMixin::F_COMMAND] = [ command, step ]
reply(workitem); return
end
workitem = h.applied_workitem if on == 'on_error'
r = try_unpersist
raise(
"failed to remove exp to supplant " +
"#{Ruote.to_storage_id(h.fei)} #{tree.first}"
) if r.respond_to?(:keys)
if new_tree[0].match(/^!(.+)$/); new_tree[0] = $1; end
new_tree[1]['_triggered'] = on
attributes.each { |k, v|
new_tree[1][k] = v if (k.match(/^on_/) && k != on) || k == 'tag'
}
@context.storage.put_msg(
'apply',
{ 'fei' => h.fei,
'parent_id' => h.parent_id,
'tree' => new_tree,
'workitem' => workitem,
'variables' => h.variables,
'trigger' => on,
'on_reply' => h.on_reply,
'supplanted' => {
'tree' => tree,
'original_tree' => original_tree,
'applied_workitem' => h.applied_workitem,
'variables' => h.variables
}})
end