bumbleworks 0.0.32 → 0.0.33

Sign up to get free protection for your applications and to get access to all the features.
@@ -43,6 +43,27 @@ module Bumbleworks
43
43
  dashboard.launch(dashboard.variables[name], *args)
44
44
  end
45
45
 
46
+ def cancel_process!(wfid, options = {})
47
+ options[:timeout] ||= 5
48
+ unless options[:method] == :kill
49
+ options[:method] = :cancel
50
+ end
51
+
52
+ dashboard.send(options[:method], wfid)
53
+ start_time = Time.now
54
+ while dashboard.process(wfid)
55
+ if (Time.now - start_time) > options[:timeout]
56
+ error_type = options[:method] == :cancel ? CancelTimeout : KillTimeout
57
+ raise error_type, "Process #{options[:method]} taking too long - #{dashboard.processes.count} processes remain. Errors: #{dashboard.errors}"
58
+ end
59
+ sleep 0.1
60
+ end
61
+ end
62
+
63
+ def kill_process!(wfid, options = {})
64
+ cancel_process!(wfid, options.merge(:method => :kill))
65
+ end
66
+
46
67
  def cancel_all_processes!(options = {})
47
68
  options[:timeout] ||= 5
48
69
  unless options[:method] == :kill
@@ -5,6 +5,11 @@ module Ruote::Exp
5
5
  class WaitForEventExpression < AwaitExpression
6
6
  names :wait_for_event
7
7
 
8
+ # This does the same as the base AwaitExpression#apply, except that this
9
+ # will always be a global listener, listening for a 'left_tag' event, and
10
+ # the event's workitem will be discarded after the reply is complete. The
11
+ # event's workitem is only used for comparisons in the where clause (see
12
+ # #reply).
8
13
  def apply
9
14
  update_tree
10
15
  h.updated_tree[1]['global'] = true
@@ -13,14 +18,29 @@ module Ruote::Exp
13
18
  super
14
19
  end
15
20
 
21
+ # On apply, the workitem for this FlowExpression was replaced by the workitem
22
+ # from the event. So when we refer to "f:" in this #reply method, we're
23
+ # looking at the event's workitem, which will be discarded at the end of this
24
+ # reply (and replaced with the applied workitem). In order to compare the
25
+ # event's workitem with the applied workitem (so we can determine whether or
26
+ # not the event was intended for us), we assign the applied_workitem's fields
27
+ # to a hash on the event's workitem fields, available at "f:receiver.*".
16
28
  def reply(workitem)
17
29
  update_tree
30
+ # If we have a where clause at all...
18
31
  if translated_where = attribute(:where, nil, :escape => true)
19
32
  if translated_where.to_s == 'entities_match'
33
+ # Check to see that the event's entity is equal to the current workitem's
34
+ # entity. If so, this message is intended for us.
20
35
  translated_where = '${f:entity_id} == ${f:receiver.entity_id} && ${f:entity_type} == ${f:receiver.entity_type}'
21
36
  else
22
- translated_where.gsub!('${event:', '${f:')
23
- translated_where.gsub!('${this:', '${f:receiver.')
37
+ # This just gives us a shortcut so the process definition reads more
38
+ # clearly. You could always use "${f:" and "${f:receiver." in your
39
+ # where clauses, but you have to remember that the former refers to the
40
+ # incoming event's workitem, and the latter is the workitem of the
41
+ # listening process.
42
+ translated_where.gsub!('${event:', '${f:') # event workitem
43
+ translated_where.gsub!('${this:', '${f:receiver.') # listening workitem
24
44
  end
25
45
  h.updated_tree[1]['where'] = translated_where
26
46
  end
@@ -1,3 +1,3 @@
1
1
  module Bumbleworks
2
- VERSION = "0.0.32"
2
+ VERSION = "0.0.33"
3
3
  end
@@ -4,6 +4,70 @@ describe Bumbleworks::Ruote do
4
4
  Bumbleworks.storage = {}
5
5
  end
6
6
 
7
+ describe ".cancel_process!" do
8
+ before :each do
9
+ Bumbleworks.start_worker!
10
+ end
11
+
12
+ it 'cancels given process' do
13
+ Bumbleworks.define_process 'do_nothing' do
14
+ lazy_guy :task => 'absolutely_nothing'
15
+ end
16
+ wfid = Bumbleworks.launch!('do_nothing')
17
+ Bumbleworks.dashboard.wait_for(:lazy_guy)
18
+ Bumbleworks.dashboard.process(wfid).should_not be_nil
19
+ described_class.cancel_process!(wfid)
20
+ Bumbleworks.dashboard.process(wfid).should be_nil
21
+ end
22
+
23
+ it 'times out if process is not cancelled in time' do
24
+ Bumbleworks.define_process "time_hog" do
25
+ sequence :on_cancel => 'ignore_parents' do
26
+ pigheaded :task => 'whatever'
27
+ end
28
+ define 'ignore_parents' do
29
+ wait '1s'
30
+ end
31
+ end
32
+ wfid = Bumbleworks.launch!('time_hog')
33
+ Bumbleworks.dashboard.wait_for(:pigheaded)
34
+ Bumbleworks.dashboard.process(wfid).should_not be_nil
35
+ expect {
36
+ described_class.cancel_process!(wfid, :timeout => 0.5)
37
+ }.to raise_error(Bumbleworks::Ruote::CancelTimeout)
38
+ end
39
+ end
40
+
41
+ describe ".kill_process!" do
42
+ before :each do
43
+ Bumbleworks.start_worker!
44
+ end
45
+
46
+ it 'kills given process without running on_cancel' do
47
+ Bumbleworks.define_process "do_nothing" do
48
+ sequence :on_cancel => 'rethink_life' do
49
+ lazy_guy :task => 'absolutely_nothing'
50
+ end
51
+ define 'rethink_life' do
52
+ wait '10s'
53
+ end
54
+ end
55
+ wfid = Bumbleworks.launch!('do_nothing')
56
+ Bumbleworks.dashboard.wait_for(:lazy_guy)
57
+ Bumbleworks.dashboard.process(wfid).should_not be_nil
58
+ described_class.kill_process!(wfid)
59
+ Bumbleworks.dashboard.process(wfid).should be_nil
60
+ end
61
+
62
+ it 'times out if process is not killed in time' do
63
+ Bumbleworks.dashboard.stub(:kill)
64
+ Bumbleworks.dashboard.stub(:process).with('woot').and_return(:i_exist)
65
+ expect {
66
+ described_class.kill_process!('woot', :timeout => 0.5)
67
+ }.to raise_error(Bumbleworks::Ruote::KillTimeout)
68
+ end
69
+ end
70
+
7
71
  describe ".cancel_all_processes!" do
8
72
  before :each do
9
73
  Bumbleworks::Ruote.register_participants
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bumbleworks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.32
4
+ version: 0.0.33
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2013-08-13 00:00:00.000000000 Z
15
+ date: 2013-08-21 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: ruote