dynflow 0.3.0 → 0.4.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.
- data/lib/dynflow.rb +2 -1
- data/lib/dynflow/action.rb +271 -101
- data/lib/dynflow/action/format.rb +4 -4
- data/lib/dynflow/action/progress.rb +8 -8
- data/lib/dynflow/execution_plan.rb +14 -15
- data/lib/dynflow/execution_plan/output_reference.rb +56 -23
- data/lib/dynflow/execution_plan/steps/abstract.rb +1 -3
- data/lib/dynflow/execution_plan/steps/abstract_flow_step.rb +0 -17
- data/lib/dynflow/execution_plan/steps/error.rb +35 -11
- data/lib/dynflow/execution_plan/steps/finalize_step.rb +1 -1
- data/lib/dynflow/execution_plan/steps/plan_step.rb +8 -3
- data/lib/dynflow/execution_plan/steps/run_step.rb +1 -1
- data/lib/dynflow/listeners/socket.rb +0 -1
- data/lib/dynflow/middleware.rb +0 -1
- data/lib/dynflow/middleware/world.rb +1 -1
- data/lib/dynflow/persistence.rb +2 -5
- data/lib/dynflow/serializable.rb +24 -11
- data/lib/dynflow/testing/assertions.rb +5 -5
- data/lib/dynflow/testing/dummy_execution_plan.rb +1 -1
- data/lib/dynflow/testing/dummy_planned_action.rb +2 -1
- data/lib/dynflow/testing/dummy_world.rb +4 -0
- data/lib/dynflow/testing/factories.rb +18 -10
- data/lib/dynflow/version.rb +1 -1
- data/lib/dynflow/world.rb +35 -21
- data/test/action_test.rb +50 -76
- data/test/clock_test.rb +4 -4
- data/test/execution_plan_test.rb +1 -1
- data/test/executor_test.rb +3 -2
- data/test/remote_via_socket_test.rb +11 -9
- data/test/support/code_workflow_example.rb +2 -3
- data/test/test_helper.rb +1 -1
- data/test/testing_test.rb +3 -3
- metadata +2 -8
- data/lib/dynflow/action/finalize_phase.rb +0 -20
- data/lib/dynflow/action/flow_phase.rb +0 -44
- data/lib/dynflow/action/plan_phase.rb +0 -87
- data/lib/dynflow/action/presenter.rb +0 -51
- data/lib/dynflow/action/run_phase.rb +0 -45
- data/lib/dynflow/middleware/action.rb +0 -9
@@ -24,7 +24,7 @@ module Support
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def summary
|
27
|
-
triages =
|
27
|
+
triages = execution_plan.actions.find_all do |action|
|
28
28
|
action.is_a? Triage
|
29
29
|
end
|
30
30
|
assignees = triages.map do |triage|
|
@@ -33,7 +33,6 @@ module Support
|
|
33
33
|
end.compact.uniq
|
34
34
|
{ assignees: assignees }
|
35
35
|
end
|
36
|
-
|
37
36
|
end
|
38
37
|
|
39
38
|
class Slow < Dynflow::Action
|
@@ -274,7 +273,7 @@ module Support
|
|
274
273
|
end
|
275
274
|
|
276
275
|
def poll_external_task
|
277
|
-
progress = external_task
|
276
|
+
progress = external_task.fetch(:progress)
|
278
277
|
new_progress = if progress == 30
|
279
278
|
if input[:text] =~ /cancel-external/
|
280
279
|
progress
|
data/test/test_helper.rb
CHANGED
data/test/testing_test.rb
CHANGED
@@ -14,7 +14,7 @@ module Dynflow
|
|
14
14
|
action = create_and_plan_action CWE::DummyHeavyProgress, input
|
15
15
|
|
16
16
|
action.must_be_kind_of CWE::DummyHeavyProgress
|
17
|
-
action.
|
17
|
+
action.phase.must_equal Action::Plan
|
18
18
|
action.input.must_equal input
|
19
19
|
action.execution_plan.must_be_kind_of Testing::DummyExecutionPlan
|
20
20
|
action.state.must_equal :success
|
@@ -29,7 +29,7 @@ module Dynflow
|
|
29
29
|
action = run_action plan
|
30
30
|
|
31
31
|
action.must_be_kind_of CWE::DummyHeavyProgress
|
32
|
-
action.
|
32
|
+
action.phase.must_equal Action::Run
|
33
33
|
action.input.must_equal input
|
34
34
|
action.world.must_equal plan.world
|
35
35
|
action.run_step_id.wont_equal action.plan_step_id
|
@@ -67,7 +67,7 @@ module Dynflow
|
|
67
67
|
action = finalize_action run
|
68
68
|
|
69
69
|
action.must_be_kind_of CWE::DummyHeavyProgress
|
70
|
-
action.
|
70
|
+
action.phase.must_equal Action::Finalize
|
71
71
|
action.input.must_equal input
|
72
72
|
action.output.must_equal run.output
|
73
73
|
action.world.must_equal plan.world
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-02-
|
12
|
+
date: 2014-02-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -226,15 +226,10 @@ files:
|
|
226
226
|
- lib/dynflow.rb
|
227
227
|
- lib/dynflow/action.rb
|
228
228
|
- lib/dynflow/action/cancellable_polling.rb
|
229
|
-
- lib/dynflow/action/finalize_phase.rb
|
230
|
-
- lib/dynflow/action/flow_phase.rb
|
231
229
|
- lib/dynflow/action/format.rb
|
232
230
|
- lib/dynflow/action/missing.rb
|
233
|
-
- lib/dynflow/action/plan_phase.rb
|
234
231
|
- lib/dynflow/action/polling.rb
|
235
|
-
- lib/dynflow/action/presenter.rb
|
236
232
|
- lib/dynflow/action/progress.rb
|
237
|
-
- lib/dynflow/action/run_phase.rb
|
238
233
|
- lib/dynflow/action/suspended.rb
|
239
234
|
- lib/dynflow/clock.rb
|
240
235
|
- lib/dynflow/daemon.rb
|
@@ -282,7 +277,6 @@ files:
|
|
282
277
|
- lib/dynflow/logger_adapters/simple.rb
|
283
278
|
- lib/dynflow/micro_actor.rb
|
284
279
|
- lib/dynflow/middleware.rb
|
285
|
-
- lib/dynflow/middleware/action.rb
|
286
280
|
- lib/dynflow/middleware/register.rb
|
287
281
|
- lib/dynflow/middleware/resolver.rb
|
288
282
|
- lib/dynflow/middleware/stack.rb
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Dynflow
|
2
|
-
module Action::FinalizePhase
|
3
|
-
|
4
|
-
def self.included(base)
|
5
|
-
base.send(:include, Action::FlowPhase)
|
6
|
-
base.send(:attr_reader, :output)
|
7
|
-
end
|
8
|
-
|
9
|
-
def execute
|
10
|
-
self.state = :running
|
11
|
-
save_state
|
12
|
-
with_error_handling do
|
13
|
-
world.middleware.execute(:finalize, self) do
|
14
|
-
finalize
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Dynflow
|
2
|
-
module Action::FlowPhase
|
3
|
-
|
4
|
-
def self.included(base)
|
5
|
-
base.extend(ClassMethods)
|
6
|
-
base.send(:attr_reader, :input)
|
7
|
-
end
|
8
|
-
|
9
|
-
def initialize(attributes, world)
|
10
|
-
super attributes, world
|
11
|
-
|
12
|
-
indifferent_access_hash_variable_set :input, deserialize_references(attributes[:input])
|
13
|
-
indifferent_access_hash_variable_set :output, attributes[:output] || {}
|
14
|
-
end
|
15
|
-
|
16
|
-
def to_hash
|
17
|
-
super.merge recursive_to_hash(input: input,
|
18
|
-
output: output)
|
19
|
-
end
|
20
|
-
|
21
|
-
def deserialize_references(value)
|
22
|
-
case value
|
23
|
-
when Hash
|
24
|
-
if value[:class] == "Dynflow::ExecutionPlan::OutputReference"
|
25
|
-
ExecutionPlan::OutputReference.new_from_hash(value)
|
26
|
-
else
|
27
|
-
value.reduce(HashWithIndifferentAccess.new) do |h, (key, val)|
|
28
|
-
h.update(key => deserialize_references(val))
|
29
|
-
end
|
30
|
-
end
|
31
|
-
when Array
|
32
|
-
value.map { |val| deserialize_references(val) }
|
33
|
-
else
|
34
|
-
value
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
module ClassMethods
|
39
|
-
def new_from_hash(hash, step, world)
|
40
|
-
new(hash.merge(step: step), world)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
module Dynflow
|
2
|
-
module Action::PlanPhase
|
3
|
-
attr_reader :execution_plan, :trigger
|
4
|
-
|
5
|
-
def self.included(base)
|
6
|
-
base.attr_indifferent_access_hash :input
|
7
|
-
end
|
8
|
-
|
9
|
-
def initialize(attributes, execution_plan, trigger)
|
10
|
-
super attributes, execution_plan.world
|
11
|
-
plan_step_id || raise(ArgumentError, 'missing plan_step_id')
|
12
|
-
|
13
|
-
self.input = attributes[:input] || {}
|
14
|
-
@execution_plan = Type! execution_plan, ExecutionPlan
|
15
|
-
@plan_step_id = plan_step_id
|
16
|
-
@trigger = Type! trigger, Action, NilClass
|
17
|
-
end
|
18
|
-
|
19
|
-
def execute(*args)
|
20
|
-
self.state = :running
|
21
|
-
save_state
|
22
|
-
with_error_handling do
|
23
|
-
concurrence do
|
24
|
-
world.middleware.execute(:plan, self, *args) do |*new_args|
|
25
|
-
plan(*new_args)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
subscribed_actions = world.subscribed_actions(self.action_class)
|
30
|
-
if subscribed_actions.any?
|
31
|
-
# we encapsulate the flow for this action into a concurrence and
|
32
|
-
# add the subscribed flows to it as well.
|
33
|
-
trigger_flow = execution_plan.current_run_flow.sub_flows.pop
|
34
|
-
execution_plan.switch_flow(Flows::Concurrence.new([trigger_flow].compact)) do
|
35
|
-
subscribed_actions.each do |action_class|
|
36
|
-
new_plan_step = execution_plan.add_plan_step(action_class, self)
|
37
|
-
new_plan_step.execute(execution_plan, self, *args)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_hash
|
45
|
-
super.merge recursive_to_hash(input: input)
|
46
|
-
end
|
47
|
-
|
48
|
-
# DSL for plan method
|
49
|
-
|
50
|
-
def concurrence(&block)
|
51
|
-
execution_plan.switch_flow(Flows::Concurrence.new([]), &block)
|
52
|
-
end
|
53
|
-
|
54
|
-
def sequence(&block)
|
55
|
-
execution_plan.switch_flow(Flows::Sequence.new([]), &block)
|
56
|
-
end
|
57
|
-
|
58
|
-
def plan_self(input)
|
59
|
-
@input = input.with_indifferent_access
|
60
|
-
if self.respond_to?(:run)
|
61
|
-
run_step = execution_plan.add_run_step(self)
|
62
|
-
@run_step_id = run_step.id
|
63
|
-
@output_reference = ExecutionPlan::OutputReference.new(run_step.id, id)
|
64
|
-
end
|
65
|
-
|
66
|
-
if self.respond_to?(:finalize)
|
67
|
-
finalize_step = execution_plan.add_finalize_step(self)
|
68
|
-
@finalize_step_id = finalize_step.id
|
69
|
-
end
|
70
|
-
|
71
|
-
return self # to stay consistent with plan_action
|
72
|
-
end
|
73
|
-
|
74
|
-
def plan_action(action_class, *args)
|
75
|
-
execution_plan.add_plan_step(action_class, self).execute(execution_plan, nil, *args)
|
76
|
-
end
|
77
|
-
|
78
|
-
def output
|
79
|
-
unless @output_reference
|
80
|
-
raise 'plan_self has to be invoked before being able to reference the output'
|
81
|
-
end
|
82
|
-
|
83
|
-
return @output_reference
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
87
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
module Dynflow
|
2
|
-
|
3
|
-
# This module is used for providing access to the results of the
|
4
|
-
# action. It's used in ExecutionPlan#actions to provide access to
|
5
|
-
# data of the actions in the execution plan.
|
6
|
-
#
|
7
|
-
# It also defines helper methods to extract usable data from the action itself,
|
8
|
-
# as well as other actions involved in the execution plan. One action (usually the
|
9
|
-
# main trigger, can use them to collect data across the whole execution_plan)
|
10
|
-
module Action::Presenter
|
11
|
-
|
12
|
-
def self.included(base)
|
13
|
-
base.send(:attr_reader, :input)
|
14
|
-
base.send(:attr_reader, :output)
|
15
|
-
base.send(:attr_reader, :all_actions)
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.load(execution_plan, action_id, involved_steps, all_actions)
|
19
|
-
persistence_adapter = execution_plan.world.persistence.adapter
|
20
|
-
attributes = persistence_adapter.load_action(execution_plan.id,
|
21
|
-
action_id)
|
22
|
-
raise ArgumentError, 'missing :class' unless attributes[:class]
|
23
|
-
Action.constantize(attributes[:class]).presenter.new(attributes,
|
24
|
-
involved_steps,
|
25
|
-
all_actions)
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_hash
|
29
|
-
recursive_to_hash(action: action_class,
|
30
|
-
input: input,
|
31
|
-
output: output)
|
32
|
-
end
|
33
|
-
|
34
|
-
# @param [Hash] attributes - the action attributes, usually loaded form persistence layer
|
35
|
-
# @param [Array<ExecutionPlan::Steps::AbstractStep> - steps that operate on top of the action
|
36
|
-
# @param [Array<Action::Presenter>] - array of all the actions involved in the execution plan
|
37
|
-
# with this action. Allows to access data from other actions
|
38
|
-
def initialize(attributes, involved_steps, all_actions)
|
39
|
-
@execution_plan_id = attributes[:execution_plan_id] || raise(ArgumentError, 'missing execution_plan_id')
|
40
|
-
@id = attributes[:id] || raise(ArgumentError, 'missing id')
|
41
|
-
|
42
|
-
# TODO: use the involved_steps to provide summary state and error for the action
|
43
|
-
@involved_steps = involved_steps
|
44
|
-
@all_actions = all_actions
|
45
|
-
|
46
|
-
indifferent_access_hash_variable_set :input, attributes[:input]
|
47
|
-
indifferent_access_hash_variable_set :output, attributes[:output] || {}
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Dynflow
|
2
|
-
module Action::RunPhase
|
3
|
-
|
4
|
-
def self.included(base)
|
5
|
-
base.send(:include, Action::FlowPhase)
|
6
|
-
base.attr_indifferent_access_hash :output
|
7
|
-
end
|
8
|
-
|
9
|
-
SUSPEND = Object.new
|
10
|
-
|
11
|
-
def execute(event)
|
12
|
-
@world.logger.debug "step #{execution_plan_id}:#{@step.id} got event #{event}" if event
|
13
|
-
case
|
14
|
-
when state == :running
|
15
|
-
raise NotImplementedError, 'recovery after restart is not implemented'
|
16
|
-
|
17
|
-
when [:pending, :error, :suspended].include?(state)
|
18
|
-
if [:pending, :error].include?(state) && event
|
19
|
-
raise 'event can be processed only when in suspended state'
|
20
|
-
end
|
21
|
-
|
22
|
-
self.state = :running
|
23
|
-
save_state
|
24
|
-
with_error_handling do
|
25
|
-
result = catch(SUSPEND) do
|
26
|
-
world.middleware.execute(:run, self, *Array(event)) { |*args| run(*args) }
|
27
|
-
end
|
28
|
-
if result == SUSPEND
|
29
|
-
self.state = :suspended
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
else
|
34
|
-
raise "wrong state #{state} when event:#{event}"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# DSL for run
|
39
|
-
|
40
|
-
def suspend(&block)
|
41
|
-
block.call Action::Suspended.new self if block
|
42
|
-
throw SUSPEND, SUSPEND
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|