parallizer 0.2.4 → 0.3.0
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.
- data/Gemfile.lock +2 -2
- data/lib/parallizer/proxy.rb +8 -21
- data/lib/parallizer/version.rb +1 -1
- data/lib/parallizer.rb +23 -22
- data/parallizer.gemspec +1 -0
- data/spec/parallizer/proxy_spec.rb +24 -42
- metadata +24 -3
- data/lib/parallizer/thread_pool.rb +0 -63
data/Gemfile.lock
CHANGED
data/lib/parallizer/proxy.rb
CHANGED
@@ -9,31 +9,18 @@ class Parallizer
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def method_missing(name, *args, &block)
|
12
|
-
value = nil
|
13
|
-
|
14
12
|
if call_info = @call_infos[[name, *args]]
|
15
|
-
call_info[:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if call_info[:exception]
|
23
|
-
# add the current call stack to the exception backtrace
|
24
|
-
exception = call_info[:exception].clone
|
25
|
-
exception.set_backtrace((call_info[:exception].backtrace || []) + caller)
|
26
|
-
raise exception
|
27
|
-
end
|
28
|
-
|
29
|
-
value = call_info[:result]
|
13
|
+
if call_info[:exception]
|
14
|
+
# add the current call stack to the exception backtrace
|
15
|
+
exception = call_info[:exception].clone
|
16
|
+
exception.set_backtrace((call_info[:exception].backtrace || []) + caller)
|
17
|
+
raise exception
|
18
|
+
else
|
19
|
+
call_info[:result]
|
30
20
|
end
|
31
21
|
else
|
32
|
-
|
33
|
-
value = @client.send(*[name, *args], &block)
|
22
|
+
@client.send(*[name, *args], &block)
|
34
23
|
end
|
35
|
-
|
36
|
-
value
|
37
24
|
end
|
38
25
|
|
39
26
|
def respond_to?(name, include_private = false, &block)
|
data/lib/parallizer/version.rb
CHANGED
data/lib/parallizer.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
+
require 'work_queue'
|
1
2
|
require 'parallizer/version'
|
2
3
|
require 'parallizer/proxy'
|
3
4
|
require 'parallizer/method_call_notifier'
|
4
|
-
require 'parallizer/thread_pool'
|
5
5
|
|
6
6
|
class Parallizer
|
7
|
-
WORK_QUEUE_SIZE =
|
7
|
+
WORK_QUEUE_SIZE = 10
|
8
8
|
|
9
9
|
attr_reader :calls, :call_infos, :client, :proxy, :options
|
10
10
|
|
@@ -34,42 +34,43 @@ class Parallizer
|
|
34
34
|
:complete? => false,
|
35
35
|
:result => nil,
|
36
36
|
:exception => nil,
|
37
|
-
:condition_variable => ConditionVariable.new,
|
38
|
-
:mutex => Mutex.new,
|
39
37
|
:retries => options[:retries]
|
40
38
|
}
|
41
39
|
call_infos[method_name_and_args] = call_info
|
42
|
-
|
43
|
-
enqueue_call_info(call_info, method_name_and_args)
|
44
40
|
end
|
45
41
|
|
46
42
|
def create_proxy
|
47
43
|
raise ArgumentError, "Cannot create another proxy" if @proxy
|
48
44
|
|
45
|
+
execute
|
46
|
+
|
49
47
|
Parallizer::Proxy.new(client, call_infos)
|
50
48
|
end
|
51
49
|
|
52
50
|
private
|
53
51
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
52
|
+
def self.work_queue
|
53
|
+
# TODO: share the work queue among calling threads
|
54
|
+
Thread.current[:parallizer_work_queue] ||= WorkQueue.new(WORK_QUEUE_SIZE)
|
55
|
+
end
|
56
|
+
|
57
|
+
def execute
|
58
|
+
call_infos.each do |method_name_and_args, call_info|
|
59
|
+
Parallizer.work_queue.enqueue_b do
|
60
|
+
(call_info[:retries] + 1).times do
|
61
|
+
begin
|
62
|
+
call_info[:exception] = nil # reset exception before each send attempt
|
63
|
+
call_info[:result] = client.send(*method_name_and_args)
|
64
|
+
break # success
|
65
|
+
rescue Exception => e
|
66
|
+
call_info[:exception] = e
|
66
67
|
end
|
67
|
-
ensure
|
68
|
-
call_info[:complete?] = true
|
69
|
-
call_info[:condition_variable].broadcast
|
70
|
-
Parallizer::ThreadPool.put(Thread.current)
|
71
68
|
end
|
72
69
|
end
|
73
70
|
end
|
71
|
+
|
72
|
+
Parallizer.work_queue.join
|
73
|
+
|
74
|
+
Parallizer::Proxy.new(client, call_infos)
|
74
75
|
end
|
75
76
|
end
|
data/parallizer.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
+
s.add_dependency 'work_queue'
|
21
22
|
s.add_development_dependency 'rake'
|
22
23
|
s.add_development_dependency 'rspec', '~> 2.9.0'
|
23
24
|
s.add_development_dependency 'always_execute', '~> 0.1.1'
|
@@ -29,57 +29,39 @@ describe Parallizer::Proxy do
|
|
29
29
|
@call_key += [:a_method, "some value"]
|
30
30
|
end
|
31
31
|
|
32
|
-
context "with
|
32
|
+
context "with an exception" do
|
33
33
|
before do
|
34
|
-
@call_info[:
|
35
|
-
@call_info[:
|
36
|
-
@call_info[:result] = 'this is a value'
|
34
|
+
@call_info[:exception] = StandardError.new('An Exception')
|
35
|
+
@call_info[:exception].set_backtrace(["/tmp/foo.rb:123:in `in a_worker_thread_method'"])
|
37
36
|
end
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
execute do
|
39
|
+
def a_calling_thread_method
|
40
|
+
call_infos = { @call_key => @call_info }
|
41
|
+
proxy = Parallizer::Proxy.new(@client, call_infos)
|
42
|
+
proxy.send(*@call_key) rescue $!
|
43
|
+
end
|
44
|
+
a_calling_thread_method
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should raise exception" do
|
48
|
+
@execute_result.class.should == @call_info[:exception].class
|
49
|
+
@execute_result.message.should == @call_info[:exception].message
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should append backtrace of current call" do
|
53
|
+
@execute_result.backtrace.join.should match /a_worker_thread_method/
|
54
|
+
@execute_result.backtrace.join.should match /a_calling_thread_method/
|
41
55
|
end
|
42
56
|
end
|
43
57
|
|
44
|
-
context "with
|
58
|
+
context "with a result" do
|
45
59
|
before do
|
46
|
-
@call_info[:
|
47
|
-
end
|
48
|
-
|
49
|
-
context "with an exception" do
|
50
|
-
before do
|
51
|
-
@call_info[:exception] = StandardError.new('An Exception')
|
52
|
-
@call_info[:exception].set_backtrace(["/tmp/foo.rb:123:in `in a_worker_thread_method'"])
|
53
|
-
end
|
54
|
-
|
55
|
-
execute do
|
56
|
-
def a_calling_thread_method
|
57
|
-
call_infos = { @call_key => @call_info }
|
58
|
-
proxy = Parallizer::Proxy.new(@client, call_infos)
|
59
|
-
proxy.send(*@call_key) rescue $!
|
60
|
-
end
|
61
|
-
a_calling_thread_method
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should raise exception" do
|
65
|
-
@execute_result.class.should == @call_info[:exception].class
|
66
|
-
@execute_result.message.should == @call_info[:exception].message
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should append backtrace of current call" do
|
70
|
-
@execute_result.backtrace.join.should match /a_worker_thread_method/
|
71
|
-
@execute_result.backtrace.join.should match /a_calling_thread_method/
|
72
|
-
end
|
60
|
+
@call_info[:result] = "a result"
|
73
61
|
end
|
74
62
|
|
75
|
-
|
76
|
-
|
77
|
-
@call_info[:result] = "a result"
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should return result" do
|
81
|
-
@execute_result.should == @call_info[:result]
|
82
|
-
end
|
63
|
+
it "should return result" do
|
64
|
+
@execute_result.should == @call_info[:result]
|
83
65
|
end
|
84
66
|
end
|
85
67
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: work_queue
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: rake
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,7 +91,6 @@ files:
|
|
75
91
|
- lib/parallizer.rb
|
76
92
|
- lib/parallizer/method_call_notifier.rb
|
77
93
|
- lib/parallizer/proxy.rb
|
78
|
-
- lib/parallizer/thread_pool.rb
|
79
94
|
- lib/parallizer/version.rb
|
80
95
|
- parallizer.gemspec
|
81
96
|
- spec/parallizer/method_call_notifier_spec.rb
|
@@ -94,12 +109,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
109
|
- - ! '>='
|
95
110
|
- !ruby/object:Gem::Version
|
96
111
|
version: '0'
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
hash: 4537061514701133663
|
97
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
116
|
none: false
|
99
117
|
requirements:
|
100
118
|
- - ! '>='
|
101
119
|
- !ruby/object:Gem::Version
|
102
120
|
version: '0'
|
121
|
+
segments:
|
122
|
+
- 0
|
123
|
+
hash: 4537061514701133663
|
103
124
|
requirements: []
|
104
125
|
rubyforge_project: parallizer
|
105
126
|
rubygems_version: 1.8.24
|
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
|
-
class Parallizer
|
4
|
-
# Initially taken from Celluloid. -mgp
|
5
|
-
module ThreadPool
|
6
|
-
THEAD_POOL_SIZE = 16
|
7
|
-
|
8
|
-
@pool = []
|
9
|
-
@mutex = Mutex.new
|
10
|
-
|
11
|
-
@max_idle = THEAD_POOL_SIZE
|
12
|
-
|
13
|
-
class << self
|
14
|
-
attr_accessor :max_idle
|
15
|
-
|
16
|
-
# Get a thread from the pool, running the given block
|
17
|
-
def get(&block)
|
18
|
-
@mutex.synchronize do
|
19
|
-
begin
|
20
|
-
if @pool.empty?
|
21
|
-
thread = create
|
22
|
-
else
|
23
|
-
thread = @pool.shift
|
24
|
-
end
|
25
|
-
end until thread.status # handle crashed threads
|
26
|
-
|
27
|
-
thread[:queue] << block
|
28
|
-
thread
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# Return a thread to the pool
|
33
|
-
def put(thread)
|
34
|
-
@mutex.synchronize do
|
35
|
-
if @pool.size >= @max_idle
|
36
|
-
thread[:queue] << nil
|
37
|
-
else
|
38
|
-
@pool << thread
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Create a new thread with an associated queue of procs to run
|
44
|
-
def create
|
45
|
-
queue = Queue.new
|
46
|
-
thread = Thread.new do
|
47
|
-
while proc = queue.pop
|
48
|
-
begin
|
49
|
-
proc.call
|
50
|
-
rescue => ex
|
51
|
-
# Let this thread die on exceptions other than standard errors
|
52
|
-
end
|
53
|
-
put thread
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
thread[:queue] = queue
|
58
|
-
thread
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|