bumbleworks 0.0.71 → 0.0.72
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/bumbleworks.rb +1 -0
- data/lib/bumbleworks/configuration.rb +12 -0
- data/lib/bumbleworks/entity.rb +6 -3
- data/lib/bumbleworks/expression.rb +62 -0
- data/lib/bumbleworks/process.rb +41 -16
- data/lib/bumbleworks/process/error_record.rb +67 -0
- data/lib/bumbleworks/tracker.rb +5 -1
- data/lib/bumbleworks/version.rb +1 -1
- data/spec/fixtures/participants/naughty_participant.rb +8 -0
- data/spec/integration/entity_spec.rb +9 -0
- data/spec/lib/bumbleworks/configuration_spec.rb +12 -0
- data/spec/lib/bumbleworks/entity_spec.rb +6 -0
- data/spec/lib/bumbleworks/expression_spec.rb +69 -0
- data/spec/lib/bumbleworks/process/error_record_spec.rb +62 -0
- data/spec/lib/bumbleworks/process_spec.rb +113 -29
- data/spec/lib/bumbleworks/tracker_spec.rb +8 -2
- metadata +12 -4
data/lib/bumbleworks.rb
CHANGED
@@ -4,6 +4,7 @@ require "bumbleworks/configuration"
|
|
4
4
|
require "bumbleworks/support"
|
5
5
|
require "bumbleworks/process_definition"
|
6
6
|
require "bumbleworks/process"
|
7
|
+
require "bumbleworks/expression"
|
7
8
|
require "bumbleworks/task"
|
8
9
|
require "bumbleworks/participant_registration"
|
9
10
|
require "bumbleworks/ruote"
|
@@ -169,6 +169,13 @@ module Bumbleworks
|
|
169
169
|
#
|
170
170
|
define_setting :store_history
|
171
171
|
|
172
|
+
# The set of registered entity classes. This can be manually set in configuration,
|
173
|
+
# but if you include Bumbleworks::Entity in any class, that class will automatically
|
174
|
+
# be loaded into this array at the time of module inclusion.
|
175
|
+
#
|
176
|
+
# default: []
|
177
|
+
define_setting :entity_classes
|
178
|
+
|
172
179
|
def initialize
|
173
180
|
@storage_adapters = []
|
174
181
|
@storage_options = {}
|
@@ -226,6 +233,11 @@ module Bumbleworks
|
|
226
233
|
@store_history.nil? ? true : @store_history
|
227
234
|
end
|
228
235
|
|
236
|
+
# Default entity_classes to empty array
|
237
|
+
def entity_classes
|
238
|
+
@entity_classes ||= []
|
239
|
+
end
|
240
|
+
|
229
241
|
# Root folder where Bumbleworks looks for ruote assets (participants,
|
230
242
|
# process_definitions, etc.) The root path must be absolute.
|
231
243
|
# It can be defined through a configuration block:
|
data/lib/bumbleworks/entity.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Bumbleworks
|
2
2
|
module Entity
|
3
3
|
def self.included(klass)
|
4
|
+
Bumbleworks.entity_classes << klass
|
4
5
|
klass.extend ClassMethods
|
5
6
|
end
|
6
7
|
|
@@ -83,11 +84,13 @@ module Bumbleworks
|
|
83
84
|
end
|
84
85
|
|
85
86
|
module ClassMethods
|
86
|
-
attr_reader :processes
|
87
|
-
|
88
87
|
def process(process_name, options = {})
|
89
88
|
options[:attribute] ||= default_process_identifier_attribute(process_name)
|
90
|
-
|
89
|
+
processes[process_name.to_sym] = options
|
90
|
+
end
|
91
|
+
|
92
|
+
def processes
|
93
|
+
@processes ||= {}
|
91
94
|
end
|
92
95
|
|
93
96
|
def entity_type
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Bumbleworks
|
2
|
+
class Expression
|
3
|
+
attr_reader :expid
|
4
|
+
|
5
|
+
def initialize(flow_expression)
|
6
|
+
@flow_expression = flow_expression
|
7
|
+
@fei = @flow_expression.fei
|
8
|
+
@expid = @fei.expid
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns a Bumbleworks::Process instance for the expression's
|
12
|
+
# wfid; effectively, the process instance this expression is
|
13
|
+
# a part of.
|
14
|
+
def process
|
15
|
+
@process ||= Bumbleworks::Process.new(@fei.wfid)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the process tree at this expression.
|
19
|
+
def tree
|
20
|
+
@flow_expression.tree
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns a Bumbleworks::Process::ErrorRecord instance for the
|
24
|
+
# expression's error, if there is one. If no error was raised
|
25
|
+
# during the execution of this expression, returns nil.
|
26
|
+
#
|
27
|
+
# Note that what is returned is not the exception itself that
|
28
|
+
# was raised during execution, but rather a *record* of that error.
|
29
|
+
# If you want a re-created instance of the actual exception,
|
30
|
+
# you can call #reify on the ErrorRecord instance returned.
|
31
|
+
def error
|
32
|
+
@error ||= ruote_error
|
33
|
+
end
|
34
|
+
|
35
|
+
# Cancel this expression. The process will then move on to the
|
36
|
+
# next expression.
|
37
|
+
def cancel!
|
38
|
+
Bumbleworks.dashboard.cancel_expression(@fei)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Kill this expression. The process will then move on to the
|
42
|
+
# next expression.
|
43
|
+
#
|
44
|
+
# WARNING: Killing an expression will not trigger any 'on_cancel'
|
45
|
+
# callbacks. It's preferable to #cancel! the expression if you
|
46
|
+
# can.
|
47
|
+
def kill!
|
48
|
+
Bumbleworks.dashboard.kill_expression(@fei)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the workitem as it was applied to this expression.
|
52
|
+
def workitem
|
53
|
+
Workitem.new(@flow_expression.applied_workitem)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def ruote_error
|
59
|
+
process.errors.detect { |err| err.fei == @fei }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/bumbleworks/process.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "bumbleworks/workitem_entity_storage"
|
2
|
+
require "bumbleworks/process/error_record"
|
2
3
|
|
3
4
|
module Bumbleworks
|
4
5
|
class Process
|
@@ -9,14 +10,18 @@ module Bumbleworks
|
|
9
10
|
attr_reader :id
|
10
11
|
|
11
12
|
class << self
|
12
|
-
def all
|
13
|
-
ids.map do |wfid|
|
13
|
+
def all(options = {})
|
14
|
+
ids(options).map do |wfid|
|
14
15
|
new(wfid)
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
|
-
def ids
|
19
|
-
Bumbleworks.dashboard.process_wfids
|
19
|
+
def ids(options = {})
|
20
|
+
wfids = Bumbleworks.dashboard.process_wfids
|
21
|
+
wfids.reverse! if options[:reverse]
|
22
|
+
limit = options[:limit] || wfids.count
|
23
|
+
offset = options[:offset] || 0
|
24
|
+
wfids[offset, limit]
|
20
25
|
end
|
21
26
|
|
22
27
|
def count
|
@@ -37,6 +42,10 @@ module Bumbleworks
|
|
37
42
|
|
38
43
|
alias_method :wfid, :id
|
39
44
|
|
45
|
+
def <=>(other)
|
46
|
+
wfid <=> other.wfid
|
47
|
+
end
|
48
|
+
|
40
49
|
def ==(other)
|
41
50
|
wfid == other.wfid
|
42
51
|
end
|
@@ -54,31 +63,33 @@ module Bumbleworks
|
|
54
63
|
end
|
55
64
|
|
56
65
|
def expressions
|
57
|
-
@expressions ||=
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
}
|
65
|
-
end
|
66
|
+
@expressions ||= ruote_expressions.map { |rexp|
|
67
|
+
Bumbleworks::Expression.new(rexp)
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def expression_at_position(position)
|
72
|
+
expressions.detect { |exp| exp.expid == position }
|
66
73
|
end
|
67
74
|
|
68
75
|
def errors
|
69
76
|
@errors ||= Bumbleworks.dashboard.context.storage.get_many('errors', [wfid]).map { |err|
|
70
|
-
::
|
77
|
+
Bumbleworks::Process::ErrorRecord.new(
|
78
|
+
::Ruote::ProcessError.new(err)
|
79
|
+
)
|
71
80
|
}
|
72
81
|
end
|
73
82
|
|
74
83
|
def leaves
|
75
|
-
@leaves ||=
|
84
|
+
@leaves ||= ruote_expressions.inject([]) { |a, exp|
|
76
85
|
a.select { |e| ! exp.ancestor?(e.fei) } + [ exp ]
|
86
|
+
}.map { |leaf|
|
87
|
+
Bumbleworks::Expression.new(leaf)
|
77
88
|
}
|
78
89
|
end
|
79
90
|
|
80
91
|
def workitems
|
81
|
-
@workitems ||= leaves.map(&:
|
92
|
+
@workitems ||= leaves.map(&:workitem)
|
82
93
|
end
|
83
94
|
|
84
95
|
def tasks
|
@@ -131,5 +142,19 @@ module Bumbleworks
|
|
131
142
|
end
|
132
143
|
super
|
133
144
|
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def ruote_expressions
|
149
|
+
@ruote_expressions ||= begin
|
150
|
+
context = Bumbleworks.dashboard.context
|
151
|
+
raw_expressions = context.storage.get_many('expressions', [wfid])
|
152
|
+
raw_expressions.collect { |e|
|
153
|
+
::Ruote::Exp::FlowExpression.from_h(context, e)
|
154
|
+
}.sort_by { |e|
|
155
|
+
e.fei.expid
|
156
|
+
}
|
157
|
+
end
|
158
|
+
end
|
134
159
|
end
|
135
160
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Bumbleworks
|
2
|
+
class Process
|
3
|
+
class ErrorRecord
|
4
|
+
# The initializer takes a Ruote::ProcessError instance.
|
5
|
+
def initialize(process_error)
|
6
|
+
@process_error = process_error
|
7
|
+
end
|
8
|
+
|
9
|
+
# Returns the FlowExpressionId of the expression where this error
|
10
|
+
# occurred.
|
11
|
+
def fei
|
12
|
+
@process_error.fei
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the class name of the error that was actually raised
|
16
|
+
# during execution of the process.
|
17
|
+
|
18
|
+
# Be aware that this class may not exist in the current binding
|
19
|
+
# when you instantiate the ErrorRecord; if it does not, calling
|
20
|
+
# #reify will throw an exception.
|
21
|
+
def error_class_name
|
22
|
+
@process_error.h['class']
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the original error's backtrace.
|
26
|
+
#
|
27
|
+
# The original backtrace will be returned in standard backtrace
|
28
|
+
# format: an array of strings with paths and line numbers.
|
29
|
+
def backtrace
|
30
|
+
@process_error.h['trace'].split(/\n/)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the original error message.
|
34
|
+
#
|
35
|
+
# Ruote's error logging has a strange issue; the message recorded
|
36
|
+
# and returned via the Ruote::ProcessError instance is the full
|
37
|
+
# #inspect of the error. This method strips away the resulting
|
38
|
+
# cruft (if it exists) and leaves behind just the message itself.
|
39
|
+
def message
|
40
|
+
@message ||= @process_error.message.
|
41
|
+
gsub(/\#\<#{error_class_name}: (.*)\>$/, '\1')
|
42
|
+
end
|
43
|
+
|
44
|
+
# Re-instantiates the original exception.
|
45
|
+
#
|
46
|
+
# If you wish to re-create the actual exception that was raised
|
47
|
+
# during process execution, this method will attempt to return
|
48
|
+
# an instance of the error class, with the message and backtrace
|
49
|
+
# restored.
|
50
|
+
#
|
51
|
+
# In order for this to work, the error class itself must be a
|
52
|
+
# defined constant in the current binding; if it's not, you'll get
|
53
|
+
# an exception. Be cognizant of this caveat if you choose to use
|
54
|
+
# this feature; Bumbleworks makes no attempt to protect you.
|
55
|
+
#
|
56
|
+
# This is not because Bumbleworks doesn't love you. It just wants
|
57
|
+
# you to spread your wings, and the only way to truly experience
|
58
|
+
# flight is to first taste the ground.
|
59
|
+
def reify
|
60
|
+
klass = Bumbleworks::Support.constantize(error_class_name)
|
61
|
+
err = klass.new(message)
|
62
|
+
err.set_backtrace(backtrace)
|
63
|
+
err
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/bumbleworks/tracker.rb
CHANGED
@@ -8,6 +8,10 @@ module Bumbleworks
|
|
8
8
|
new(tid, attrs)
|
9
9
|
end
|
10
10
|
end
|
11
|
+
|
12
|
+
def count
|
13
|
+
all.count
|
14
|
+
end
|
11
15
|
end
|
12
16
|
|
13
17
|
def initialize(id, original_hash = nil)
|
@@ -43,7 +47,7 @@ module Bumbleworks
|
|
43
47
|
|
44
48
|
def waiting_expression
|
45
49
|
return nil unless fei
|
46
|
-
process.
|
50
|
+
process.expression_at_position(fei['expid']).tree
|
47
51
|
end
|
48
52
|
|
49
53
|
def where_clause
|
data/lib/bumbleworks/version.rb
CHANGED
@@ -10,6 +10,15 @@ describe 'Entity Module' do
|
|
10
10
|
load File.join(app_root, 'full_initializer.rb')
|
11
11
|
end
|
12
12
|
|
13
|
+
describe 'including' do
|
14
|
+
it 'registers entity with Bumbleworks' do
|
15
|
+
Bumbleworks.entity_classes = [:geese]
|
16
|
+
FirstNewClass = Class.new { include Bumbleworks::Entity }
|
17
|
+
SecondNewClass = Class.new { include Bumbleworks::Entity }
|
18
|
+
Bumbleworks.entity_classes.should == [:geese, FirstNewClass, SecondNewClass]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
13
22
|
describe 'process control' do
|
14
23
|
it 'launching assigns entity to process and subsequent tasks' do
|
15
24
|
rainbow_loom = RainbowLoom.new('12345')
|
@@ -218,6 +218,18 @@ describe Bumbleworks::Configuration do
|
|
218
218
|
end
|
219
219
|
end
|
220
220
|
|
221
|
+
describe '#entity_classes' do
|
222
|
+
it 'is empty by default' do
|
223
|
+
configuration.entity_classes.should be_empty
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'returns the registered entity classes' do
|
227
|
+
configuration.entity_classes = [:fumpin, :nuffin]
|
228
|
+
configuration.entity_classes << :summin
|
229
|
+
configuration.entity_classes.should == [:fumpin, :nuffin, :summin]
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
221
233
|
describe "#storage" do
|
222
234
|
it 'can set storage directly' do
|
223
235
|
storage = double("Storage")
|
@@ -253,6 +253,12 @@ describe Bumbleworks::Entity do
|
|
253
253
|
end
|
254
254
|
end
|
255
255
|
|
256
|
+
describe '.processes' do
|
257
|
+
it 'returns empty hash if no registered processes' do
|
258
|
+
expect(entity_class.processes).to eq({})
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
256
262
|
describe '.default_process_identifier_attribute' do
|
257
263
|
it 'adds _process_identifier to end of given process name' do
|
258
264
|
entity_class.default_process_identifier_attribute('zoof').should == :zoof_process_identifier
|
@@ -0,0 +1,69 @@
|
|
1
|
+
describe Bumbleworks::Expression do
|
2
|
+
let(:fei) { double({ :expid => '1_2_3', :wfid => 'snooks' }) }
|
3
|
+
let(:fexp) { double('FlowExpression', :fei => fei, :tree => :a_tree) }
|
4
|
+
subject { described_class.new(fexp) }
|
5
|
+
|
6
|
+
describe '#expid' do
|
7
|
+
it 'returns expid from fei' do
|
8
|
+
subject.expid.should == '1_2_3'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#process' do
|
13
|
+
it 'returns process for expression wfid' do
|
14
|
+
subject.process.should == Bumbleworks::Process.new('snooks')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#tree' do
|
19
|
+
it 'returns tree from flow expression' do
|
20
|
+
expect(subject.tree).to eq :a_tree
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#error' do
|
25
|
+
it 'returns error from process that matches fei' do
|
26
|
+
process = double
|
27
|
+
process.stub(:errors => [
|
28
|
+
double(:fei => :not_me, :message => 'alarming!'),
|
29
|
+
double(:fei => fei, :message => 'boo!'),
|
30
|
+
double(:fei => :also_not_me, :message => 'yippee!')
|
31
|
+
])
|
32
|
+
subject.stub(:process => process)
|
33
|
+
subject.error.message.should == 'boo!'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns nil if no error during this expression' do
|
37
|
+
process = double
|
38
|
+
process.stub(:errors => [
|
39
|
+
double(:fei => :not_me, :message => 'alarming!'),
|
40
|
+
double(:fei => :also_not_me, :message => 'yippee!')
|
41
|
+
])
|
42
|
+
subject.stub(:process => process)
|
43
|
+
subject.error.should be_nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#cancel!' do
|
48
|
+
it 'cancels the expression' do
|
49
|
+
Bumbleworks.storage = {}
|
50
|
+
Bumbleworks.dashboard.should_receive(:cancel_expression).with(fei)
|
51
|
+
subject.cancel!
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#kill!' do
|
56
|
+
it 'kills the expression' do
|
57
|
+
Bumbleworks.storage = {}
|
58
|
+
Bumbleworks.dashboard.should_receive(:kill_expression).with(fei)
|
59
|
+
subject.kill!
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#workitem' do
|
64
|
+
it 'returns the workitem as applied to this expression' do
|
65
|
+
fexp.stub(:applied_workitem).and_return(:something_raw)
|
66
|
+
subject.workitem.should == Bumbleworks::Workitem.new(:something_raw)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.expand_path(File.join(fixtures_path, 'participants', 'naughty_participant'))
|
2
|
+
|
3
|
+
describe Bumbleworks::Process::ErrorRecord do
|
4
|
+
before :each do
|
5
|
+
Bumbleworks.reset!
|
6
|
+
Bumbleworks.storage = {}
|
7
|
+
Bumbleworks::Ruote.register_participants do
|
8
|
+
fall_apart NaughtyParticipant
|
9
|
+
end
|
10
|
+
Bumbleworks.start_worker!
|
11
|
+
|
12
|
+
Bumbleworks.define_process 'a_pain_in_the_tush' do
|
13
|
+
fall_apart
|
14
|
+
end
|
15
|
+
@process = Bumbleworks.launch!('a_pain_in_the_tush')
|
16
|
+
wait_until { @process.reload.errors.count == 1 }
|
17
|
+
@error = @process.errors.first
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#error_class_name' do
|
21
|
+
it 'returns the class name of the recorded error (as a string)' do
|
22
|
+
expect(@error.error_class_name).to eq 'NaughtyParticipant::StupidError'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#backtrace' do
|
27
|
+
it 'returns the recorded error backtrace as array of strings' do
|
28
|
+
expect(@error.backtrace).to be_an Array
|
29
|
+
expect(@error.backtrace.first).to match(/in `on_workitem'$/)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#fei' do
|
34
|
+
it 'returns the fei from when the error occurred' do
|
35
|
+
fei = @error.fei
|
36
|
+
expect(fei.wfid).to eq @process.wfid
|
37
|
+
expect(fei.expid).to eq '0_0'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#message' do
|
42
|
+
it 'returns the original error message' do
|
43
|
+
expect(@error.message).to eq 'Oh crumb.'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#reify' do
|
48
|
+
it 're-instantiates the original exception' do
|
49
|
+
original_error = @error.reify
|
50
|
+
expect(original_error).to be_a NaughtyParticipant::StupidError
|
51
|
+
expect(original_error.backtrace).to eq @error.backtrace
|
52
|
+
expect(original_error.message).to eq @error.message
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'raises exception if exception class not defined' do
|
56
|
+
@error.instance_variable_get(:@process_error).h['class'] = 'Goose'
|
57
|
+
expect {
|
58
|
+
@error.reify
|
59
|
+
}.to raise_error(NameError, 'uninitialized constant Goose')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -7,6 +7,14 @@ describe Bumbleworks::Process do
|
|
7
7
|
Bumbleworks::Ruote.register_participants
|
8
8
|
Bumbleworks.start_worker!
|
9
9
|
|
10
|
+
Bumbleworks.define_process 'food_is_an_illusion' do
|
11
|
+
noop :tag => 'oh_boy_are_we_hungry'
|
12
|
+
concurrence do
|
13
|
+
admin :task => 'eat_a_hat'
|
14
|
+
hatter :task => 'weep'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
10
18
|
Bumbleworks.define_process 'going_to_the_dance' do
|
11
19
|
concurrence do
|
12
20
|
wait_for_event :an_invitation
|
@@ -25,30 +33,53 @@ describe Bumbleworks::Process do
|
|
25
33
|
end
|
26
34
|
end
|
27
35
|
|
28
|
-
|
36
|
+
describe '.all' do
|
37
|
+
it 'returns sorted and filtered array of instances for all processes' do
|
38
|
+
expect(described_class).to receive(:ids).with(:some_options).and_return([:a, :b, :c])
|
39
|
+
expect(described_class.all(:some_options)).to eq [
|
40
|
+
Bumbleworks::Process.new(:a),
|
41
|
+
Bumbleworks::Process.new(:b),
|
42
|
+
Bumbleworks::Process.new(:c)
|
43
|
+
]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '.ids' do
|
29
48
|
before(:each) do
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
49
|
+
bp1 = Bumbleworks.launch!('going_to_the_dance')
|
50
|
+
bp2 = Bumbleworks.launch!('going_to_the_dance')
|
51
|
+
bp3 = Bumbleworks.launch!('going_to_the_dance')
|
52
|
+
bp4 = Bumbleworks.launch!('going_to_the_dance')
|
53
|
+
bp5 = Bumbleworks.launch!('straightening_the_rocks')
|
54
|
+
@sorted_processes = [bp1, bp2, bp3, bp4, bp5].sort
|
55
|
+
wait_until { Bumbleworks.dashboard.process_wfids.count == 5 }
|
34
56
|
end
|
35
57
|
|
36
|
-
|
37
|
-
|
38
|
-
described_class.all.should =~ [@bp1, @bp2, @bp3]
|
39
|
-
end
|
58
|
+
it 'returns all process wfids' do
|
59
|
+
described_class.ids.should == @sorted_processes.map(&:wfid)
|
40
60
|
end
|
41
61
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
62
|
+
it 'allows pagination options' do
|
63
|
+
described_class.ids(:limit => 2).should == @sorted_processes[0, 2].map(&:wfid)
|
64
|
+
described_class.ids(:offset => 2).should == @sorted_processes[2, 5].map(&:wfid)
|
65
|
+
described_class.ids(:limit => 2, :offset => 1).should == @sorted_processes[1, 2].map(&:wfid)
|
46
66
|
end
|
47
67
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
68
|
+
it 'allows reverse order' do
|
69
|
+
described_class.ids(:reverse => true).should == @sorted_processes.reverse.map(&:wfid)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'allows combined reverse and pagination' do
|
73
|
+
described_class.ids(:reverse => true, :limit => 2).should == @sorted_processes.reverse[0, 2].map(&:wfid)
|
74
|
+
described_class.ids(:reverse => true, :offset => 2).should == @sorted_processes.reverse[2, 5].map(&:wfid)
|
75
|
+
described_class.ids(:reverse => true, :limit => 2, :offset => 1).should == @sorted_processes.reverse[1, 2].map(&:wfid)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '.count' do
|
80
|
+
it 'returns number of processes' do
|
81
|
+
allow(described_class).to receive(:ids).and_return([:a, :b, :c, :d])
|
82
|
+
described_class.count.should == 4
|
52
83
|
end
|
53
84
|
end
|
54
85
|
|
@@ -67,7 +98,7 @@ describe Bumbleworks::Process do
|
|
67
98
|
end
|
68
99
|
|
69
100
|
describe '#errors' do
|
70
|
-
it 'returns all process errors' do
|
101
|
+
it 'returns all process errors as ErrorRecord instances' do
|
71
102
|
Bumbleworks.define_process 'error_process' do
|
72
103
|
concurrence do
|
73
104
|
error 'first error'
|
@@ -77,25 +108,24 @@ describe Bumbleworks::Process do
|
|
77
108
|
bp = Bumbleworks.launch!('error_process')
|
78
109
|
Bumbleworks.dashboard.wait_for('error_intercepted')
|
79
110
|
errors = bp.errors
|
111
|
+
errors.map(&:class).uniq.should == [
|
112
|
+
Bumbleworks::Process::ErrorRecord
|
113
|
+
]
|
80
114
|
errors.map(&:message).should =~ [
|
81
|
-
'
|
82
|
-
'
|
115
|
+
'first error',
|
116
|
+
'second error'
|
83
117
|
]
|
84
118
|
end
|
85
119
|
end
|
86
120
|
|
87
121
|
describe '#workitems' do
|
88
|
-
it 'returns array of
|
122
|
+
it 'returns array of workitems from each leaf' do
|
89
123
|
bp = described_class.new('chumpy')
|
90
|
-
l1 = double(:
|
91
|
-
l2 = double(:
|
92
|
-
l3 = double(:
|
124
|
+
l1 = double(:workitem => 'w1')
|
125
|
+
l2 = double(:workitem => 'w2')
|
126
|
+
l3 = double(:workitem => 'w3')
|
93
127
|
bp.stub(:leaves => [l1, l2, l3])
|
94
|
-
bp.workitems.should == [
|
95
|
-
Bumbleworks::Workitem.new('aw1'),
|
96
|
-
Bumbleworks::Workitem.new('aw2'),
|
97
|
-
Bumbleworks::Workitem.new('aw3')
|
98
|
-
]
|
128
|
+
bp.workitems.should == ['w1','w2','w3']
|
99
129
|
end
|
100
130
|
end
|
101
131
|
|
@@ -109,6 +139,49 @@ describe Bumbleworks::Process do
|
|
109
139
|
let(:storage_workitem) { entity_workitem }
|
110
140
|
end
|
111
141
|
|
142
|
+
describe '#expressions' do
|
143
|
+
it 'returns all expressions as array of Expression instances' do
|
144
|
+
bp = Bumbleworks.launch!('food_is_an_illusion')
|
145
|
+
Bumbleworks.dashboard.wait_for(:admin)
|
146
|
+
expect(bp.expressions.map(&:expid)).to eq [
|
147
|
+
'0', '0_1', '0_1_0', '0_1_1'
|
148
|
+
]
|
149
|
+
expect(bp.expressions.map(&:class).uniq).to eq [
|
150
|
+
Bumbleworks::Expression
|
151
|
+
]
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe '#expression_at_position' do
|
156
|
+
before(:each) do
|
157
|
+
@bp = Bumbleworks.launch!('food_is_an_illusion')
|
158
|
+
Bumbleworks.dashboard.wait_for(:admin)
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'returns the expression whose expid matches the given position' do
|
162
|
+
expression = @bp.expression_at_position('0_1_0')
|
163
|
+
expect(expression).to be_a Bumbleworks::Expression
|
164
|
+
expect(expression.expid).to eq '0_1_0'
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'returns nil if no expression at given position' do
|
168
|
+
expect(@bp.expression_at_position('0_2_1')).to be_nil
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe '#leaves' do
|
173
|
+
it 'returns only expressions being worked on' do
|
174
|
+
bp = Bumbleworks.launch!('food_is_an_illusion')
|
175
|
+
Bumbleworks.dashboard.wait_for(:admin)
|
176
|
+
expect(bp.leaves.map(&:expid)).to eq [
|
177
|
+
'0_1_0', '0_1_1'
|
178
|
+
]
|
179
|
+
expect(bp.leaves.map(&:class).uniq).to eq [
|
180
|
+
Bumbleworks::Expression
|
181
|
+
]
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
112
185
|
describe '#entity_workitem' do
|
113
186
|
it 'returns first workitem from workitems array, if no entity fields conflict' do
|
114
187
|
bp = described_class.new('nothing')
|
@@ -260,6 +333,17 @@ describe Bumbleworks::Process do
|
|
260
333
|
end
|
261
334
|
end
|
262
335
|
|
336
|
+
describe '#<=>' do
|
337
|
+
it 'compares processes by wfid' do
|
338
|
+
bp1 = described_class.new(1)
|
339
|
+
bp2 = described_class.new(2)
|
340
|
+
bp3 = described_class.new(1)
|
341
|
+
expect(bp1 <=> bp2).to eq -1
|
342
|
+
expect(bp2 <=> bp3).to eq 1
|
343
|
+
expect(bp3 <=> bp1).to eq 0
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
263
347
|
describe '#process_status' do
|
264
348
|
it 'returns a process_status instance for the wfid' do
|
265
349
|
bp = described_class.new('frogheads')
|
@@ -22,6 +22,12 @@ describe Bumbleworks::Tracker do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
describe '.count' do
|
26
|
+
it 'returns count of current trackers' do
|
27
|
+
expect(described_class.count).to eq 5
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
25
31
|
describe '.new' do
|
26
32
|
it 'sets tracker id and fetches original_hash from dashboard' do
|
27
33
|
tr = described_class.new('global_tracker')
|
@@ -113,8 +119,8 @@ describe Bumbleworks::Tracker do
|
|
113
119
|
|
114
120
|
it 'returns expression awaiting reply' do
|
115
121
|
process = Bumbleworks::Process.new('my_wfid')
|
116
|
-
expression1 = double(:
|
117
|
-
expression2 = double(:
|
122
|
+
expression1 = double(:expid => '0_0_0', :tree => :a_global_expression)
|
123
|
+
expression2 = double(:expid => '0_0_1', :tree => :a_local_expression)
|
118
124
|
process.stub(:expressions => [expression1, expression2])
|
119
125
|
|
120
126
|
tracker1 = described_class.new('global_tracker')
|
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.
|
4
|
+
version: 0.0.72
|
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: 2014-
|
15
|
+
date: 2014-03-03 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: ruote
|
@@ -170,6 +170,7 @@ files:
|
|
170
170
|
- lib/bumbleworks/entity.rb
|
171
171
|
- lib/bumbleworks/error_handler.rb
|
172
172
|
- lib/bumbleworks/error_logger.rb
|
173
|
+
- lib/bumbleworks/expression.rb
|
173
174
|
- lib/bumbleworks/hash_storage.rb
|
174
175
|
- lib/bumbleworks/participant.rb
|
175
176
|
- lib/bumbleworks/participant_registration.rb
|
@@ -179,6 +180,7 @@ files:
|
|
179
180
|
- lib/bumbleworks/participants/participant.rb
|
180
181
|
- lib/bumbleworks/participants/storage_participant.rb
|
181
182
|
- lib/bumbleworks/process.rb
|
183
|
+
- lib/bumbleworks/process/error_record.rb
|
182
184
|
- lib/bumbleworks/process_definition.rb
|
183
185
|
- lib/bumbleworks/rake_tasks.rb
|
184
186
|
- lib/bumbleworks/ruote.rb
|
@@ -215,6 +217,7 @@ files:
|
|
215
217
|
- spec/fixtures/definitions/nested_folder/test_nested_process.rb
|
216
218
|
- spec/fixtures/definitions/test_process.rb
|
217
219
|
- spec/fixtures/entities/rainbow_loom.rb
|
220
|
+
- spec/fixtures/participants/naughty_participant.rb
|
218
221
|
- spec/fixtures/trackers.rb
|
219
222
|
- spec/integration/entity_spec.rb
|
220
223
|
- spec/integration/example_configurations_spec.rb
|
@@ -224,12 +227,14 @@ files:
|
|
224
227
|
- spec/lib/bumbleworks/entity_spec.rb
|
225
228
|
- spec/lib/bumbleworks/error_handler_spec.rb
|
226
229
|
- spec/lib/bumbleworks/error_logger_spec.rb
|
230
|
+
- spec/lib/bumbleworks/expression_spec.rb
|
227
231
|
- spec/lib/bumbleworks/hash_storage_spec.rb
|
228
232
|
- spec/lib/bumbleworks/participant/base_spec.rb
|
229
233
|
- spec/lib/bumbleworks/participant/entity_interactor_spec.rb
|
230
234
|
- spec/lib/bumbleworks/participant/error_dispatcher_spec.rb
|
231
235
|
- spec/lib/bumbleworks/participant/local_participant_spec.rb
|
232
236
|
- spec/lib/bumbleworks/participant_registration_spec.rb
|
237
|
+
- spec/lib/bumbleworks/process/error_record_spec.rb
|
233
238
|
- spec/lib/bumbleworks/process_definition_spec.rb
|
234
239
|
- spec/lib/bumbleworks/process_spec.rb
|
235
240
|
- spec/lib/bumbleworks/ruote/exp/broadcast_event_expression_spec.rb
|
@@ -266,7 +271,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
266
271
|
version: '0'
|
267
272
|
segments:
|
268
273
|
- 0
|
269
|
-
hash:
|
274
|
+
hash: -3659689790798964412
|
270
275
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
271
276
|
none: false
|
272
277
|
requirements:
|
@@ -275,7 +280,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
275
280
|
version: '0'
|
276
281
|
segments:
|
277
282
|
- 0
|
278
|
-
hash:
|
283
|
+
hash: -3659689790798964412
|
279
284
|
requirements: []
|
280
285
|
rubyforge_project:
|
281
286
|
rubygems_version: 1.8.23
|
@@ -300,6 +305,7 @@ test_files:
|
|
300
305
|
- spec/fixtures/definitions/nested_folder/test_nested_process.rb
|
301
306
|
- spec/fixtures/definitions/test_process.rb
|
302
307
|
- spec/fixtures/entities/rainbow_loom.rb
|
308
|
+
- spec/fixtures/participants/naughty_participant.rb
|
303
309
|
- spec/fixtures/trackers.rb
|
304
310
|
- spec/integration/entity_spec.rb
|
305
311
|
- spec/integration/example_configurations_spec.rb
|
@@ -309,12 +315,14 @@ test_files:
|
|
309
315
|
- spec/lib/bumbleworks/entity_spec.rb
|
310
316
|
- spec/lib/bumbleworks/error_handler_spec.rb
|
311
317
|
- spec/lib/bumbleworks/error_logger_spec.rb
|
318
|
+
- spec/lib/bumbleworks/expression_spec.rb
|
312
319
|
- spec/lib/bumbleworks/hash_storage_spec.rb
|
313
320
|
- spec/lib/bumbleworks/participant/base_spec.rb
|
314
321
|
- spec/lib/bumbleworks/participant/entity_interactor_spec.rb
|
315
322
|
- spec/lib/bumbleworks/participant/error_dispatcher_spec.rb
|
316
323
|
- spec/lib/bumbleworks/participant/local_participant_spec.rb
|
317
324
|
- spec/lib/bumbleworks/participant_registration_spec.rb
|
325
|
+
- spec/lib/bumbleworks/process/error_record_spec.rb
|
318
326
|
- spec/lib/bumbleworks/process_definition_spec.rb
|
319
327
|
- spec/lib/bumbleworks/process_spec.rb
|
320
328
|
- spec/lib/bumbleworks/ruote/exp/broadcast_event_expression_spec.rb
|