bumbleworks 0.0.78 → 0.0.79

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 93db3b577ea6a3ae073459e9fd407d9aeb217c40
4
- data.tar.gz: 20fae058c24f92274ebe9ba5d1929e9ac972960c
3
+ metadata.gz: 4318f91e073ccdd49dc2cd628c7f93991e2214da
4
+ data.tar.gz: 529b85a2177008687c9bfb0bba2abbb0b00be213
5
5
  SHA512:
6
- metadata.gz: 90190f2f09fdd353d63dcd4fc9d5bf7b2a78df2952993b791dbdddf940b933f74494dec8c7ed69229bb5e9902b2cb98b7831eb2771687edf3fc4e8cc12e3009a
7
- data.tar.gz: 5ad45cb7eb9e3d7574deb08f17f0662b7a777e9de5f366f142056db0eb22dc04f120e135f242001e8bd3ff3a3a8262455a4bd1114984f850d6ba162748a36331
6
+ metadata.gz: b47f0e5543948f413dc6b83bd368db1685ddc5d1fbc6a399e2f2ff0d5d40a92bbb7c92ba9b32d3ccace51915251369ba9fa4095c2af5826711d8a5100e8c5751
7
+ data.tar.gz: c9b44b6f6dd055b8f0afa70f2d7d8161b6b6654cfae1cb335a865ed170f6d0ed2dd8b9f2d4674eb40402677d19ec2395af56eeb941c361163ca8c1558bd1d0ad
@@ -1,4 +1,5 @@
1
1
  require "ruote"
2
+ require_relative "worker.rb"
2
3
 
3
4
  Dir[File.join(File.dirname(__FILE__), 'ruote', 'exp', '*.rb')].each { |f| require f }
4
5
 
@@ -31,7 +32,7 @@ module Bumbleworks
31
32
  set_up_storage_history
32
33
  register_error_dispatcher
33
34
  dashboard.noisy = options[:verbose] == true
34
- worker = ::Ruote::Worker.new(dashboard.context)
35
+ worker = Bumbleworks::Worker.new(dashboard.context)
35
36
  if options[:join] == true
36
37
  worker.run
37
38
  else
@@ -1,3 +1,3 @@
1
1
  module Bumbleworks
2
- VERSION = "0.0.78"
2
+ VERSION = "0.0.79"
3
3
  end
@@ -0,0 +1,133 @@
1
+ require 'securerandom'
2
+
3
+ class Bumbleworks::Worker < Ruote::Worker
4
+ class WorkerStateNotChanged < StandardError; end
5
+
6
+ attr_reader :id
7
+
8
+ class << self
9
+ def info
10
+ Bumbleworks.dashboard.worker_info
11
+ end
12
+
13
+ def shutdown_all(options = {})
14
+ change_worker_state('stopped', options)
15
+ end
16
+
17
+ def pause_all(options = {})
18
+ change_worker_state('paused', options)
19
+ end
20
+
21
+ def unpause_all(options = {})
22
+ change_worker_state('running', options)
23
+ end
24
+
25
+ def worker_states
26
+ Bumbleworks.dashboard.worker_info.inject({}) { |hsh, info|
27
+ id, state = info[0], info[1]['state']
28
+ if state && state != 'stopped'
29
+ hsh[id] = state
30
+ end
31
+ hsh
32
+ }
33
+ end
34
+
35
+ def forget_worker(id_to_delete)
36
+ purge_worker_info do |id, info|
37
+ id == id_to_delete
38
+ end
39
+ end
40
+
41
+ def purge_stale_worker_info
42
+ purge_worker_info do |id, info|
43
+ info['state'].nil? || info['state'] == 'stopped'
44
+ end
45
+ end
46
+
47
+ def purge_worker_info(&block)
48
+ doc = Bumbleworks.dashboard.storage.get('variables', 'workers')
49
+ doc['workers'] = doc['workers'].reject { |id, info|
50
+ block.call(id, info)
51
+ }
52
+ result = Bumbleworks.dashboard.storage.put(doc)
53
+ purge_stale_worker_info if result
54
+ info
55
+ end
56
+
57
+ def change_worker_state(new_state, options = {})
58
+ options[:timeout] ||= Bumbleworks.timeout
59
+ with_worker_state_enabled do
60
+ Bumbleworks.dashboard.worker_state = new_state
61
+ start_time = Time.now
62
+ until worker_states.values.all? { |state| state == new_state }
63
+ if (Time.now - start_time) > options[:timeout]
64
+ raise WorkerStateNotChanged, "Worker states: #{worker_states.inspect}"
65
+ end
66
+ sleep 0.1
67
+ end
68
+ end
69
+ return true
70
+ end
71
+
72
+ def with_worker_state_enabled
73
+ Bumbleworks.dashboard.context['worker_state_enabled'] = true
74
+ yield
75
+ Bumbleworks.dashboard.context['worker_state_enabled'] = false
76
+ end
77
+ end
78
+
79
+ def initialize(*args, &block)
80
+ super
81
+ @id = SecureRandom.uuid
82
+ if @info
83
+ @info = Info.new(self)
84
+ save_info
85
+ end
86
+ end
87
+
88
+ def save_info
89
+ @info.save_with_cleanup if @info
90
+ end
91
+
92
+ def shutdown
93
+ super
94
+ save_info
95
+ end
96
+
97
+ def determine_state
98
+ if @context['worker_state_enabled']
99
+ super
100
+ save_info
101
+ end
102
+ end
103
+
104
+ class Info < Ruote::Worker::Info
105
+ def <<(msg)
106
+ super
107
+ cleanup_saved_info if Time.now > @last_save + 60
108
+ end
109
+
110
+ def save_with_cleanup
111
+ save
112
+ cleanup_saved_info
113
+ end
114
+
115
+ def cleanup_saved_info
116
+ key = [@worker.name, @ip.gsub(/\./, '_'), $$.to_s].join('/')
117
+ doc = @worker.storage.get('variables', 'workers')
118
+ existing_worker_info = doc['workers'].delete(key)
119
+ if existing_worker_info
120
+ doc['workers'][@worker.id] = existing_worker_info.merge({
121
+ 'state' => @worker.state,
122
+ 'name' => @worker.name
123
+ })
124
+ result = @worker.storage.put(doc)
125
+ # result will be nil if put succeeded; if it's not,
126
+ # let's try again
127
+ cleanup_saved_info if result
128
+ else
129
+ cleanup_saved_info
130
+ end
131
+ end
132
+ end
133
+ end
@@ -218,18 +218,18 @@ describe Bumbleworks::Ruote do
218
218
  it 'adds new worker to dashboard and returns worker' do
219
219
  expect(described_class.dashboard.worker).to be_nil
220
220
  new_worker = described_class.start_worker!
221
- expect(new_worker).to be_an_instance_of(Ruote::Worker)
221
+ expect(new_worker).to be_an_instance_of(Bumbleworks::Worker)
222
222
  expect(described_class.dashboard.worker).to eq(new_worker)
223
223
  end
224
224
 
225
225
  it 'runs in current thread if :join option is true' do
226
- allow(::Ruote::Worker).to receive(:new).and_return(worker_double = double('worker'))
226
+ allow(Bumbleworks::Worker).to receive(:new).and_return(worker_double = double('worker'))
227
227
  expect(worker_double).to receive(:run)
228
228
  described_class.start_worker!(:join => true)
229
229
  end
230
230
 
231
231
  it 'runs in new thread and returns worker if :join option not true' do
232
- allow(::Ruote::Worker).to receive(:new).and_return(worker_double = double('worker'))
232
+ allow(Bumbleworks::Worker).to receive(:new).and_return(worker_double = double('worker'))
233
233
  expect(worker_double).to receive(:run_in_thread)
234
234
  expect(described_class.start_worker!).to eq(worker_double)
235
235
  end
@@ -0,0 +1,130 @@
1
+ require 'pry'
2
+
3
+ describe Bumbleworks::Worker do
4
+ let(:context) { Bumbleworks.dashboard.context }
5
+ subject { described_class.new(context) }
6
+
7
+ it 'is a Ruote::Worker' do
8
+ expect(subject).to be_a(Ruote::Worker)
9
+ end
10
+
11
+ describe '.new' do
12
+ it 'saves the worker info to a storage variable' do
13
+ subject
14
+ workers = Bumbleworks.dashboard.worker_info
15
+ expect(workers.count).to eq(1)
16
+ expect(workers.keys.first).to eq(subject.id)
17
+ end
18
+ end
19
+
20
+ context 'with multiple workers' do
21
+ let!(:workers) {
22
+ 2.times.map { |i|
23
+ worker = described_class.new(context)
24
+ worker.run_in_thread
25
+ worker
26
+ }
27
+ }
28
+
29
+ describe '.worker_states' do
30
+ it 'returns the states of all active workers' do
31
+ subject.run_in_thread
32
+ expect(described_class.worker_states).to eq({
33
+ subject.id => 'running',
34
+ workers[0].id => 'running',
35
+ workers[1].id => 'running'
36
+ })
37
+ end
38
+
39
+ it 'does not include stopped or nil states' do
40
+ subject.run_in_thread
41
+ workers[0].shutdown
42
+ workers[1].instance_variable_set(:@state, nil)
43
+ workers[1].instance_variable_get(:@info).save_with_cleanup
44
+ expect(described_class.worker_states).to eq({
45
+ subject.id => 'running'
46
+ })
47
+ end
48
+ end
49
+
50
+ describe '.info' do
51
+ it 'returns Bumbleworks.dashboard.worker_info' do
52
+ allow(Bumbleworks.dashboard).to receive(:worker_info).and_return(:bontron)
53
+ expect(described_class.info).to eq(:bontron)
54
+ end
55
+ end
56
+
57
+ describe '.forget_worker' do
58
+ it 'deletes worker info for given worker id' do
59
+ described_class.forget_worker(workers[1].id)
60
+ expect(described_class.info.keys).not_to include(workers[1].id)
61
+ end
62
+ end
63
+
64
+ describe '.purge_stale_worker_info' do
65
+ it 'deletes all worker info where state is stopped or nil' do
66
+ subject.run_in_thread
67
+ workers[0].shutdown
68
+ workers[1].instance_variable_set(:@state, nil)
69
+ workers[1].instance_variable_get(:@info).save_with_cleanup
70
+ subject_info = described_class.info[subject.id]
71
+ described_class.purge_stale_worker_info
72
+ expect(described_class.info).to eq({
73
+ subject.id => subject_info
74
+ })
75
+ end
76
+ end
77
+
78
+ describe '.change_worker_state' do
79
+ it 'changes state of all workers' do
80
+ expect(workers.map(&:state).uniq).to eq(['running'])
81
+ described_class.change_worker_state('paused')
82
+ expect(workers.map(&:state).uniq).to eq(['paused'])
83
+ end
84
+
85
+ it 'times out if worker states not changed in time' do
86
+ # Stub setting of worker state so workers are never stopped
87
+ allow(Bumbleworks.dashboard).to receive(:worker_state=)
88
+ expect {
89
+ described_class.change_worker_state('paused', :timeout => 0)
90
+ }.to raise_error(described_class::WorkerStateNotChanged)
91
+ end
92
+
93
+ it 'ignores already stopped workers' do
94
+ described_class.shutdown_all
95
+ subject.run_in_thread
96
+ described_class.change_worker_state('paused')
97
+ expect(subject.state).to eq('paused')
98
+ expect(workers.map(&:state)).to eq(['stopped', 'stopped'])
99
+ end
100
+ end
101
+ end
102
+
103
+ describe '.shutdown_all' do
104
+ it 'changes all worker states to stopped' do
105
+ expect(described_class).to receive(:change_worker_state).with('stopped', {})
106
+ described_class.shutdown_all
107
+ end
108
+ end
109
+
110
+ describe '.pause_all' do
111
+ it 'changes all worker states to paused' do
112
+ expect(described_class).to receive(:change_worker_state).with('paused', {})
113
+ described_class.pause_all
114
+ end
115
+ end
116
+
117
+ describe '.unpause_all' do
118
+ it 'changes all worker states to running' do
119
+ expect(described_class).to receive(:change_worker_state).with('running', {})
120
+ described_class.unpause_all
121
+ end
122
+ end
123
+
124
+ describe '#id' do
125
+ it 'returns generated uuid' do
126
+ allow(SecureRandom).to receive(:uuid).and_return('smokeeeeys')
127
+ expect(subject.id).to eq('smokeeeeys')
128
+ end
129
+ end
130
+ end
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.78
4
+ version: 0.0.79
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maher Hawash
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-08-03 00:00:00.000000000 Z
14
+ date: 2014-08-10 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: ruote
@@ -181,6 +181,7 @@ files:
181
181
  - lib/bumbleworks/tree_builder.rb
182
182
  - lib/bumbleworks/user.rb
183
183
  - lib/bumbleworks/version.rb
184
+ - lib/bumbleworks/worker.rb
184
185
  - lib/bumbleworks/workitem.rb
185
186
  - lib/bumbleworks/workitem_entity_storage.rb
186
187
  - lib/tasks/bumbleworks.rake
@@ -234,6 +235,7 @@ files:
234
235
  - spec/lib/bumbleworks/tracker_spec.rb
235
236
  - spec/lib/bumbleworks/tree_builder_spec.rb
236
237
  - spec/lib/bumbleworks/user_spec.rb
238
+ - spec/lib/bumbleworks/worker_spec.rb
237
239
  - spec/lib/bumbleworks/workitem_entity_storage_spec.rb
238
240
  - spec/lib/bumbleworks/workitem_spec.rb
239
241
  - spec/lib/bumbleworks_spec.rb
@@ -317,6 +319,7 @@ test_files:
317
319
  - spec/lib/bumbleworks/tracker_spec.rb
318
320
  - spec/lib/bumbleworks/tree_builder_spec.rb
319
321
  - spec/lib/bumbleworks/user_spec.rb
322
+ - spec/lib/bumbleworks/worker_spec.rb
320
323
  - spec/lib/bumbleworks/workitem_entity_storage_spec.rb
321
324
  - spec/lib/bumbleworks/workitem_spec.rb
322
325
  - spec/lib/bumbleworks_spec.rb