dynflow 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/lib/dynflow.rb +2 -1
  2. data/lib/dynflow/action.rb +271 -101
  3. data/lib/dynflow/action/format.rb +4 -4
  4. data/lib/dynflow/action/progress.rb +8 -8
  5. data/lib/dynflow/execution_plan.rb +14 -15
  6. data/lib/dynflow/execution_plan/output_reference.rb +56 -23
  7. data/lib/dynflow/execution_plan/steps/abstract.rb +1 -3
  8. data/lib/dynflow/execution_plan/steps/abstract_flow_step.rb +0 -17
  9. data/lib/dynflow/execution_plan/steps/error.rb +35 -11
  10. data/lib/dynflow/execution_plan/steps/finalize_step.rb +1 -1
  11. data/lib/dynflow/execution_plan/steps/plan_step.rb +8 -3
  12. data/lib/dynflow/execution_plan/steps/run_step.rb +1 -1
  13. data/lib/dynflow/listeners/socket.rb +0 -1
  14. data/lib/dynflow/middleware.rb +0 -1
  15. data/lib/dynflow/middleware/world.rb +1 -1
  16. data/lib/dynflow/persistence.rb +2 -5
  17. data/lib/dynflow/serializable.rb +24 -11
  18. data/lib/dynflow/testing/assertions.rb +5 -5
  19. data/lib/dynflow/testing/dummy_execution_plan.rb +1 -1
  20. data/lib/dynflow/testing/dummy_planned_action.rb +2 -1
  21. data/lib/dynflow/testing/dummy_world.rb +4 -0
  22. data/lib/dynflow/testing/factories.rb +18 -10
  23. data/lib/dynflow/version.rb +1 -1
  24. data/lib/dynflow/world.rb +35 -21
  25. data/test/action_test.rb +50 -76
  26. data/test/clock_test.rb +4 -4
  27. data/test/execution_plan_test.rb +1 -1
  28. data/test/executor_test.rb +3 -2
  29. data/test/remote_via_socket_test.rb +11 -9
  30. data/test/support/code_workflow_example.rb +2 -3
  31. data/test/test_helper.rb +1 -1
  32. data/test/testing_test.rb +3 -3
  33. metadata +2 -8
  34. data/lib/dynflow/action/finalize_phase.rb +0 -20
  35. data/lib/dynflow/action/flow_phase.rb +0 -44
  36. data/lib/dynflow/action/plan_phase.rb +0 -87
  37. data/lib/dynflow/action/presenter.rb +0 -51
  38. data/lib/dynflow/action/run_phase.rb +0 -45
  39. 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 = all_actions.find_all do |action|
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[:progress]
276
+ progress = external_task.fetch(:progress)
278
277
  new_progress = if progress == 30
279
278
  if input[:text] =~ /cancel-external/
280
279
  progress
@@ -28,7 +28,7 @@ class TestExecutionLog
28
28
  end
29
29
 
30
30
  def <<(action)
31
- @log << [action.action_class, action.input]
31
+ @log << [action.class, action.input]
32
32
  end
33
33
 
34
34
  def log
@@ -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.must_be_kind_of Action::PlanPhase
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.must_be_kind_of Action::RunPhase
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.must_be_kind_of Action::FinalizePhase
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.3.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-11 00:00:00.000000000 Z
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
@@ -1,9 +0,0 @@
1
- module Dynflow
2
- module Middleware::Action
3
-
4
- def middleware
5
- @middleware ||= Middleware::Register.new
6
- end
7
-
8
- end
9
- end