bumbleworks 0.0.34 → 0.0.35

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.
@@ -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!
@@ -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
- before_update(metadata)
97
- update_workitem
98
- log(:update, metadata)
99
- after_update(metadata)
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
- before_update(metadata)
106
- before_complete(metadata)
107
- proceed_workitem
108
- log(:complete, metadata)
109
- after_complete(metadata)
110
- after_update(metadata)
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
- before_claim(token)
126
- set_claimant(token)
127
- log(:claim)
128
- after_claim(token)
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
- before_release(current_claimant)
140
- log(:release)
141
- set_claimant(nil)
142
- after_release(current_claimant)
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
- after_dispatch
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 Bumbleworks::Task::AvailabilityTimeout, "No tasks found matching criteria in time"
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
- Task.new(wi) if wi.params['task']
81
+ @task_class.new(wi) if wi.params['task']
72
82
  }.compact
73
83
  end
74
84
  end
@@ -1,3 +1,3 @@
1
1
  module Bumbleworks
2
- VERSION = "0.0.34"
2
+ VERSION = "0.0.35"
3
3
  end
@@ -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, and triggers callback' do
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 after_dispatch callback' do
122
+ it 'calls after hooks' do
109
123
  task = described_class.new(workflow_item)
110
124
  task.stub(:log)
111
- task.should_receive(:after_dispatch)
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 before_release and after_release callbacks' do
475
- @task.should_receive(:before_release).with('boss').ordered
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(:after_release).with('boss').ordered
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 before_update and after_update callbacks' do
578
+ it 'calls with hooks' do
512
579
  task = described_class.new(workflow_item)
513
580
  task.stub(:log)
514
- task.should_receive(:before_update).with(:argue_mints).ordered
581
+ task.should_receive(:call_before_hooks).with(:update, :argue_mints).ordered
515
582
  task.should_receive(:update_workitem).ordered
516
- task.should_receive(:after_update).with(:argue_mints).ordered
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(:before_update).with(:argue_mints).ordered
574
- task.should_receive(:before_complete).with(:argue_mints).ordered
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(:after_complete).with(:argue_mints).ordered
577
- task.should_receive(:after_update).with(:argue_mints).ordered
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.34
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-08-21 00:00:00.000000000 Z
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: