bumbleworks 0.0.78 → 0.0.79

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.
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