bumbleworks 0.0.34 → 0.0.35
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/bumbleworks/configuration.rb +8 -0
- data/lib/bumbleworks/task.rb +39 -20
- data/lib/bumbleworks/task/finder.rb +13 -3
- data/lib/bumbleworks/version.rb +1 -1
- data/spec/lib/bumbleworks/configuration_spec.rb +12 -0
- data/spec/lib/bumbleworks/task/finder_spec.rb +34 -0
- data/spec/lib/bumbleworks/task_spec.rb +80 -13
- metadata +10 -3
@@ -83,6 +83,10 @@ module Bumbleworks
|
|
83
83
|
# default: Bumbleworks::SimpleLogger
|
84
84
|
define_setting :logger
|
85
85
|
|
86
|
+
# All before_* and after_* callback methods prototyped in Tasks::Base will
|
87
|
+
# also be called on all registered observers.
|
88
|
+
define_setting :observers
|
89
|
+
|
86
90
|
def initialize
|
87
91
|
@storage_adapters = []
|
88
92
|
end
|
@@ -149,6 +153,10 @@ module Bumbleworks
|
|
149
153
|
@logger ||= Bumbleworks::SimpleLogger
|
150
154
|
end
|
151
155
|
|
156
|
+
def observers
|
157
|
+
@observers ||= []
|
158
|
+
end
|
159
|
+
|
152
160
|
# Clears all memoize variables and configuration settings
|
153
161
|
#
|
154
162
|
def clear!
|
data/lib/bumbleworks/task.rb
CHANGED
@@ -33,7 +33,7 @@ module Bumbleworks
|
|
33
33
|
|
34
34
|
def method_missing(method, *args)
|
35
35
|
if Finder.new.respond_to?(method)
|
36
|
-
return Finder.new.send(method, *args)
|
36
|
+
return Finder.new([], self).send(method, *args)
|
37
37
|
end
|
38
38
|
super
|
39
39
|
end
|
@@ -91,23 +91,37 @@ module Bumbleworks
|
|
91
91
|
klass = Bumbleworks::Support.constantize("#{klass_name}Task")
|
92
92
|
end
|
93
93
|
|
94
|
+
def call_before_hooks(action, *args)
|
95
|
+
call_hooks(:before, action, *args)
|
96
|
+
end
|
97
|
+
|
98
|
+
def call_after_hooks(action, *args)
|
99
|
+
call_hooks(:after, action, *args)
|
100
|
+
end
|
101
|
+
|
102
|
+
def with_hooks(action, *args, &block)
|
103
|
+
call_before_hooks(action, *args)
|
104
|
+
yield
|
105
|
+
call_after_hooks(action, *args)
|
106
|
+
end
|
107
|
+
|
94
108
|
# update workitem with changes to fields & params
|
95
109
|
def update(metadata = {})
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
110
|
+
with_hooks(:update, metadata) do
|
111
|
+
update_workitem
|
112
|
+
log(:update, metadata)
|
113
|
+
end
|
100
114
|
end
|
101
115
|
|
102
116
|
# proceed workitem (saving changes to fields)
|
103
117
|
def complete(metadata = {})
|
104
118
|
raise NotCompletable.new(not_completable_error_message) unless completable?
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
119
|
+
with_hooks(:update, metadata) do
|
120
|
+
with_hooks(:complete, metadata) do
|
121
|
+
proceed_workitem
|
122
|
+
log(:complete, metadata)
|
123
|
+
end
|
124
|
+
end
|
111
125
|
end
|
112
126
|
|
113
127
|
# Token used to claim task, nil if not claimed
|
@@ -122,10 +136,10 @@ module Bumbleworks
|
|
122
136
|
|
123
137
|
# Claim task and assign token to claimant
|
124
138
|
def claim(token)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
139
|
+
with_hooks(:claim, token) do
|
140
|
+
set_claimant(token)
|
141
|
+
log(:claim)
|
142
|
+
end
|
129
143
|
end
|
130
144
|
|
131
145
|
# true if task is claimed
|
@@ -136,15 +150,15 @@ module Bumbleworks
|
|
136
150
|
# release claim on task.
|
137
151
|
def release
|
138
152
|
current_claimant = claimant
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
153
|
+
with_hooks(:release, current_claimant) do
|
154
|
+
log(:release)
|
155
|
+
set_claimant(nil)
|
156
|
+
end
|
143
157
|
end
|
144
158
|
|
145
159
|
def on_dispatch
|
146
160
|
log(:dispatch)
|
147
|
-
|
161
|
+
call_after_hooks(:dispatch)
|
148
162
|
end
|
149
163
|
|
150
164
|
def log(action, metadata = {})
|
@@ -170,6 +184,11 @@ module Bumbleworks
|
|
170
184
|
end
|
171
185
|
|
172
186
|
private
|
187
|
+
def call_hooks(phase, action, *args)
|
188
|
+
(Bumbleworks.observers + [self]).each do |observer|
|
189
|
+
observer.send(:"#{phase}_#{action}", *args)
|
190
|
+
end
|
191
|
+
end
|
173
192
|
|
174
193
|
def displayify(modifier, options = {})
|
175
194
|
task_name = Bumbleworks::Support.send(modifier, nickname)
|
@@ -3,8 +3,9 @@ module Bumbleworks
|
|
3
3
|
class Finder
|
4
4
|
include Enumerable
|
5
5
|
|
6
|
-
def initialize(queries = [])
|
6
|
+
def initialize(queries = [], task_class = Bumbleworks::Task)
|
7
7
|
@queries = queries
|
8
|
+
@task_class = task_class
|
8
9
|
end
|
9
10
|
|
10
11
|
def by_nickname(nickname)
|
@@ -22,6 +23,15 @@ module Bumbleworks
|
|
22
23
|
for_roles([identifier])
|
23
24
|
end
|
24
25
|
|
26
|
+
def unclaimed(check = true)
|
27
|
+
@queries << proc { |wi| wi['fields']['params']['claimant'].nil? == check }
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def claimed
|
32
|
+
unclaimed(false)
|
33
|
+
end
|
34
|
+
|
25
35
|
def for_claimant(token)
|
26
36
|
@queries << proc { |wi| wi['fields']['params']['claimant'] == token }
|
27
37
|
self
|
@@ -57,7 +67,7 @@ module Bumbleworks
|
|
57
67
|
start_time = Time.now
|
58
68
|
while first.nil?
|
59
69
|
if (Time.now - start_time) > options[:timeout]
|
60
|
-
raise
|
70
|
+
raise @task_class::AvailabilityTimeout, "No tasks found matching criteria in time"
|
61
71
|
end
|
62
72
|
sleep 0.1
|
63
73
|
end
|
@@ -68,7 +78,7 @@ module Bumbleworks
|
|
68
78
|
|
69
79
|
def from_workitems(workitems)
|
70
80
|
workitems.map { |wi|
|
71
|
-
|
81
|
+
@task_class.new(wi) if wi.params['task']
|
72
82
|
}.compact
|
73
83
|
end
|
74
84
|
end
|
data/lib/bumbleworks/version.rb
CHANGED
@@ -192,6 +192,18 @@ describe Bumbleworks::Configuration do
|
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
195
|
+
describe '#observers' do
|
196
|
+
it 'is empty by default' do
|
197
|
+
configuration.observers.should be_empty
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'returns the registered observers' do
|
201
|
+
configuration.observers = [:smash, :pumpkin]
|
202
|
+
configuration.observers << :rhubarb
|
203
|
+
configuration.observers.should == [:smash, :pumpkin, :rhubarb]
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
195
207
|
describe "#storage" do
|
196
208
|
it 'can set storage directly' do
|
197
209
|
storage = double("Storage")
|
@@ -0,0 +1,34 @@
|
|
1
|
+
describe Bumbleworks::Task::Finder do
|
2
|
+
before :each do
|
3
|
+
Bumbleworks.reset!
|
4
|
+
Bumbleworks.storage = {}
|
5
|
+
Bumbleworks::Ruote.register_participants
|
6
|
+
Bumbleworks.start_worker!
|
7
|
+
Bumbleworks.define_process 'dog-lifecycle' do
|
8
|
+
concurrence do
|
9
|
+
dog :task => 'eat'
|
10
|
+
dog :task => 'bark'
|
11
|
+
dog :task => 'pet_dog'
|
12
|
+
cat :task => 'skip_and_jump'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#all' do
|
18
|
+
it 'uses Bumbleworks::Task class by default for task generation' do
|
19
|
+
Bumbleworks.launch!('dog-lifecycle')
|
20
|
+
Bumbleworks.dashboard.wait_for(:cat)
|
21
|
+
tasks = Bumbleworks::Task::Finder.new.all
|
22
|
+
tasks.should be_all { |t| t.class == Bumbleworks::Task }
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'uses provided class for task generation' do
|
26
|
+
class MyOwnTask < Bumbleworks::Task; end
|
27
|
+
Bumbleworks.launch!('dog-lifecycle')
|
28
|
+
Bumbleworks.dashboard.wait_for(:cat)
|
29
|
+
tasks = Bumbleworks::Task::Finder.new([], MyOwnTask).all
|
30
|
+
tasks.should be_all { |t| t.class == MyOwnTask }
|
31
|
+
Object.send(:remove_const, :MyOwnTask)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -80,6 +80,20 @@ describe Bumbleworks::Task do
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
+
[:before, :after].each do |phase|
|
84
|
+
describe "#call_#{phase}_hooks" do
|
85
|
+
it "calls #{phase} hooks on task and all observers" do
|
86
|
+
observer1, observer2 = double('observer1'), double('observer2')
|
87
|
+
Bumbleworks.observers = [observer1, observer2]
|
88
|
+
task = described_class.new(workflow_item)
|
89
|
+
task.should_receive(:"#{phase}_snoogle").with(:chachunga, :faloop)
|
90
|
+
observer1.should_receive(:"#{phase}_snoogle").with(:chachunga, :faloop)
|
91
|
+
observer2.should_receive(:"#{phase}_snoogle").with(:chachunga, :faloop)
|
92
|
+
task.send(:"call_#{phase}_hooks", :snoogle, :chachunga, :faloop)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
83
97
|
describe '#on_dispatch' do
|
84
98
|
before :each do
|
85
99
|
Bumbleworks.define_process 'planting_a_noodle' do
|
@@ -89,7 +103,7 @@ describe Bumbleworks::Task do
|
|
89
103
|
end
|
90
104
|
end
|
91
105
|
|
92
|
-
it 'is called when task is dispatched
|
106
|
+
it 'is called when task is dispatched' do
|
93
107
|
described_class.any_instance.should_receive(:on_dispatch)
|
94
108
|
Bumbleworks.launch!('planting_a_noodle')
|
95
109
|
Bumbleworks.dashboard.wait_for(:horse_feeder)
|
@@ -105,10 +119,10 @@ describe Bumbleworks::Task do
|
|
105
119
|
log_entry[:target_id].should == task.id
|
106
120
|
end
|
107
121
|
|
108
|
-
it 'calls
|
122
|
+
it 'calls after hooks' do
|
109
123
|
task = described_class.new(workflow_item)
|
110
124
|
task.stub(:log)
|
111
|
-
task.should_receive(:
|
125
|
+
task.should_receive(:call_after_hooks).with(:dispatch)
|
112
126
|
task.on_dispatch
|
113
127
|
end
|
114
128
|
end
|
@@ -256,6 +270,51 @@ describe Bumbleworks::Task do
|
|
256
270
|
end
|
257
271
|
end
|
258
272
|
|
273
|
+
describe '.unclaimed' do
|
274
|
+
it 'returns all unclaimed tasks' do
|
275
|
+
Bumbleworks.define_process 'dog-lifecycle' do
|
276
|
+
concurrence do
|
277
|
+
dog :task => 'eat'
|
278
|
+
dog :task => 'bark'
|
279
|
+
dog :task => 'pet_dog'
|
280
|
+
cat :task => 'skip_and_jump'
|
281
|
+
end
|
282
|
+
dog :task => 'nap'
|
283
|
+
end
|
284
|
+
Bumbleworks.launch!('dog-lifecycle')
|
285
|
+
Bumbleworks.dashboard.wait_for(:cat)
|
286
|
+
@unclaimed = described_class.unclaimed
|
287
|
+
@unclaimed.map(&:nickname).should =~ ['eat', 'bark', 'pet_dog', 'skip_and_jump']
|
288
|
+
described_class.all.each do |t|
|
289
|
+
t.claim('radish') unless ['pet_dog', 'bark'].include?(t.nickname)
|
290
|
+
end
|
291
|
+
@unclaimed = described_class.unclaimed
|
292
|
+
@unclaimed.map(&:nickname).should =~ ['pet_dog', 'bark']
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
describe '.claimed' do
|
297
|
+
it 'returns all claimed tasks' do
|
298
|
+
Bumbleworks.define_process 'dog-lifecycle' do
|
299
|
+
concurrence do
|
300
|
+
dog :task => 'eat'
|
301
|
+
dog :task => 'bark'
|
302
|
+
dog :task => 'pet_dog'
|
303
|
+
cat :task => 'skip_and_jump'
|
304
|
+
end
|
305
|
+
dog :task => 'nap'
|
306
|
+
end
|
307
|
+
Bumbleworks.launch!('dog-lifecycle')
|
308
|
+
Bumbleworks.dashboard.wait_for(:cat)
|
309
|
+
described_class.claimed.should be_empty
|
310
|
+
described_class.all.each_with_index do |t, i|
|
311
|
+
t.claim("radish_#{i}") unless ['pet_dog', 'bark'].include?(t.nickname)
|
312
|
+
end
|
313
|
+
@claimed = described_class.claimed
|
314
|
+
@claimed.map(&:nickname).should =~ ['eat', 'skip_and_jump']
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
259
318
|
describe '.all' do
|
260
319
|
before :each do
|
261
320
|
Bumbleworks.define_process 'dog-lifecycle' do
|
@@ -282,6 +341,14 @@ describe Bumbleworks::Task do
|
|
282
341
|
['dog_legs', 'skip_and_jump']
|
283
342
|
]
|
284
343
|
end
|
344
|
+
|
345
|
+
it 'uses subclass for generation of tasks' do
|
346
|
+
class MyOwnTask < Bumbleworks::Task; end
|
347
|
+
Bumbleworks.dashboard.wait_for(:dog_legs)
|
348
|
+
tasks = MyOwnTask.all
|
349
|
+
tasks.should be_all { |t| t.class == MyOwnTask }
|
350
|
+
Object.send(:remove_const, :MyOwnTask)
|
351
|
+
end
|
285
352
|
end
|
286
353
|
|
287
354
|
describe '#[], #[]=' do
|
@@ -471,10 +538,10 @@ describe Bumbleworks::Task do
|
|
471
538
|
@task.params['claimed_at'].should be_nil
|
472
539
|
end
|
473
540
|
|
474
|
-
it 'calls
|
475
|
-
@task.should_receive(:
|
541
|
+
it 'calls with hooks' do
|
542
|
+
@task.should_receive(:call_before_hooks).with(:release, 'boss').ordered
|
476
543
|
@task.should_receive(:set_claimant).ordered
|
477
|
-
@task.should_receive(:
|
544
|
+
@task.should_receive(:call_after_hooks).with(:release, 'boss').ordered
|
478
545
|
@task.release
|
479
546
|
end
|
480
547
|
|
@@ -508,12 +575,12 @@ describe Bumbleworks::Task do
|
|
508
575
|
task.fields['meal'].should == 'salted_rhubarb'
|
509
576
|
end
|
510
577
|
|
511
|
-
it 'calls
|
578
|
+
it 'calls with hooks' do
|
512
579
|
task = described_class.new(workflow_item)
|
513
580
|
task.stub(:log)
|
514
|
-
task.should_receive(:
|
581
|
+
task.should_receive(:call_before_hooks).with(:update, :argue_mints).ordered
|
515
582
|
task.should_receive(:update_workitem).ordered
|
516
|
-
task.should_receive(:
|
583
|
+
task.should_receive(:call_after_hooks).with(:update, :argue_mints).ordered
|
517
584
|
task.update(:argue_mints)
|
518
585
|
end
|
519
586
|
|
@@ -570,11 +637,11 @@ describe Bumbleworks::Task do
|
|
570
637
|
it 'calls update and complete callbacks' do
|
571
638
|
task = described_class.new(workflow_item)
|
572
639
|
task.stub(:log)
|
573
|
-
task.should_receive(:
|
574
|
-
task.should_receive(:
|
640
|
+
task.should_receive(:call_before_hooks).with(:update, :argue_mints).ordered
|
641
|
+
task.should_receive(:call_before_hooks).with(:complete, :argue_mints).ordered
|
575
642
|
task.should_receive(:proceed_workitem).ordered
|
576
|
-
task.should_receive(:
|
577
|
-
task.should_receive(:
|
643
|
+
task.should_receive(:call_after_hooks).with(:complete, :argue_mints).ordered
|
644
|
+
task.should_receive(:call_after_hooks).with(:update, :argue_mints).ordered
|
578
645
|
task.complete(:argue_mints)
|
579
646
|
end
|
580
647
|
|
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.35
|
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-
|
15
|
+
date: 2013-09-12 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: ruote
|
@@ -213,6 +213,7 @@ files:
|
|
213
213
|
- spec/lib/bumbleworks/simple_logger_spec.rb
|
214
214
|
- spec/lib/bumbleworks/storage_adapter_spec.rb
|
215
215
|
- spec/lib/bumbleworks/support_spec.rb
|
216
|
+
- spec/lib/bumbleworks/task/finder_spec.rb
|
216
217
|
- spec/lib/bumbleworks/task_spec.rb
|
217
218
|
- spec/lib/bumbleworks/tree_builder_spec.rb
|
218
219
|
- spec/lib/bumbleworks/workitem_entity_storage_spec.rb
|
@@ -233,12 +234,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
233
234
|
- - ! '>='
|
234
235
|
- !ruby/object:Gem::Version
|
235
236
|
version: '0'
|
237
|
+
segments:
|
238
|
+
- 0
|
239
|
+
hash: -265632514630841988
|
236
240
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
237
241
|
none: false
|
238
242
|
requirements:
|
239
243
|
- - ! '>='
|
240
244
|
- !ruby/object:Gem::Version
|
241
245
|
version: '0'
|
246
|
+
segments:
|
247
|
+
- 0
|
248
|
+
hash: -265632514630841988
|
242
249
|
requirements: []
|
243
250
|
rubyforge_project:
|
244
251
|
rubygems_version: 1.8.23
|
@@ -273,6 +280,7 @@ test_files:
|
|
273
280
|
- spec/lib/bumbleworks/simple_logger_spec.rb
|
274
281
|
- spec/lib/bumbleworks/storage_adapter_spec.rb
|
275
282
|
- spec/lib/bumbleworks/support_spec.rb
|
283
|
+
- spec/lib/bumbleworks/task/finder_spec.rb
|
276
284
|
- spec/lib/bumbleworks/task_spec.rb
|
277
285
|
- spec/lib/bumbleworks/tree_builder_spec.rb
|
278
286
|
- spec/lib/bumbleworks/workitem_entity_storage_spec.rb
|
@@ -280,4 +288,3 @@ test_files:
|
|
280
288
|
- spec/spec_helper.rb
|
281
289
|
- spec/support/path_helpers.rb
|
282
290
|
- spec/support/tracer.rb
|
283
|
-
has_rdoc:
|