gearman-ruby 2.0.0 → 3.0.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.
- data/Rakefile +5 -6
- data/VERSION.yml +2 -2
- data/examples/calculus_client.rb +8 -10
- data/examples/calculus_worker.rb +4 -1
- data/examples/client.php +23 -0
- data/examples/client.rb +6 -10
- data/examples/client_background.rb +7 -7
- data/examples/client_data.rb +4 -4
- data/examples/client_epoch.rb +23 -0
- data/examples/client_exception.rb +4 -2
- data/examples/client_prefix.rb +4 -2
- data/examples/client_reverse.rb +27 -0
- data/examples/scale_image.rb +4 -3
- data/examples/scale_image_worker.rb +1 -1
- data/examples/worker.rb +2 -4
- data/examples/worker_data.rb +2 -2
- data/examples/worker_exception.rb +1 -1
- data/examples/worker_prefix.rb +1 -1
- data/examples/worker_reverse_string.rb +27 -0
- data/examples/worker_reverse_to_file.rb +18 -0
- data/examples/{evented_worker.rb → worker_signals.rb} +18 -8
- data/lib/gearman.rb +68 -21
- data/lib/gearman/client.rb +137 -65
- data/lib/gearman/server.rb +4 -4
- data/lib/gearman/task.rb +140 -20
- data/lib/gearman/taskset.rb +280 -5
- data/lib/gearman/testlib.rb +95 -0
- data/lib/gearman/util.rb +184 -28
- data/lib/gearman/worker.rb +356 -20
- data/test/client_test.rb +145 -0
- data/test/mock_client_test.rb +629 -0
- data/test/mock_worker_test.rb +321 -0
- data/test/util_test.rb +8 -3
- data/test/worker_test.rb +50 -34
- metadata +41 -41
- data/examples/client_echo.rb +0 -16
- data/examples/evented_client.rb +0 -23
- data/examples/worker_echo.rb +0 -20
- data/examples/worker_echo_pprof.rb +0 -5
- data/gearman-ruby.gemspec +0 -111
- data/lib/gearman/evented/client.rb +0 -99
- data/lib/gearman/evented/reactor.rb +0 -86
- data/lib/gearman/evented/worker.rb +0 -118
- data/lib/gearman/job.rb +0 -38
- data/lib/gearman/protocol.rb +0 -110
- data/test/basic_integration_test.rb +0 -121
- data/test/crash_test.rb +0 -69
- data/test/job_test.rb +0 -30
- data/test/protocol_test.rb +0 -132
- data/test/test_helper.rb +0 -31
data/test/client_test.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift('../lib')
|
4
|
+
require 'gearman'
|
5
|
+
require 'gearman/testlib'
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
class TestClient < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@server = FakeJobServer.new(self)
|
12
|
+
@server_b = FakeJobServer.new(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
@server.stop
|
17
|
+
end
|
18
|
+
##
|
19
|
+
# Test the get_socket, return_socket, close_socket, and
|
20
|
+
# get_hostport_for_socket methods of Client.
|
21
|
+
def test_sockets
|
22
|
+
client = Gearman::Client.new
|
23
|
+
hostport = "localhost:#{@server.port}"
|
24
|
+
client.job_servers = [hostport]
|
25
|
+
|
26
|
+
# If we get a socket, return it, and request a socket for the same
|
27
|
+
# host, we should get the original one again.
|
28
|
+
origsock = client.get_socket(client.get_job_server)
|
29
|
+
client.return_socket(origsock)
|
30
|
+
assert_equal(origsock, client.get_socket(client.get_job_server))
|
31
|
+
assert_equal(hostport, client.get_hostport_for_socket(origsock))
|
32
|
+
|
33
|
+
# We should get another socket if we call get_socket again.
|
34
|
+
newsock = client.get_socket(client.get_job_server)
|
35
|
+
assert_not_equal(origsock, newsock)
|
36
|
+
assert_equal(hostport, client.get_hostport_for_socket(newsock))
|
37
|
+
|
38
|
+
# They should be closed when we call close_socket, and we should get
|
39
|
+
# a new socket the next time.
|
40
|
+
client.close_socket(origsock)
|
41
|
+
client.close_socket(newsock)
|
42
|
+
assert(origsock.closed?)
|
43
|
+
assert(newsock.closed?)
|
44
|
+
assert_not_equal(origsock, client.get_socket(client.get_job_server))
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# We check that the client does not fail if at least one
|
49
|
+
# server is up.
|
50
|
+
def test_first_connection_server_down_retry
|
51
|
+
client = Gearman::Client.new
|
52
|
+
hostport_good = "localhost:#{@server.port}"
|
53
|
+
hostport_bad = "nonexistent:8080"
|
54
|
+
# TODO: why does this fail?
|
55
|
+
# hostport_bad = "localhost:#{@server.port+x}" for x in (1..5)
|
56
|
+
|
57
|
+
client.job_servers = [hostport_bad,hostport_good]
|
58
|
+
|
59
|
+
first_requested_server = client.get_job_server
|
60
|
+
assert(first_requested_server == hostport_bad)
|
61
|
+
|
62
|
+
begin
|
63
|
+
result = client.get_socket(first_requested_server)
|
64
|
+
assert(false)
|
65
|
+
rescue RuntimeError
|
66
|
+
assert(true)
|
67
|
+
end
|
68
|
+
|
69
|
+
assert(client.bad_servers.size == 1)
|
70
|
+
|
71
|
+
second_requested_server = client.get_job_server
|
72
|
+
assert(second_requested_server == hostport_good)
|
73
|
+
begin
|
74
|
+
client.get_socket(second_requested_server)
|
75
|
+
assert(true)
|
76
|
+
rescue RuntimeError
|
77
|
+
assert(false)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# We check that the client raises a fatal exception if server fails
|
83
|
+
# while connected.
|
84
|
+
def test_client_down_if_server_down
|
85
|
+
client = Gearman::Client.new
|
86
|
+
hostport_good = "localhost:#{@server.port}"
|
87
|
+
hostport_good_b = "localhost:#{@server_b.port}"
|
88
|
+
|
89
|
+
client.job_servers = [hostport_good,hostport_good_b]
|
90
|
+
|
91
|
+
# We simulate a gearmand server failure after receiving some data
|
92
|
+
# from the client
|
93
|
+
Thread.new do
|
94
|
+
server_socket = @server.expect_connection
|
95
|
+
@server.expect_anything_and_close_socket(server_socket)
|
96
|
+
end
|
97
|
+
|
98
|
+
taskset = Gearman::TaskSet.new(client)
|
99
|
+
|
100
|
+
task = Gearman::Task.new('sleep', 20)
|
101
|
+
task.on_complete {|d| puts d }
|
102
|
+
|
103
|
+
should_be_true = true
|
104
|
+
begin
|
105
|
+
taskset.add_task(task)
|
106
|
+
should_be_true = false
|
107
|
+
rescue Exception => ex
|
108
|
+
end
|
109
|
+
assert(should_be_true)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_option_request_exceptions
|
113
|
+
this_server = FakeJobServer.new(self)
|
114
|
+
Thread.new do
|
115
|
+
server_socket = this_server.expect_connection
|
116
|
+
this_server.expect_request(server_socket, "option_req", "exceptions")
|
117
|
+
this_server.send_response(server_socket, :job_created, 'a')
|
118
|
+
end
|
119
|
+
client = Gearman::Client.new
|
120
|
+
hostport = "localhost:#{this_server.port}"
|
121
|
+
client.job_servers = [hostport]
|
122
|
+
client.option_request("exceptions")
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_option_request_bad
|
126
|
+
this_server = FakeJobServer.new(self)
|
127
|
+
Thread.new do
|
128
|
+
server_socket = this_server.expect_connection
|
129
|
+
this_server.expect_request(server_socket, "option_req", "cccceptionsccc")
|
130
|
+
this_server.send_response(server_socket, :exception, 'a')
|
131
|
+
end
|
132
|
+
|
133
|
+
client = Gearman::Client.new
|
134
|
+
hostport = "localhost:#{this_server.port}"
|
135
|
+
client.job_servers = [hostport]
|
136
|
+
begin
|
137
|
+
client.option_request("cccceptionsccc")
|
138
|
+
assert(false)
|
139
|
+
rescue Gearman::ProtocolError
|
140
|
+
assert(true)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
end
|
@@ -0,0 +1,629 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift('../lib')
|
4
|
+
require 'gearman'
|
5
|
+
require 'gearman/testlib'
|
6
|
+
require 'test/unit'
|
7
|
+
require 'thread'
|
8
|
+
|
9
|
+
Thread.abort_on_exception = true
|
10
|
+
|
11
|
+
class TestClient < Test::Unit::TestCase
|
12
|
+
##
|
13
|
+
# Do a simple test of the functionality of the client code.
|
14
|
+
def test_client
|
15
|
+
server = FakeJobServer.new(self)
|
16
|
+
client, task1, task2, taskset, sock, res1, res2 = nil
|
17
|
+
|
18
|
+
s = TestScript.new
|
19
|
+
c = TestScript.new
|
20
|
+
|
21
|
+
server_thread = Thread.new { s.loop_forever }.run
|
22
|
+
client_thread = Thread.new { c.loop_forever }.run
|
23
|
+
|
24
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
25
|
+
|
26
|
+
c.exec { task1 = Gearman::Task.new('add', '5 2') }
|
27
|
+
c.exec { task1.on_complete {|d| res1 = d.to_i } }
|
28
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
29
|
+
c.exec { taskset.add_task(task1) }
|
30
|
+
s.exec { sock = server.expect_connection }
|
31
|
+
s.wait
|
32
|
+
|
33
|
+
s.exec { server.expect_request(sock, :submit_job, "add\000\0005 2") }
|
34
|
+
s.exec { server.send_response(sock, :job_created, 'a') }
|
35
|
+
|
36
|
+
# Create a second task. It should use the same socket as the first.
|
37
|
+
c.exec { task2 = Gearman::Task.new('add', '10 5') }
|
38
|
+
c.exec { task2.on_complete {|d| res2 = d.to_i } }
|
39
|
+
c.exec { taskset.add_task(task2) }
|
40
|
+
|
41
|
+
# Return the response to the first job before the handle for the
|
42
|
+
# second.
|
43
|
+
s.exec { server.send_response(sock, :work_complete, "a\0007") }
|
44
|
+
s.exec { server.expect_request(sock, :submit_job, "add\000\00010 5") }
|
45
|
+
s.exec { server.send_response(sock, :job_created, 'b') }
|
46
|
+
|
47
|
+
# After the client waits on the taskset, send the response to the
|
48
|
+
# second job.
|
49
|
+
c.exec { taskset.wait }
|
50
|
+
s.exec { server.send_response(sock, :work_complete, "b\00015") }
|
51
|
+
c.wait
|
52
|
+
s.wait
|
53
|
+
|
54
|
+
# Check that we got the right answers.
|
55
|
+
assert_equal(7, res1)
|
56
|
+
assert_equal(15, res2)
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Tests that the high priority option can be set in a job request
|
61
|
+
def test_client_submit_priority_high
|
62
|
+
server = FakeJobServer.new(self)
|
63
|
+
client, task1, task2, taskset, sock, res1, res2 = nil
|
64
|
+
|
65
|
+
s = TestScript.new
|
66
|
+
c = TestScript.new
|
67
|
+
|
68
|
+
server_thread = Thread.new { s.loop_forever }.run
|
69
|
+
client_thread = Thread.new { c.loop_forever }.run
|
70
|
+
|
71
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
72
|
+
|
73
|
+
c.exec { task1 = Gearman::Task.new('add', '5 2', { :priority => :high }) }
|
74
|
+
c.exec { task1.on_complete {|d| res1 = d.to_i } }
|
75
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
76
|
+
c.exec { taskset.add_task(task1) }
|
77
|
+
s.exec { sock = server.expect_connection }
|
78
|
+
s.wait
|
79
|
+
|
80
|
+
s.exec { server.expect_request(sock, :submit_job_high, "add\000\0005 2") }
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Tests that the low priority option can be set in a job request
|
85
|
+
def test_client_submit_priority_low
|
86
|
+
server = FakeJobServer.new(self)
|
87
|
+
client, task1, task2, taskset, sock, res1, res2 = nil
|
88
|
+
|
89
|
+
s = TestScript.new
|
90
|
+
c = TestScript.new
|
91
|
+
|
92
|
+
server_thread = Thread.new { s.loop_forever }.run
|
93
|
+
client_thread = Thread.new { c.loop_forever }.run
|
94
|
+
|
95
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
96
|
+
|
97
|
+
c.exec { task1 = Gearman::Task.new('add', '5 2', { :priority => :low }) }
|
98
|
+
c.exec { task1.on_complete {|d| res1 = d.to_i } }
|
99
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
100
|
+
c.exec { taskset.add_task(task1) }
|
101
|
+
s.exec { sock = server.expect_connection }
|
102
|
+
s.wait
|
103
|
+
|
104
|
+
s.exec { server.expect_request(sock, :submit_job_low, "add\000\0005 2") }
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
##
|
109
|
+
# Check that the client sends a correct background job request
|
110
|
+
def test_client_submit_background
|
111
|
+
server = FakeJobServer.new(self)
|
112
|
+
client, task1, task2, taskset, sock, res1, res2 = nil
|
113
|
+
|
114
|
+
s = TestScript.new
|
115
|
+
c = TestScript.new
|
116
|
+
|
117
|
+
server_thread = Thread.new { s.loop_forever }.run
|
118
|
+
client_thread = Thread.new { c.loop_forever }.run
|
119
|
+
|
120
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
121
|
+
|
122
|
+
c.exec { task1 = Gearman::Task.new('add', '5 2', { :background => :true }) }
|
123
|
+
c.exec { task1.on_complete {|d| res1 = d.to_i } }
|
124
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
125
|
+
c.exec { taskset.add_task(task1) }
|
126
|
+
s.exec { sock = server.expect_connection }
|
127
|
+
s.wait
|
128
|
+
|
129
|
+
s.exec { server.expect_request(sock, :submit_job_bg, "add\000\0005 2") }
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Check that the client sends a correct background job with high priority request
|
134
|
+
def test_client_submit_background
|
135
|
+
server = FakeJobServer.new(self)
|
136
|
+
client, task1, task2, taskset, sock, res1, res2 = nil
|
137
|
+
|
138
|
+
s = TestScript.new
|
139
|
+
c = TestScript.new
|
140
|
+
|
141
|
+
server_thread = Thread.new { s.loop_forever }.run
|
142
|
+
client_thread = Thread.new { c.loop_forever }.run
|
143
|
+
|
144
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
145
|
+
|
146
|
+
c.exec { task1 = Gearman::Task.new('add', '5 2', { :background => :true, :priority => :high }) }
|
147
|
+
c.exec { task1.on_complete {|d| res1 = d.to_i } }
|
148
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
149
|
+
c.exec { taskset.add_task(task1) }
|
150
|
+
s.exec { sock = server.expect_connection }
|
151
|
+
s.wait
|
152
|
+
|
153
|
+
s.exec { server.expect_request(sock, :submit_job_high_bg, "add\000\0005 2") }
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# Check that the client sends a correct background job with low priority request
|
158
|
+
def test_client_submit_background
|
159
|
+
server = FakeJobServer.new(self)
|
160
|
+
client, task1, task2, taskset, sock, res1, res2 = nil
|
161
|
+
|
162
|
+
s = TestScript.new
|
163
|
+
c = TestScript.new
|
164
|
+
|
165
|
+
server_thread = Thread.new { s.loop_forever }.run
|
166
|
+
client_thread = Thread.new { c.loop_forever }.run
|
167
|
+
|
168
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
169
|
+
|
170
|
+
c.exec { task1 = Gearman::Task.new('add', '5 2', { :background => :true, :priority => :low }) }
|
171
|
+
c.exec { task1.on_complete {|d| res1 = d.to_i } }
|
172
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
173
|
+
c.exec { taskset.add_task(task1) }
|
174
|
+
s.exec { sock = server.expect_connection }
|
175
|
+
s.wait
|
176
|
+
|
177
|
+
s.exec { server.expect_request(sock, :submit_job_low_bg, "add\000\0005 2") }
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Test Client#do_task.
|
182
|
+
def test_do_task
|
183
|
+
server = FakeJobServer.new(self)
|
184
|
+
client, sock, res = nil
|
185
|
+
|
186
|
+
s = TestScript.new
|
187
|
+
c = TestScript.new
|
188
|
+
|
189
|
+
server_thread = Thread.new { s.loop_forever }.run
|
190
|
+
client_thread = Thread.new { c.loop_forever }.run
|
191
|
+
|
192
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
193
|
+
|
194
|
+
c.exec { res = client.do_task('add', '5 2').to_i }
|
195
|
+
s.exec { sock = server.expect_connection }
|
196
|
+
s.wait
|
197
|
+
|
198
|
+
s.exec { server.expect_request(sock, :submit_job, "add\000\0005 2") }
|
199
|
+
s.exec { server.send_response(sock, :job_created, 'a') }
|
200
|
+
s.exec { server.send_response(sock, :work_complete, "a\0007") }
|
201
|
+
c.wait
|
202
|
+
s.wait
|
203
|
+
|
204
|
+
assert_equal(7, res)
|
205
|
+
|
206
|
+
c.exec { res = client.do_task('add', '1 2') }
|
207
|
+
s.exec { server.expect_request(sock, :submit_job, "add\000\0001 2") }
|
208
|
+
s.exec { server.send_response(sock, :job_created, 'a') }
|
209
|
+
s.exec { server.send_response(sock, :work_fail, 'a') }
|
210
|
+
c.wait
|
211
|
+
s.wait
|
212
|
+
|
213
|
+
assert_equal(nil, res)
|
214
|
+
end
|
215
|
+
|
216
|
+
##
|
217
|
+
# Test that Gearman::Task's callback's get called when they should.
|
218
|
+
def test_callbacks
|
219
|
+
server = FakeJobServer.new(self)
|
220
|
+
client, task, taskset, sock = nil
|
221
|
+
failed, retries, num, den, warning = nil
|
222
|
+
|
223
|
+
s = TestScript.new
|
224
|
+
c = TestScript.new
|
225
|
+
|
226
|
+
server_thread = Thread.new { s.loop_forever }.run
|
227
|
+
client_thread = Thread.new { c.loop_forever }.run
|
228
|
+
|
229
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
230
|
+
|
231
|
+
task = Gearman::Task.new('foo', 'bar', { :retry_count => 3 })
|
232
|
+
task.on_fail { failed = true }
|
233
|
+
task.on_retry {|r| retries = r }
|
234
|
+
task.on_status {|n,d| num = n.to_i; den = d.to_i }
|
235
|
+
task.on_warning {|msg| warning = msg }
|
236
|
+
received_data = ""
|
237
|
+
task.on_data {|data| received_data << data }
|
238
|
+
|
239
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
240
|
+
c.exec { taskset.add_task(task) }
|
241
|
+
s.exec { sock = server.expect_connection }
|
242
|
+
s.wait
|
243
|
+
|
244
|
+
# Send 4 failures back to the client.
|
245
|
+
c.exec { taskset.wait }
|
246
|
+
s.exec { server.expect_request(sock, :submit_job, "foo\000\000bar") }
|
247
|
+
s.exec { server.send_response(sock, :job_created, 'a') }
|
248
|
+
s.exec { server.send_response(sock, :work_fail, 'a') }
|
249
|
+
s.exec { server.expect_request(sock, :submit_job, "foo\000\000bar") }
|
250
|
+
s.exec { server.send_response(sock, :job_created, 'b') }
|
251
|
+
s.exec { server.send_response(sock, :work_fail, 'b') }
|
252
|
+
s.exec { server.expect_request(sock, :submit_job, "foo\000\000bar") }
|
253
|
+
s.exec { server.send_response(sock, :job_created, 'c') }
|
254
|
+
s.exec { server.send_response(sock, :work_status, "c\0001\0002") }
|
255
|
+
s.exec { server.send_response(sock, :work_fail, 'c') }
|
256
|
+
s.exec { server.send_response(sock, :job_created, 'd') }
|
257
|
+
s.exec { server.send_response(sock, :work_data, "d\000data chunk 1") }
|
258
|
+
s.exec { server.send_response(sock, :work_data, "d\000data chunk 2") }
|
259
|
+
s.exec { server.send_response(sock, :work_warning, "d\000warning") }
|
260
|
+
s.exec { server.send_response(sock, :work_fail, 'd') }
|
261
|
+
c.wait
|
262
|
+
s.wait
|
263
|
+
|
264
|
+
assert_equal(true, failed)
|
265
|
+
assert_equal(3, retries)
|
266
|
+
assert_equal(1, num)
|
267
|
+
assert_equal(2, den)
|
268
|
+
assert_equal("data chunk 1data chunk 2", received_data)
|
269
|
+
assert_equal("warning", warning)
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_failure
|
273
|
+
server = FakeJobServer.new(self)
|
274
|
+
client, task1, task2, taskset, sock = nil
|
275
|
+
res1, res2, fail1, fail2, setres = nil
|
276
|
+
|
277
|
+
s = TestScript.new
|
278
|
+
c = TestScript.new
|
279
|
+
|
280
|
+
server_thread = Thread.new { s.loop_forever }.run
|
281
|
+
client_thread = Thread.new { c.loop_forever }.run
|
282
|
+
|
283
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
284
|
+
|
285
|
+
c.exec { task1 = Gearman::Task.new('func1', 'a') }
|
286
|
+
c.exec { task1.on_complete {|d| res1 = d } }
|
287
|
+
c.exec { task1.on_fail { fail1 = true } }
|
288
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
289
|
+
c.exec { taskset.add_task(task1) }
|
290
|
+
s.exec { sock = server.expect_connection }
|
291
|
+
s.wait
|
292
|
+
|
293
|
+
s.exec { server.expect_request(sock, :submit_job, "func1\000\000a") }
|
294
|
+
s.exec { server.send_response(sock, :job_created, 'a') }
|
295
|
+
|
296
|
+
c.exec { task2 = Gearman::Task.new('func2', 'b') }
|
297
|
+
c.exec { task2.on_complete {|d| res2 = d } }
|
298
|
+
c.exec { task2.on_fail { fail2 = true } }
|
299
|
+
c.exec { taskset.add_task(task2) }
|
300
|
+
|
301
|
+
s.exec { server.expect_request(sock, :submit_job, "func2\000\000b") }
|
302
|
+
s.exec { server.send_response(sock, :job_created, 'b') }
|
303
|
+
|
304
|
+
s.exec { server.send_response(sock, :work_complete, "a\000a1") }
|
305
|
+
s.exec { server.send_response(sock, :work_fail, "b") }
|
306
|
+
|
307
|
+
c.exec { setres = taskset.wait }
|
308
|
+
c.wait
|
309
|
+
s.wait
|
310
|
+
|
311
|
+
assert_equal('a1', res1)
|
312
|
+
assert_equal(nil, res2)
|
313
|
+
assert_equal(nil, fail1)
|
314
|
+
assert_equal(true, fail2)
|
315
|
+
assert_equal(false, setres)
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_exception
|
319
|
+
server = FakeJobServer.new(self)
|
320
|
+
client, task, taskset, sock = nil
|
321
|
+
res,exception, setres = nil
|
322
|
+
|
323
|
+
s = TestScript.new
|
324
|
+
c = TestScript.new
|
325
|
+
|
326
|
+
server_thread = Thread.new { s.loop_forever }.run
|
327
|
+
client_thread = Thread.new { c.loop_forever }.run
|
328
|
+
|
329
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
330
|
+
|
331
|
+
c.exec { task = Gearman::Task.new('func2', 'b') }
|
332
|
+
c.exec { task.on_complete {|d| res = d } }
|
333
|
+
c.exec { task.on_exception {|message| exception=message; false } }
|
334
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
335
|
+
c.exec { taskset.add_task(task) }
|
336
|
+
s.exec { sock = server.expect_connection }
|
337
|
+
|
338
|
+
s.exec { server.expect_request(sock, :submit_job, "func2\000\000b") }
|
339
|
+
s.exec { server.send_response(sock, :job_created, 'b') }
|
340
|
+
|
341
|
+
s.exec { server.send_response(sock, :work_exception, "b\0exceptionmsg") }
|
342
|
+
|
343
|
+
c.exec { setres = taskset.wait }
|
344
|
+
c.wait
|
345
|
+
s.wait
|
346
|
+
|
347
|
+
assert_equal(nil, res)
|
348
|
+
assert_equal('exceptionmsg',exception)
|
349
|
+
end
|
350
|
+
|
351
|
+
##
|
352
|
+
# Test that user-supplied uniq values are handled correctly.
|
353
|
+
def test_uniq
|
354
|
+
server1 = FakeJobServer.new(self)
|
355
|
+
server2 = FakeJobServer.new(self)
|
356
|
+
client = nil
|
357
|
+
sock1, sock2 = nil
|
358
|
+
taskset = nil
|
359
|
+
task1, task2, task3, task4 = nil
|
360
|
+
res1, res2, res3, res4 = nil
|
361
|
+
hostport1 = "localhost:#{server1.port}"
|
362
|
+
hostport2 = "localhost:#{server2.port}"
|
363
|
+
|
364
|
+
s1 = TestScript.new
|
365
|
+
s2 = TestScript.new
|
366
|
+
c = TestScript.new
|
367
|
+
|
368
|
+
server1_thread = Thread.new { s1.loop_forever }.run
|
369
|
+
server2_thread = Thread.new { s2.loop_forever }.run
|
370
|
+
client_thread = Thread.new { c.loop_forever }.run
|
371
|
+
|
372
|
+
c.exec { client = Gearman::Client.new }
|
373
|
+
c.exec { client.job_servers = [hostport1, hostport2] }
|
374
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
375
|
+
|
376
|
+
# Submit a task with uniq key 'u' to the first server.
|
377
|
+
c.exec { client.test_hostport = hostport1 }
|
378
|
+
c.exec { task1 = Gearman::Task.new('func1', 'arg', { :uniq => 'u' }) }
|
379
|
+
c.exec { task1.on_complete {|d| res1 = d.to_i } }
|
380
|
+
c.exec { taskset.add_task(task1) }
|
381
|
+
|
382
|
+
s1.exec { sock1 = server1.expect_connection }
|
383
|
+
s1.wait
|
384
|
+
|
385
|
+
s1.exec { server1.expect_request(
|
386
|
+
sock1, :submit_job, "func1\000#{'u'.hash}\000arg") }
|
387
|
+
s1.exec { server1.send_response(sock1, :job_created, 'a') }
|
388
|
+
|
389
|
+
# If we submit a second task with the same key, it should get sent to
|
390
|
+
# the same server.
|
391
|
+
c.exec { client.test_hostport = hostport2 }
|
392
|
+
c.exec { task2 = Gearman::Task.new('func1', 'arg2', { :uniq => 'u' }) }
|
393
|
+
c.exec { task2.on_complete {|d| res2 = d.to_i } }
|
394
|
+
c.exec { taskset.add_task(task2) }
|
395
|
+
|
396
|
+
s1.exec { server1.expect_request(
|
397
|
+
sock1, :submit_job, "func1\000#{'u'.hash}\000arg2") }
|
398
|
+
s1.exec { server1.send_response(sock1, :job_created, 'a') }
|
399
|
+
|
400
|
+
# When we create a task with key 'a', it should go to the second
|
401
|
+
# server.
|
402
|
+
c.exec { task3 = Gearman::Task.new('func1', 'arg', { :uniq => 'a' }) }
|
403
|
+
c.exec { task3.on_complete {|d| res3 = d.to_i } }
|
404
|
+
c.exec { taskset.add_task(task3) }
|
405
|
+
|
406
|
+
s2.exec { sock2 = server2.expect_connection }
|
407
|
+
s2.wait
|
408
|
+
|
409
|
+
s2.exec { server2.expect_request(
|
410
|
+
sock2, :submit_job, "func1\000#{'a'.hash}\000arg") }
|
411
|
+
s2.exec { server2.send_response(sock2, :job_created, 'b') }
|
412
|
+
|
413
|
+
# If we tell the client to use the first server again and create
|
414
|
+
# another job with no uniq key, it should go back to the first server.
|
415
|
+
c.exec { client.test_hostport = hostport1 }
|
416
|
+
c.exec { task4 = Gearman::Task.new('func1', 'arg') }
|
417
|
+
c.exec { task4.on_complete {|d| res4 = d.to_i } }
|
418
|
+
c.exec { taskset.add_task(task4) }
|
419
|
+
|
420
|
+
s1.exec { server1.expect_request(
|
421
|
+
sock1, :submit_job, "func1\000\000arg") }
|
422
|
+
s1.exec { server1.send_response(sock1, :job_created, 'c') }
|
423
|
+
|
424
|
+
# Send back responses for all the handles we've handed out and make
|
425
|
+
# sure that we got what we expected.
|
426
|
+
c.exec { taskset.wait }
|
427
|
+
s1.exec { server1.send_response(sock1, :work_complete, "a\0001") }
|
428
|
+
s2.exec { server2.send_response(sock2, :work_complete, "b\0002") }
|
429
|
+
s1.exec { server1.send_response(sock1, :work_complete, "c\0003") }
|
430
|
+
|
431
|
+
c.wait
|
432
|
+
s1.wait
|
433
|
+
s2.wait
|
434
|
+
|
435
|
+
assert_equal(1, res1)
|
436
|
+
assert_equal(1, res2)
|
437
|
+
assert_equal(2, res3)
|
438
|
+
assert_equal(3, res4)
|
439
|
+
|
440
|
+
c.wait
|
441
|
+
s1.wait
|
442
|
+
s2.wait
|
443
|
+
end
|
444
|
+
|
445
|
+
##
|
446
|
+
# Test that '-' uniq values work correctly.
|
447
|
+
def test_uniq_dash
|
448
|
+
server1 = FakeJobServer.new(self)
|
449
|
+
server2 = FakeJobServer.new(self)
|
450
|
+
client, taskset, sock1, sock2 = nil
|
451
|
+
task1, task2, task3 = nil
|
452
|
+
res1, res2, res3 = nil
|
453
|
+
hostport1 = "localhost:#{server1.port}"
|
454
|
+
hostport2 = "localhost:#{server2.port}"
|
455
|
+
|
456
|
+
s1 = TestScript.new
|
457
|
+
s2 = TestScript.new
|
458
|
+
c = TestScript.new
|
459
|
+
|
460
|
+
server1_thread = Thread.new { s1.loop_forever }.run
|
461
|
+
server2_thread = Thread.new { s2.loop_forever }.run
|
462
|
+
client_thread = Thread.new { c.loop_forever }.run
|
463
|
+
|
464
|
+
c.exec { client = Gearman::Client.new }
|
465
|
+
c.exec { client.job_servers = [hostport1, hostport2] }
|
466
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
467
|
+
|
468
|
+
# The first task uses uniq = '-' with the argument 'arg'.
|
469
|
+
c.exec { client.test_hostport = hostport1 }
|
470
|
+
c.exec { task1 = Gearman::Task.new('func1', 'arg', { :uniq => '-' }) }
|
471
|
+
c.exec { task1.on_complete {|d| res1 = d.to_i } }
|
472
|
+
c.exec { taskset.add_task(task1) }
|
473
|
+
|
474
|
+
s1.exec { sock1 = server1.expect_connection }
|
475
|
+
s1.wait
|
476
|
+
|
477
|
+
s1.exec { server1.expect_request(
|
478
|
+
sock1, :submit_job, "func1\000#{'arg'.hash}\000arg") }
|
479
|
+
s1.exec { server1.send_response(sock1, :job_created, 'a') }
|
480
|
+
|
481
|
+
# The second task uses the same arg, so it should be merged with the
|
482
|
+
# first by the server (and also be executed on the first server, even
|
483
|
+
# though we've changed the client to use the second by default).
|
484
|
+
c.exec { client.test_hostport = hostport2 }
|
485
|
+
c.exec { task2 = Gearman::Task.new('func1', 'arg', { :uniq => '-' }) }
|
486
|
+
c.exec { task2.on_complete {|d| res2 = d.to_i } }
|
487
|
+
c.exec { taskset.add_task(task2) }
|
488
|
+
|
489
|
+
s1.exec { server1.expect_request(
|
490
|
+
sock1, :submit_job, "func1\000#{'arg'.hash}\000arg") }
|
491
|
+
s1.exec { server1.send_response(sock1, :job_created, 'a') }
|
492
|
+
|
493
|
+
# The third task uses 'arg2', so it should not be merged and instead
|
494
|
+
# run on the second server.
|
495
|
+
c.exec { task3 = Gearman::Task.new('func1', 'arg2', { :uniq => '-' }) }
|
496
|
+
c.exec { task3.on_complete {|d| res3 = d.to_i } }
|
497
|
+
c.exec { taskset.add_task(task3) }
|
498
|
+
|
499
|
+
s2.exec { sock2 = server2.expect_connection }
|
500
|
+
s2.wait
|
501
|
+
|
502
|
+
s2.exec { server2.expect_request(
|
503
|
+
sock2, :submit_job, "func1\000#{'arg2'.hash}\000arg2") }
|
504
|
+
s2.exec { server2.send_response(sock2, :job_created, 'b') }
|
505
|
+
|
506
|
+
# Send back results for the two handles that we've handed out.
|
507
|
+
c.exec { taskset.wait }
|
508
|
+
s1.exec { server1.send_response(sock1, :work_complete, "a\0001") }
|
509
|
+
s2.exec { server2.send_response(sock2, :work_complete, "b\0002") }
|
510
|
+
|
511
|
+
c.wait
|
512
|
+
s1.wait
|
513
|
+
s2.wait
|
514
|
+
|
515
|
+
assert_equal(1, res1)
|
516
|
+
assert_equal(1, res2)
|
517
|
+
assert_equal(2, res3)
|
518
|
+
end
|
519
|
+
|
520
|
+
##
|
521
|
+
# Test that NUL bytes in returned data are preserved.
|
522
|
+
def test_nuls_in_data
|
523
|
+
server = FakeJobServer.new(self)
|
524
|
+
client, sock, res = nil
|
525
|
+
|
526
|
+
s = TestScript.new
|
527
|
+
c = TestScript.new
|
528
|
+
|
529
|
+
server_thread = Thread.new { s.loop_forever }.run
|
530
|
+
client_thread = Thread.new { c.loop_forever }.run
|
531
|
+
|
532
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
533
|
+
|
534
|
+
c.exec { res = client.do_task('foo', nil) }
|
535
|
+
s.exec { sock = server.expect_connection }
|
536
|
+
s.wait
|
537
|
+
|
538
|
+
s.exec { server.expect_request(sock, :submit_job, "foo\000\000") }
|
539
|
+
s.exec { server.send_response(sock, :job_created, 'a') }
|
540
|
+
s.exec { server.send_response(sock, :work_complete, "a\0001\0002\0003") }
|
541
|
+
c.wait
|
542
|
+
s.wait
|
543
|
+
|
544
|
+
assert_equal("1\0002\0003", res)
|
545
|
+
end
|
546
|
+
|
547
|
+
##
|
548
|
+
# Test that clients time out when the server sends a partial packet and
|
549
|
+
# then hangs.
|
550
|
+
def test_read_timeouts
|
551
|
+
server = FakeJobServer.new(self)
|
552
|
+
client, sock, task, taskset, res = nil
|
553
|
+
|
554
|
+
s = TestScript.new
|
555
|
+
c = TestScript.new
|
556
|
+
|
557
|
+
server_thread = Thread.new { s.loop_forever }.run
|
558
|
+
client_thread = Thread.new { c.loop_forever }.run
|
559
|
+
|
560
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
561
|
+
|
562
|
+
# First, create a new task. The server claims to be sending back a
|
563
|
+
# packet with 1 byte of data, but actually sends an empty packet. The
|
564
|
+
# client should time out after 0.1 sec.
|
565
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
566
|
+
c.exec { task = Gearman::Task.new('foo', 'bar') }
|
567
|
+
c.exec { client.task_create_timeout_sec = 0.1 }
|
568
|
+
c.exec { res = taskset.add_task(task) }
|
569
|
+
s.exec { sock = server.expect_connection }
|
570
|
+
s.wait
|
571
|
+
|
572
|
+
s.exec { server.expect_request(sock, :submit_job, "foo\000\000bar") }
|
573
|
+
s.exec { server.send_response(sock, :job_created, '', 1) }
|
574
|
+
c.wait
|
575
|
+
s.wait
|
576
|
+
|
577
|
+
assert_equal(false, res)
|
578
|
+
|
579
|
+
# Now create a task, but only return a partial packet for
|
580
|
+
# work_complete. The client should again time out after 0.1 sec.
|
581
|
+
c.exec { res = taskset.add_task(task) }
|
582
|
+
s.exec { sock = server.expect_connection }
|
583
|
+
s.wait
|
584
|
+
|
585
|
+
s.exec { server.expect_request(sock, :submit_job, "foo\000\000bar") }
|
586
|
+
s.exec { server.send_response(sock, :job_created, 'a') }
|
587
|
+
c.exec { res = taskset.wait(0.1) }
|
588
|
+
s.exec { server.send_response(sock, :work_complete, "a\000", 3) }
|
589
|
+
c.wait
|
590
|
+
s.wait
|
591
|
+
|
592
|
+
assert_equal(false, res)
|
593
|
+
end
|
594
|
+
|
595
|
+
##
|
596
|
+
# Tests partial data responses (work_data)
|
597
|
+
def test_chunked_data
|
598
|
+
server = FakeJobServer.new(self)
|
599
|
+
client, sock, task, taskset, res = nil
|
600
|
+
|
601
|
+
s = TestScript.new
|
602
|
+
c = TestScript.new
|
603
|
+
|
604
|
+
server_thread = Thread.new { s.loop_forever }.run
|
605
|
+
client_thread = Thread.new { c.loop_forever }.run
|
606
|
+
|
607
|
+
c.exec { client = Gearman::Client.new("localhost:#{server.port}") }
|
608
|
+
task = Gearman::Task.new('foo', 'bar', { :retry_count => 3 })
|
609
|
+
received_data = ""
|
610
|
+
task.on_data {|data| received_data << data }
|
611
|
+
task.on_complete {|data| received_data << data}
|
612
|
+
|
613
|
+
c.exec { taskset = Gearman::TaskSet.new(client) }
|
614
|
+
c.exec { taskset.add_task(task) }
|
615
|
+
s.exec { sock = server.expect_connection }
|
616
|
+
s.wait
|
617
|
+
|
618
|
+
c.exec { taskset.wait }
|
619
|
+
s.exec { server.expect_request(sock, :submit_job, "foo\000\000bar") }
|
620
|
+
s.exec { server.send_response(sock, :job_created, 'a') }
|
621
|
+
s.exec { server.send_response(sock, :work_data, "a\000data chunk 1\n") }
|
622
|
+
s.exec { server.send_response(sock, :work_data, "a\000data chunk 2\n") }
|
623
|
+
s.exec { server.send_response(sock, :work_complete, "a\000data complete") }
|
624
|
+
c.wait
|
625
|
+
s.wait
|
626
|
+
|
627
|
+
assert_equal("data chunk 1\ndata chunk 2\ndata complete", received_data)
|
628
|
+
end
|
629
|
+
end
|