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.
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