concurrent-ruby 0.1.1.pre.5 → 0.1.1
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 +4 -4
- data/README.md +1 -48
- data/lib/concurrent.rb +0 -6
- data/lib/concurrent/agent.rb +40 -19
- data/lib/concurrent/cached_thread_pool.rb +11 -10
- data/lib/concurrent/defer.rb +12 -8
- data/lib/concurrent/fixed_thread_pool.rb +6 -12
- data/lib/concurrent/future.rb +20 -8
- data/lib/concurrent/global_thread_pool.rb +0 -13
- data/lib/concurrent/goroutine.rb +1 -5
- data/lib/concurrent/obligation.rb +64 -10
- data/lib/concurrent/promise.rb +60 -38
- data/lib/concurrent/thread_pool.rb +5 -16
- data/lib/concurrent/utilities.rb +0 -8
- data/lib/concurrent/version.rb +1 -1
- data/md/defer.md +4 -4
- data/md/promise.md +0 -2
- data/md/thread_pool.md +0 -27
- data/spec/concurrent/agent_spec.rb +27 -8
- data/spec/concurrent/cached_thread_pool_spec.rb +1 -14
- data/spec/concurrent/defer_spec.rb +21 -17
- data/spec/concurrent/event_machine_defer_proxy_spec.rb +149 -159
- data/spec/concurrent/fixed_thread_pool_spec.rb +3 -2
- data/spec/concurrent/future_spec.rb +10 -3
- data/spec/concurrent/goroutine_spec.rb +0 -15
- data/spec/concurrent/obligation_shared.rb +2 -16
- data/spec/concurrent/promise_spec.rb +13 -15
- data/spec/concurrent/thread_pool_shared.rb +5 -5
- data/spec/concurrent/utilities_spec.rb +1 -30
- data/spec/spec_helper.rb +0 -25
- metadata +7 -28
- data/lib/concurrent/executor.rb +0 -95
- data/lib/concurrent/functions.rb +0 -120
- data/lib/concurrent/null_thread_pool.rb +0 -22
- data/lib/concurrent/reactor.rb +0 -161
- data/lib/concurrent/reactor/drb_async_demux.rb +0 -74
- data/lib/concurrent/reactor/tcp_sync_demux.rb +0 -98
- data/md/executor.md +0 -176
- data/spec/concurrent/executor_spec.rb +0 -200
- data/spec/concurrent/functions_spec.rb +0 -217
- data/spec/concurrent/global_thread_pool_spec.rb +0 -38
- data/spec/concurrent/null_thread_pool_spec.rb +0 -54
- data/spec/concurrent/reactor/drb_async_demux_spec.rb +0 -12
- data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +0 -12
- data/spec/concurrent/reactor_spec.rb +0 -351
@@ -41,7 +41,7 @@ module Concurrent
|
|
41
41
|
context '#kill' do
|
42
42
|
|
43
43
|
it 'kills all threads' do
|
44
|
-
Thread.should_receive(:kill).
|
44
|
+
Thread.should_receive(:kill).exactly(5).times
|
45
45
|
pool = FixedThreadPool.new(5)
|
46
46
|
pool.kill
|
47
47
|
sleep(0.1)
|
@@ -74,9 +74,10 @@ module Concurrent
|
|
74
74
|
it 'restarts threads that experience exception' do
|
75
75
|
pool = FixedThreadPool.new(5)
|
76
76
|
3.times{ pool << proc{ raise StandardError } }
|
77
|
-
sleep(
|
77
|
+
sleep(2)
|
78
78
|
pool.size.should eq 5
|
79
79
|
pool.status.should_not include(nil)
|
80
|
+
#pool.status.include?(nil).should be_false
|
80
81
|
end
|
81
82
|
end
|
82
83
|
end
|
@@ -9,7 +9,7 @@ module Concurrent
|
|
9
9
|
let!(:rejected_reason) { StandardError.new('mojo jojo') }
|
10
10
|
|
11
11
|
let(:pending_subject) do
|
12
|
-
Future.new{ sleep(
|
12
|
+
Future.new{ sleep(2) }
|
13
13
|
end
|
14
14
|
|
15
15
|
let(:fulfilled_subject) do
|
@@ -21,7 +21,7 @@ module Concurrent
|
|
21
21
|
end
|
22
22
|
|
23
23
|
before(:each) do
|
24
|
-
|
24
|
+
$GLOBAL_THREAD_POOL = CachedThreadPool.new
|
25
25
|
end
|
26
26
|
|
27
27
|
it_should_behave_like Obligation
|
@@ -40,7 +40,7 @@ module Concurrent
|
|
40
40
|
context '#initialize' do
|
41
41
|
|
42
42
|
it 'spawns a new thread when a block is given' do
|
43
|
-
|
43
|
+
$GLOBAL_THREAD_POOL.should_receive(:post).once.with(any_args())
|
44
44
|
Future.new{ nil }
|
45
45
|
end
|
46
46
|
|
@@ -102,6 +102,13 @@ module Concurrent
|
|
102
102
|
it 'aliases #deref for #value' do
|
103
103
|
fulfilled_subject.deref.should eq fulfilled_value
|
104
104
|
end
|
105
|
+
|
106
|
+
it 'aliases Kernel#future for Future.new' do
|
107
|
+
future().should be_a(Future)
|
108
|
+
future(){ nil }.should be_a(Future)
|
109
|
+
future(1, 2, 3).should be_a(Future)
|
110
|
+
future(1, 2, 3){ nil }.should be_a(Future)
|
111
|
+
end
|
105
112
|
end
|
106
113
|
end
|
107
114
|
end
|
@@ -48,20 +48,5 @@ module Concurrent
|
|
48
48
|
sleep(0.1)
|
49
49
|
@expected.should eq [1,2,3]
|
50
50
|
end
|
51
|
-
|
52
|
-
it 'accepts an alternate thread pool as the first argument' do
|
53
|
-
pool = Concurrent::FixedThreadPool.new(2)
|
54
|
-
pool.should_receive(:post).with(no_args())
|
55
|
-
go(pool){ sleep(0.1) }
|
56
|
-
sleep(0.2)
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'passes all other arguments to the block when a thread pool is given' do
|
60
|
-
@expected = nil
|
61
|
-
pool = Concurrent::FixedThreadPool.new(2)
|
62
|
-
go(pool, 1, 2, 3){|a, b, c| @expected = [c, b, a] }
|
63
|
-
sleep(0.1)
|
64
|
-
@expected.should eq [3, 2, 1]
|
65
|
-
end
|
66
51
|
end
|
67
52
|
end
|
@@ -37,7 +37,7 @@ module Concurrent
|
|
37
37
|
it 'returns nil when reaching the optional timeout value' do
|
38
38
|
f = pending_subject
|
39
39
|
sleep(0.1)
|
40
|
-
f.value(0).should be_nil
|
40
|
+
f.value(0.1).should be_nil
|
41
41
|
f.should be_pending
|
42
42
|
end
|
43
43
|
|
@@ -49,22 +49,8 @@ module Concurrent
|
|
49
49
|
f.should be_pending
|
50
50
|
end
|
51
51
|
|
52
|
-
it 'returns the value when fulfilled before timeout' do
|
53
|
-
f = pending_subject
|
54
|
-
sleep(0.1)
|
55
|
-
f.value(10).should be_true
|
56
|
-
f.should be_fulfilled
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'returns nil when timeout reached' do
|
60
|
-
f = pending_subject
|
61
|
-
sleep(0.1)
|
62
|
-
f.value(0.1).should be_nil
|
63
|
-
f.should be_pending
|
64
|
-
end
|
65
|
-
|
66
52
|
it 'is nil when :pending' do
|
67
|
-
expected = pending_subject.value
|
53
|
+
expected = pending_subject.value
|
68
54
|
expected.should be_nil
|
69
55
|
end
|
70
56
|
|
@@ -9,7 +9,7 @@ module Concurrent
|
|
9
9
|
let!(:rejected_reason) { StandardError.new('mojo jojo') }
|
10
10
|
|
11
11
|
let(:pending_subject) do
|
12
|
-
Promise.new{ sleep(
|
12
|
+
Promise.new{ sleep(1) }
|
13
13
|
end
|
14
14
|
|
15
15
|
let(:fulfilled_subject) do
|
@@ -22,7 +22,7 @@ module Concurrent
|
|
22
22
|
end
|
23
23
|
|
24
24
|
before(:each) do
|
25
|
-
|
25
|
+
$GLOBAL_THREAD_POOL = CachedThreadPool.new
|
26
26
|
end
|
27
27
|
|
28
28
|
it_should_behave_like Obligation
|
@@ -163,9 +163,10 @@ module Concurrent
|
|
163
163
|
end
|
164
164
|
|
165
165
|
it 'recursively rejects all children' do
|
166
|
-
p = Promise.new{ raise StandardError.new('Boom!') }
|
166
|
+
p = Promise.new{ Thread.pass; raise StandardError.new('Boom!') }
|
167
167
|
promises = 10.times.collect{ p.then{ true } }
|
168
168
|
sleep(0.1)
|
169
|
+
|
169
170
|
10.times.each{|i| promises[i].should be_rejected }
|
170
171
|
end
|
171
172
|
|
@@ -182,7 +183,7 @@ module Concurrent
|
|
182
183
|
rescue(StandardError){|ex| @expected = 1 }.
|
183
184
|
rescue(StandardError){|ex| @expected = 2 }.
|
184
185
|
rescue(StandardError){|ex| @expected = 3 }
|
185
|
-
|
186
|
+
sleep(0.1)
|
186
187
|
@expected.should eq 1
|
187
188
|
end
|
188
189
|
|
@@ -197,8 +198,6 @@ module Concurrent
|
|
197
198
|
end
|
198
199
|
|
199
200
|
it 'searches associated rescue handlers in order' do
|
200
|
-
Promise.thread_pool = CachedThreadPool.new
|
201
|
-
|
202
201
|
@expected = nil
|
203
202
|
Promise.new{ raise ArgumentError }.
|
204
203
|
rescue(ArgumentError){|ex| @expected = 1 }.
|
@@ -264,7 +263,7 @@ module Concurrent
|
|
264
263
|
|
265
264
|
it 'calls matching rescue handlers on all children' do
|
266
265
|
@expected = []
|
267
|
-
Promise.new{ raise StandardError }.
|
266
|
+
Promise.new{ Thread.pass; raise StandardError }.
|
268
267
|
then{ sleep(0.1) }.rescue{ @expected << 'Boom!' }.
|
269
268
|
then{ sleep(0.1) }.rescue{ @expected << 'Boom!' }.
|
270
269
|
then{ sleep(0.1) }.rescue{ @expected << 'Boom!' }.
|
@@ -274,14 +273,6 @@ module Concurrent
|
|
274
273
|
|
275
274
|
@expected.length.should eq 5
|
276
275
|
end
|
277
|
-
|
278
|
-
it 'matches a rescue handler added after rejection' do
|
279
|
-
@expected = false
|
280
|
-
p = Promise.new{ raise StandardError }
|
281
|
-
sleep(0.1)
|
282
|
-
p.rescue(StandardError){ @expected = true }
|
283
|
-
@expected.should be_true
|
284
|
-
end
|
285
276
|
end
|
286
277
|
|
287
278
|
context 'aliases' do
|
@@ -307,6 +298,13 @@ module Concurrent
|
|
307
298
|
sleep(0.1)
|
308
299
|
@expected.should be_true
|
309
300
|
end
|
301
|
+
|
302
|
+
it 'aliases Kernel#promise for Promise.new' do
|
303
|
+
promise().should be_a(Promise)
|
304
|
+
promise(){ nil }.should be_a(Promise)
|
305
|
+
promise(1, 2, 3).should be_a(Promise)
|
306
|
+
promise(1, 2, 3){ nil }.should be_a(Promise)
|
307
|
+
end
|
310
308
|
end
|
311
309
|
end
|
312
310
|
end
|
@@ -29,9 +29,8 @@ module Concurrent
|
|
29
29
|
|
30
30
|
context '#shutdown?' do
|
31
31
|
|
32
|
-
it 'returns true if #shutdown
|
32
|
+
it 'returns true if #shutdown has been called' do
|
33
33
|
subject.shutdown
|
34
|
-
sleep(0.1)
|
35
34
|
subject.should be_shutdown
|
36
35
|
end
|
37
36
|
|
@@ -82,9 +81,10 @@ module Concurrent
|
|
82
81
|
end
|
83
82
|
|
84
83
|
it 'allows threads to exit normally' do
|
85
|
-
|
84
|
+
pool = FixedThreadPool.new(5)
|
85
|
+
pool.shutdown
|
86
86
|
sleep(1)
|
87
|
-
|
87
|
+
pool.status.should be_empty
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
@@ -139,7 +139,7 @@ module Concurrent
|
|
139
139
|
it 'returns false when shutdown fails to complete before timeout' do
|
140
140
|
subject.post{ sleep(1) }
|
141
141
|
subject.shutdown
|
142
|
-
subject.wait_for_termination(0.5).should
|
142
|
+
subject.wait_for_termination(0.5).should be_true
|
143
143
|
end
|
144
144
|
end
|
145
145
|
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'thread'
|
3
2
|
|
4
3
|
describe 'utilities' do
|
5
4
|
|
@@ -27,7 +26,7 @@ describe 'utilities' do
|
|
27
26
|
it 'raises an exception if no block is given' do
|
28
27
|
lambda {
|
29
28
|
atomic()
|
30
|
-
}.should raise_error
|
29
|
+
}.should raise_error
|
31
30
|
end
|
32
31
|
|
33
32
|
it 'creates a new Fiber' do
|
@@ -43,32 +42,4 @@ describe 'utilities' do
|
|
43
42
|
atomic{ 'foo' }
|
44
43
|
end
|
45
44
|
end
|
46
|
-
|
47
|
-
context Mutex do
|
48
|
-
|
49
|
-
context '#sync_with_timeout' do
|
50
|
-
|
51
|
-
it 'returns the result of the block if a lock is obtained before timeout' do
|
52
|
-
mutex = Mutex.new
|
53
|
-
result = mutex.sync_with_timeout(30){ 42 }
|
54
|
-
result.should eq 42
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'raises Timeout::Error if the timeout is exceeded' do
|
58
|
-
mutex = Mutex.new
|
59
|
-
thread = Thread.new{ mutex.synchronize{ sleep(30) } }
|
60
|
-
sleep(0.1)
|
61
|
-
lambda {
|
62
|
-
mutex.sync_and_wait(1)
|
63
|
-
}.should raise_error(NoMethodError)
|
64
|
-
Thread.kill(thread)
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'raises an exception if no block given' do
|
68
|
-
lambda {
|
69
|
-
Mutex.new.sync_with_timeout()
|
70
|
-
}.should raise_error(ArgumentError)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
45
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,36 +1,11 @@
|
|
1
|
-
require 'simplecov'
|
2
|
-
SimpleCov.start do
|
3
|
-
project_name 'concurrent-ruby'
|
4
|
-
add_filter '/md/'
|
5
|
-
add_filter '/pkg/'
|
6
|
-
add_filter '/spec/'
|
7
|
-
add_filter '/tasks/'
|
8
|
-
end
|
9
|
-
|
10
1
|
require 'eventmachine'
|
11
2
|
|
12
3
|
require 'concurrent'
|
13
|
-
require 'concurrent/functions'
|
14
|
-
|
15
|
-
require 'rbconfig'
|
16
|
-
|
17
|
-
def mri?
|
18
|
-
RbConfig::CONFIG['ruby_install_name'] =~ /^ruby$/i
|
19
|
-
end
|
20
|
-
|
21
|
-
def jruby?
|
22
|
-
RbConfig::CONFIG['ruby_install_name'] =~ /^jruby$/i
|
23
|
-
end
|
24
|
-
|
25
|
-
def rbx?
|
26
|
-
RbConfig::CONFIG['ruby_install_name'] =~ /^rbx$/i
|
27
|
-
end
|
28
4
|
|
29
5
|
# import all the support files
|
30
6
|
Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require File.expand_path(f) }
|
31
7
|
|
32
8
|
RSpec.configure do |config|
|
33
|
-
config.order = 'random'
|
34
9
|
|
35
10
|
config.before(:suite) do
|
36
11
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: concurrent-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.1
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jerry D'Antonio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: functional-ruby
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.7.
|
19
|
+
version: 0.7.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.7.
|
26
|
+
version: 0.7.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -54,18 +54,12 @@ files:
|
|
54
54
|
- lib/concurrent/defer.rb
|
55
55
|
- lib/concurrent/event.rb
|
56
56
|
- lib/concurrent/event_machine_defer_proxy.rb
|
57
|
-
- lib/concurrent/executor.rb
|
58
57
|
- lib/concurrent/fixed_thread_pool.rb
|
59
|
-
- lib/concurrent/functions.rb
|
60
58
|
- lib/concurrent/future.rb
|
61
59
|
- lib/concurrent/global_thread_pool.rb
|
62
60
|
- lib/concurrent/goroutine.rb
|
63
|
-
- lib/concurrent/null_thread_pool.rb
|
64
61
|
- lib/concurrent/obligation.rb
|
65
62
|
- lib/concurrent/promise.rb
|
66
|
-
- lib/concurrent/reactor/drb_async_demux.rb
|
67
|
-
- lib/concurrent/reactor/tcp_sync_demux.rb
|
68
|
-
- lib/concurrent/reactor.rb
|
69
63
|
- lib/concurrent/thread_pool.rb
|
70
64
|
- lib/concurrent/utilities.rb
|
71
65
|
- lib/concurrent/version.rb
|
@@ -74,7 +68,6 @@ files:
|
|
74
68
|
- md/agent.md
|
75
69
|
- md/defer.md
|
76
70
|
- md/event.md
|
77
|
-
- md/executor.md
|
78
71
|
- md/future.md
|
79
72
|
- md/goroutine.md
|
80
73
|
- md/obligation.md
|
@@ -85,18 +78,11 @@ files:
|
|
85
78
|
- spec/concurrent/defer_spec.rb
|
86
79
|
- spec/concurrent/event_machine_defer_proxy_spec.rb
|
87
80
|
- spec/concurrent/event_spec.rb
|
88
|
-
- spec/concurrent/executor_spec.rb
|
89
81
|
- spec/concurrent/fixed_thread_pool_spec.rb
|
90
|
-
- spec/concurrent/functions_spec.rb
|
91
82
|
- spec/concurrent/future_spec.rb
|
92
|
-
- spec/concurrent/global_thread_pool_spec.rb
|
93
83
|
- spec/concurrent/goroutine_spec.rb
|
94
|
-
- spec/concurrent/null_thread_pool_spec.rb
|
95
84
|
- spec/concurrent/obligation_shared.rb
|
96
85
|
- spec/concurrent/promise_spec.rb
|
97
|
-
- spec/concurrent/reactor/drb_async_demux_spec.rb
|
98
|
-
- spec/concurrent/reactor/tcp_sync_demux_spec.rb
|
99
|
-
- spec/concurrent/reactor_spec.rb
|
100
86
|
- spec/concurrent/thread_pool_shared.rb
|
101
87
|
- spec/concurrent/utilities_spec.rb
|
102
88
|
- spec/spec_helper.rb
|
@@ -115,12 +101,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
115
101
|
version: 1.9.2
|
116
102
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
103
|
requirements:
|
118
|
-
- - '
|
104
|
+
- - '>='
|
119
105
|
- !ruby/object:Gem::Version
|
120
|
-
version:
|
106
|
+
version: '0'
|
121
107
|
requirements: []
|
122
108
|
rubyforge_project:
|
123
|
-
rubygems_version: 2.0.
|
109
|
+
rubygems_version: 2.0.3
|
124
110
|
signing_key:
|
125
111
|
specification_version: 4
|
126
112
|
summary: Erlang, Clojure, and Go inspired concurrent programming tools for Ruby.
|
@@ -130,18 +116,11 @@ test_files:
|
|
130
116
|
- spec/concurrent/defer_spec.rb
|
131
117
|
- spec/concurrent/event_machine_defer_proxy_spec.rb
|
132
118
|
- spec/concurrent/event_spec.rb
|
133
|
-
- spec/concurrent/executor_spec.rb
|
134
119
|
- spec/concurrent/fixed_thread_pool_spec.rb
|
135
|
-
- spec/concurrent/functions_spec.rb
|
136
120
|
- spec/concurrent/future_spec.rb
|
137
|
-
- spec/concurrent/global_thread_pool_spec.rb
|
138
121
|
- spec/concurrent/goroutine_spec.rb
|
139
|
-
- spec/concurrent/null_thread_pool_spec.rb
|
140
122
|
- spec/concurrent/obligation_shared.rb
|
141
123
|
- spec/concurrent/promise_spec.rb
|
142
|
-
- spec/concurrent/reactor/drb_async_demux_spec.rb
|
143
|
-
- spec/concurrent/reactor/tcp_sync_demux_spec.rb
|
144
|
-
- spec/concurrent/reactor_spec.rb
|
145
124
|
- spec/concurrent/thread_pool_shared.rb
|
146
125
|
- spec/concurrent/utilities_spec.rb
|
147
126
|
- spec/spec_helper.rb
|
data/lib/concurrent/executor.rb
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
module Executor
|
6
|
-
extend self
|
7
|
-
|
8
|
-
class ExecutionContext
|
9
|
-
attr_reader :name
|
10
|
-
attr_reader :execution_interval
|
11
|
-
attr_reader :timeout_interval
|
12
|
-
|
13
|
-
protected
|
14
|
-
|
15
|
-
def initialize(name, execution_interval, timeout_interval, thread)
|
16
|
-
@name = name
|
17
|
-
@execution_interval = execution_interval
|
18
|
-
@timeout_interval = timeout_interval
|
19
|
-
@thread = thread
|
20
|
-
@thread[:stop] = false
|
21
|
-
end
|
22
|
-
|
23
|
-
public
|
24
|
-
|
25
|
-
def status
|
26
|
-
return @thread.status unless @thread.nil?
|
27
|
-
end
|
28
|
-
|
29
|
-
def join(limit = nil)
|
30
|
-
if @thread.nil?
|
31
|
-
return nil
|
32
|
-
elsif limit.nil?
|
33
|
-
return @thread.join
|
34
|
-
else
|
35
|
-
return @thread.join(limit)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def stop
|
40
|
-
@thread[:stop] = true
|
41
|
-
end
|
42
|
-
|
43
|
-
def kill
|
44
|
-
unless @thread.nil?
|
45
|
-
stop
|
46
|
-
Thread.kill(@thread)
|
47
|
-
@thread = nil
|
48
|
-
end
|
49
|
-
end
|
50
|
-
alias_method :terminate, :kill
|
51
|
-
end
|
52
|
-
|
53
|
-
EXECUTION_INTERVAL = 60
|
54
|
-
TIMEOUT_INTERVAL = 30
|
55
|
-
|
56
|
-
STDOUT_LOGGER = proc do |name, level, msg|
|
57
|
-
print "%5s (%s) %s: %s\n" % [level.upcase, Time.now.strftime("%F %T"), name, msg]
|
58
|
-
end
|
59
|
-
|
60
|
-
def run(name, opts = {})
|
61
|
-
raise ArgumentError.new('no block given') unless block_given?
|
62
|
-
|
63
|
-
execution_interval = opts[:execution] || opts[:execution_interval] || EXECUTION_INTERVAL
|
64
|
-
timeout_interval = opts[:timeout] || opts[:timeout_interval] || TIMEOUT_INTERVAL
|
65
|
-
run_now = opts[:now] || opts[:run_now] || false
|
66
|
-
logger = opts[:logger] || STDOUT_LOGGER
|
67
|
-
block_args = opts[:args] || opts [:arguments] || []
|
68
|
-
|
69
|
-
executor = Thread.new(*block_args) do |*args|
|
70
|
-
sleep(execution_interval) unless run_now == true
|
71
|
-
loop do
|
72
|
-
break if Thread.current[:stop]
|
73
|
-
begin
|
74
|
-
worker = Thread.new{ yield(*args) }
|
75
|
-
worker.abort_on_exception = false
|
76
|
-
if worker.join(timeout_interval).nil?
|
77
|
-
logger.call(name, :warn, "execution timed out after #{timeout_interval} seconds")
|
78
|
-
else
|
79
|
-
logger.call(name, :info, 'execution completed successfully')
|
80
|
-
end
|
81
|
-
rescue Exception => ex
|
82
|
-
logger.call(name, :error, "execution failed with error '#{ex}'")
|
83
|
-
ensure
|
84
|
-
Thread.kill(worker)
|
85
|
-
worker = nil
|
86
|
-
end
|
87
|
-
break if Thread.current[:stop]
|
88
|
-
sleep(execution_interval)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
return ExecutionContext.new(name, execution_interval, timeout_interval, executor)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|