bumbleworks 0.0.71 → 0.0.72
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.
- 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
|