dynflow 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,16 +21,18 @@ module Dynflow
21
21
  require 'dynflow/action/cancellable_polling'
22
22
 
23
23
  def self.all_children
24
- children.inject(children) { |children, child| children + child.all_children }
24
+ children.values.inject(children.values) do |children, child|
25
+ children + child.all_children
26
+ end
25
27
  end
26
28
 
27
29
  def self.inherited(child)
28
- children << child
30
+ children[child.name] = child
29
31
  super child
30
32
  end
31
33
 
32
34
  def self.children
33
- @children ||= []
35
+ @children ||= {}
34
36
  end
35
37
 
36
38
  def self.middleware
@@ -154,6 +156,27 @@ module Dynflow
154
156
  execution_plan.steps.fetch(plan_step_id)
155
157
  end
156
158
 
159
+ # @param [Class] filter_class return only actions which are kind of `filter_class`
160
+ # @return [Array<Action>] of directly planned actions by this action,
161
+ # returned actions are in Present phase
162
+ def planned_actions(filter = Action)
163
+ phase! Present
164
+ plan_step.
165
+ planned_steps(execution_plan).
166
+ map { |s| s.action execution_plan }.
167
+ select { |a| a.is_a?(filter) }
168
+ end
169
+
170
+ # @param [Class] filter_class return only actions which are kind of `filter_class`
171
+ # @return [Array<Action>] of all (including indirectly) planned actions by this action,
172
+ # returned actions are in Present phase
173
+ def all_planned_actions(filter_class = Action)
174
+ phase! Present
175
+ mine = planned_actions
176
+ (mine + mine.reduce([]) { |arr, action| arr + action.all_planned_actions }).
177
+ select { |a| a.is_a?(filter_class) }
178
+ end
179
+
157
180
  def run_step
158
181
  phase! Present
159
182
  execution_plan.steps.fetch(run_step_id) if run_step_id
@@ -283,7 +306,7 @@ module Dynflow
283
306
  @execution_plan.switch_flow(Flows::Sequence.new([]), &block)
284
307
  end
285
308
 
286
- def plan_self(input)
309
+ def plan_self(input = {})
287
310
  phase! Plan
288
311
  self.input.update input
289
312
 
@@ -264,18 +264,12 @@ module Dynflow
264
264
  plan_total > 0 ? (plan_done / plan_total) : 1
265
265
  end
266
266
 
267
- # This method can be used to access result of the whole execution plan and detailed
268
- # progress.
269
- # @return [Array<Action::Presenter>] presenter of the actions
270
- # involved in the plan
267
+ # @return [Array<Action>] actions in Present phase, consider using
268
+ # Steps::Abstract#action instead
271
269
  def actions
272
270
  @actions ||= begin
273
- action_ids = steps.values.map(&:action_id).uniq
274
- action_ids.map do |action_id|
275
- attributes = world.persistence.adapter.load_action(id, action_id)
276
- Action.from_hash(attributes.update(phase: Action::Present, execution_plan: self),
277
- world)
278
- end
271
+ action_ids = steps.reduce({}) { |h, (_, s)| h.update s.action_id => s }
272
+ action_ids.map { |_, step| step.action self }
279
273
  end
280
274
  end
281
275
 
@@ -86,6 +86,8 @@ module Dynflow
86
86
  raise NotImplementedError, "Expected to be implemented in RunStep and FinalizeStep"
87
87
  end
88
88
 
89
+ # @return [Action] in presentation mode, intended for retrieving: progress information,
90
+ # details, human outputs, etc.
89
91
  def action(execution_plan)
90
92
  attributes = world.persistence.adapter.load_action(execution_plan_id, action_id)
91
93
  Action.from_hash(attributes.update(phase: Action::Present, execution_plan: execution_plan),
@@ -23,6 +23,10 @@ module Dynflow
23
23
  @children = children
24
24
  end
25
25
 
26
+ def planned_steps(execution_plan)
27
+ @children.map { |id| execution_plan.steps.fetch(id) }
28
+ end
29
+
26
30
  def phase
27
31
  Action::Plan
28
32
  end
@@ -20,6 +20,20 @@ module Dynflow
20
20
  execution_plan.world)
21
21
  end
22
22
 
23
+ def create_action_presentation(action_class)
24
+ execution_plan = DummyExecutionPlan.new
25
+ action_class.new(
26
+ { execution_plan: execution_plan,
27
+ execution_plan_id: execution_plan.id,
28
+ id: Testing.get_id,
29
+ phase: Action::Present,
30
+ plan_step_id: 1,
31
+ run_step_id: nil,
32
+ finalize_step_id: nil,
33
+ input: nil },
34
+ execution_plan.world)
35
+ end
36
+
23
37
  # @return [Action::PlanPhase]
24
38
  def plan_action(plan_action, *args, &block)
25
39
  Match! plan_action.phase, Action::Plan
@@ -1,3 +1,3 @@
1
1
  module Dynflow
2
- VERSION = '0.4.1'
2
+ VERSION = '0.5.0'
3
3
  end
data/test/action_test.rb CHANGED
@@ -61,9 +61,7 @@ module Dynflow
61
61
  end
62
62
 
63
63
  let :presenter do
64
- execution_plan.actions.find do |action|
65
- action.is_a? Support::CodeWorkflowExample::IncomingIssues
66
- end
64
+ execution_plan.root_plan_step.action execution_plan
67
65
  end
68
66
 
69
67
  specify { presenter.class.must_equal Support::CodeWorkflowExample::IncomingIssues }
@@ -64,7 +64,7 @@ module Dynflow
64
64
  describe 'for error in running phase' do
65
65
 
66
66
  before do
67
- step_id = execution_plan.run_flow.all_step_ids[2]
67
+ step_id = execution_plan.run_flow.all_step_ids[2]
68
68
  execution_plan.steps[step_id].set_state :error, true
69
69
  end
70
70
 
@@ -77,7 +77,7 @@ module Dynflow
77
77
  describe 'for pending step in running phase' do
78
78
 
79
79
  before do
80
- step_id = execution_plan.run_flow.all_step_ids[2]
80
+ step_id = execution_plan.run_flow.all_step_ids[2]
81
81
  execution_plan.steps[step_id].set_state :pending, true
82
82
  end
83
83
 
@@ -239,10 +239,10 @@ module Dynflow
239
239
  world.plan(Support::CodeWorkflowExample::IncomingIssues, issues_data)
240
240
  end
241
241
 
242
- it 'provides the access to the actions data via Action::Presenter' do
243
- execution_plan.actions.size.must_equal 9
244
- execution_plan.actions.each do |action|
245
- action.phase.must_equal Action::Present
242
+ it 'provides the access to the actions data via steps #action' do
243
+ execution_plan.steps.size.must_equal 20
244
+ execution_plan.steps.each do |_, step|
245
+ step.action(execution_plan).phase.must_equal Action::Present
246
246
  end
247
247
  end
248
248
  end
@@ -24,9 +24,8 @@ module Support
24
24
  end
25
25
 
26
26
  def summary
27
- triages = execution_plan.actions.find_all do |action|
28
- action.is_a? Triage
29
- end
27
+ # TODO fix, not a good pattern, it should delegate to IncomingIssue first
28
+ triages = all_planned_actions(Triage)
30
29
  assignees = triages.map do |triage|
31
30
  triage.output[:classification] &&
32
31
  triage.output[:classification][:assignee]
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.1
4
+ version: 0.5.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-18 00:00:00.000000000 Z
12
+ date: 2014-02-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport