gearman-ruby 3.0.8 → 4.0.2
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 +8 -8
- data/.travis.yml +5 -0
- data/CHANGELOG.md +6 -4
- data/README.md +111 -0
- data/examples/client.rb +1 -2
- data/examples/client_reverse_nohost.rb +30 -0
- data/examples/{client_reverse.rb → client_reverse_wait.rb} +9 -11
- data/examples/worker.rb +8 -5
- data/examples/worker_reverse_string.rb +12 -17
- data/gearman-ruby.gemspec +3 -5
- data/lib/gearman.rb +17 -77
- data/lib/gearman/client.rb +129 -147
- data/lib/gearman/connection.rb +158 -0
- data/lib/gearman/connection_pool.rb +131 -0
- data/lib/gearman/exceptions.rb +24 -0
- data/lib/gearman/logging.rb +19 -0
- data/lib/gearman/packet.rb +61 -0
- data/lib/gearman/task.rb +1 -1
- data/lib/gearman/task_set.rb +67 -0
- data/lib/gearman/version.rb +1 -1
- data/lib/gearman/worker.rb +185 -412
- data/lib/gearman/worker/ability.rb +55 -0
- data/lib/gearman/worker/callbacks.rb +39 -0
- data/lib/gearman/worker/job.rb +44 -0
- data/spec/client_spec.rb +32 -20
- data/spec/connection_pool_spec.rb +55 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/task_spec.rb +10 -0
- data/spec/taskset_spec.rb +2 -2
- metadata +18 -37
- data/HOWTO +0 -146
- data/README +0 -9
- data/TODO +0 -8
- data/VERSION.yml +0 -4
- data/examples/calculus_client.rb +0 -39
- data/examples/calculus_worker.rb +0 -45
- data/examples/client.php +0 -23
- data/examples/client_background.rb +0 -14
- data/examples/client_data.rb +0 -16
- data/examples/client_epoch.rb +0 -23
- data/examples/client_exception.rb +0 -19
- data/examples/client_prefix.rb +0 -17
- data/examples/gearman_environment.sh +0 -25
- data/examples/scale_image.rb +0 -31
- data/examples/scale_image_worker.rb +0 -34
- data/examples/server.rb +0 -15
- data/examples/worker_data.rb +0 -16
- data/examples/worker_exception.rb +0 -14
- data/examples/worker_prefix.rb +0 -25
- data/examples/worker_reverse_to_file.rb +0 -18
- data/examples/worker_signals.rb +0 -36
- data/lib/gearman/taskset.rb +0 -293
- data/lib/gearman/util.rb +0 -211
- data/spec/util_spec.rb +0 -67
@@ -0,0 +1,55 @@
|
|
1
|
+
module Gearman
|
2
|
+
class Worker
|
3
|
+
|
4
|
+
class Ability
|
5
|
+
##
|
6
|
+
# Create a new ability. Setting timeout means we register with CAN_DO_TIMEOUT
|
7
|
+
# @param func_name Function name of this ability
|
8
|
+
# @param block Code to run
|
9
|
+
# @param timeout Server gives up on us after this many seconds
|
10
|
+
def initialize(func_name, block, timeout=nil)
|
11
|
+
@func_name = func_name
|
12
|
+
@block = block
|
13
|
+
@timeout = timeout
|
14
|
+
@on_complete = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :timeout, :func_name
|
18
|
+
|
19
|
+
##
|
20
|
+
# Run the block of code given for a job of this type.
|
21
|
+
#
|
22
|
+
# @param data data passed to us by a client
|
23
|
+
# @param job interface to report job information to the server
|
24
|
+
def run(data, job)
|
25
|
+
begin
|
26
|
+
result = @block.call(data, job) if @block
|
27
|
+
@on_complete.call(result, data) if @on_complete
|
28
|
+
return result
|
29
|
+
rescue => ex
|
30
|
+
raise ex
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Add an after-ability hook
|
36
|
+
#
|
37
|
+
# The passed-in block of code will be executed after the work block for
|
38
|
+
# jobs with the same function name. It takes two arguments, the result of
|
39
|
+
# the work and the original job data. This way, if you need to hook into
|
40
|
+
# *after* the job_complete packet is sent to the server, you can do so.
|
41
|
+
#
|
42
|
+
# N.B The after-ability hook ONLY runs if the ability was successful and no
|
43
|
+
# exceptions were raised.
|
44
|
+
#
|
45
|
+
# @param func function name (without prefix)
|
46
|
+
#
|
47
|
+
def after_complete(&block)
|
48
|
+
@on_complete = block
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Provides callbacks for internal worker use:
|
2
|
+
#
|
3
|
+
# def named_metric(metric)
|
4
|
+
# "HardWorker.#{Process.pid}.#{metric}"
|
5
|
+
# end
|
6
|
+
#
|
7
|
+
# worker = Gearman::Worker.new
|
8
|
+
# worker.on_grab_job { StatsD.increment(named_metric('grab_job')) }
|
9
|
+
# worker.on_job_assign { StatsD.increment(named_metric('job_assign')) }
|
10
|
+
# worker.on_no_job { StatsD.increment(named_metric('no_job')) }
|
11
|
+
# worker.on_work_complete { StatsD.increment(named_metric('work_complete')) }
|
12
|
+
|
13
|
+
module Gearman
|
14
|
+
class Worker
|
15
|
+
|
16
|
+
module Callbacks
|
17
|
+
|
18
|
+
%w(connect grab_job no_job job_assign work_complete work_fail
|
19
|
+
work_exception).each do |event|
|
20
|
+
|
21
|
+
define_method("on_#{event}") do |&callback|
|
22
|
+
instance_variable_set("@__on_#{event}", callback)
|
23
|
+
end
|
24
|
+
|
25
|
+
define_method("run_#{event}_callback") do
|
26
|
+
callback = instance_variable_get("@__on_#{event}")
|
27
|
+
return unless callback
|
28
|
+
|
29
|
+
begin
|
30
|
+
callback.call
|
31
|
+
rescue Exception => e
|
32
|
+
logger.error "#{event} failed: #{e.inspect}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Gearman
|
2
|
+
class Worker
|
3
|
+
|
4
|
+
class Job
|
5
|
+
##
|
6
|
+
# Create a new Job.
|
7
|
+
#
|
8
|
+
# @param sock Socket connected to job server
|
9
|
+
# @param handle job server-supplied job handle
|
10
|
+
attr_reader :handle
|
11
|
+
|
12
|
+
def initialize(connection, handle)
|
13
|
+
@connection = connection
|
14
|
+
@handle = handle
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Report our status to the job server.
|
19
|
+
def report_status(numerator, denominator)
|
20
|
+
req = Packet.pack_request(:work_status, "#{@handle}\0#{numerator}\0#{denominator}")
|
21
|
+
@connection.send_update(req)
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Send data before job completes
|
27
|
+
def send_data(data)
|
28
|
+
req = Packet.pack_request(:work_data, "#{@handle}\0#{data}")
|
29
|
+
@connection.send_update(req)
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Send a warning explicitly
|
35
|
+
def report_warning(warning)
|
36
|
+
req = Packet.pack_request(:work_warning, "#{@handle}\0#{warning}")
|
37
|
+
@connection.send_update(req)
|
38
|
+
self
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
data/spec/client_spec.rb
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'socket'
|
3
|
-
require 'rspec'
|
4
|
-
require 'rspec/mocks'
|
5
|
-
require 'gearman'
|
6
3
|
|
7
4
|
describe Gearman::Client do
|
8
5
|
before(:all) do
|
9
6
|
@tcp_server = TCPServer.new 5789
|
10
|
-
@client = Gearman::Client.new(["localhost:5789"])
|
11
7
|
end
|
12
8
|
|
13
9
|
after(:all) do
|
14
10
|
@tcp_server.close
|
15
11
|
end
|
16
12
|
|
13
|
+
before(:each) do
|
14
|
+
@mock_connection_pool = double(Gearman::ConnectionPool)
|
15
|
+
Gearman::ConnectionPool.stub(:new).and_return @mock_connection_pool
|
16
|
+
|
17
|
+
@client = Gearman::Client.new(["localhost:5789"])
|
18
|
+
end
|
19
|
+
|
17
20
|
it "creates a client" do
|
18
21
|
@client.should_not be nil
|
19
22
|
end
|
@@ -30,31 +33,40 @@ describe Gearman::Client do
|
|
30
33
|
|
31
34
|
it "raises an exception when submitting a job fails" do
|
32
35
|
task = Gearman::Task.new("queue", "data")
|
33
|
-
@
|
36
|
+
@mock_connection_pool.should_receive(:get_connection).and_raise Gearman::NoJobServersError
|
34
37
|
expect {
|
35
38
|
@client.do_task(task)
|
36
|
-
}.to
|
39
|
+
}.to raise_exception
|
37
40
|
end
|
38
41
|
|
39
|
-
it "
|
40
|
-
|
41
|
-
|
42
|
-
end
|
42
|
+
it "properly emits an options request" do
|
43
|
+
mock_connection = double(Gearman::Connection)
|
44
|
+
mock_connection.should_receive(:send_request).and_return([:error, "Snarf"])
|
43
45
|
|
44
|
-
|
45
|
-
sock = double(TCPSocket)
|
46
|
-
sock.should_receive(:addr).and_return [nil, 1234, 'hostname', '1.2.3.4']
|
47
|
-
sock.should_receive(:close)
|
48
|
-
@client.return_socket(sock)
|
49
|
-
end
|
46
|
+
@mock_connection_pool.should_receive(:with_all_connections).and_yield mock_connection
|
50
47
|
|
51
|
-
it "properly emits an options request" do
|
52
|
-
Gearman::Util.should_receive(:send_request)
|
53
|
-
Gearman::Util.should_receive(:read_response).and_return([:error, "Snarf"])
|
54
48
|
expect {
|
55
|
-
@client.
|
49
|
+
@client.set_options("exceptions")
|
56
50
|
}.to raise_error
|
57
51
|
|
58
52
|
end
|
59
53
|
|
54
|
+
|
55
|
+
|
56
|
+
it "should raise a NetworkError when it didn't write as much as expected to a socket" do
|
57
|
+
socket = double(TCPSocket)
|
58
|
+
socket.should_receive(:write).with(anything).and_return(0)
|
59
|
+
|
60
|
+
task = Gearman::Task.new("job_queue", "data")
|
61
|
+
request = task.get_submit_packet
|
62
|
+
connection = Gearman::Connection.new("localhost", 1234)
|
63
|
+
connection.should_receive(:socket).and_return socket
|
64
|
+
|
65
|
+
expect {
|
66
|
+
connection.send_request(request)
|
67
|
+
}.to raise_error
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
|
60
72
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
describe Gearman::ConnectionPool do
|
6
|
+
context "normalizing job servers" do
|
7
|
+
before :each do
|
8
|
+
@connection_pool = Gearman::ConnectionPool.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should handle a string for input" do
|
12
|
+
connection = Gearman::Connection.new("localhost", 1234)
|
13
|
+
connection.should_receive(:is_healthy?).and_return true
|
14
|
+
Gearman::Connection.should_receive(:new).with("localhost", 1234).and_return connection
|
15
|
+
@connection_pool.add_servers("localhost:1234")
|
16
|
+
@connection_pool.get_connection.should be connection
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should handle an array of host:port without changing a thing" do
|
20
|
+
connection_one = Gearman::Connection.new("localhost", 123)
|
21
|
+
connection_one.should_receive(:is_healthy?).and_return true
|
22
|
+
connection_two = Gearman::Connection.new("localhost", 456)
|
23
|
+
connection_two.should_receive(:is_healthy?).and_return true
|
24
|
+
|
25
|
+
Gearman::Connection.should_receive(:new).with("localhost", 123).and_return connection_one
|
26
|
+
Gearman::Connection.should_receive(:new).with("localhost", 456).and_return connection_two
|
27
|
+
|
28
|
+
servers = [ "#{connection_one.to_host_port}", "#{connection_two.to_host_port}" ]
|
29
|
+
@connection_pool.add_servers(servers)
|
30
|
+
|
31
|
+
|
32
|
+
@connection_pool.get_connection.should be connection_two
|
33
|
+
@connection_pool.get_connection.should be connection_one
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should append the default port to anything in the array that doesn't have a port" do
|
38
|
+
in_servers = ["foo.bar.com:123", "narf.quiddle.com"]
|
39
|
+
out_servers = ["foo.bar.com:123", "narf.quiddle.com:4730"]
|
40
|
+
|
41
|
+
connection_one = Gearman::Connection.new("foo.bar.com", 123)
|
42
|
+
connection_one.should_receive(:is_healthy?).and_return true
|
43
|
+
connection_two = Gearman::Connection.new("narf.quiddle.com", 4730)
|
44
|
+
connection_two.should_receive(:is_healthy?).and_return true
|
45
|
+
|
46
|
+
Gearman::Connection.should_receive(:new).with("foo.bar.com", 123).and_return connection_one
|
47
|
+
Gearman::Connection.should_receive(:new).with("narf.quiddle.com", 4730).and_return connection_two
|
48
|
+
|
49
|
+
@connection_pool.add_servers(in_servers)
|
50
|
+
|
51
|
+
@connection_pool.get_connection.should be connection_two
|
52
|
+
@connection_pool.get_connection.should be connection_one
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'simplecov'
|
2
|
+
require 'rspec'
|
3
|
+
require 'rspec/mocks'
|
2
4
|
|
3
5
|
SimpleCov.start do
|
4
6
|
add_filter "/spec/"
|
@@ -8,6 +10,9 @@ end
|
|
8
10
|
$:.unshift(File.expand_path('../lib', __FILE__))
|
9
11
|
require 'gearman'
|
10
12
|
|
13
|
+
Gearman.logger = Logger.new(STDERR)
|
14
|
+
Gearman.logger.level = Logger::DEBUG
|
15
|
+
|
11
16
|
RSpec.configure do |config|
|
12
17
|
config.mock_with :rspec
|
13
18
|
end
|
data/spec/task_spec.rb
CHANGED
@@ -16,6 +16,16 @@ describe Gearman::Task do
|
|
16
16
|
}.to raise_error
|
17
17
|
end
|
18
18
|
|
19
|
+
it "should generate a task from two arguments" do
|
20
|
+
task = Gearman::Task.new("queue", "data")
|
21
|
+
task.should_not be nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should generate a task from three arguments" do
|
25
|
+
task = Gearman::Task.new("queue", "data", {:background => true})
|
26
|
+
task.should_not be nil
|
27
|
+
end
|
28
|
+
|
19
29
|
it "generates a uniq value based on the data and the function" do
|
20
30
|
hash_data = 'bc2ca93d86a28cb72fedf36326d1da0cc3d4ed6a'
|
21
31
|
task_one = Gearman::Task.new("unique_id", "abcdef")
|
data/spec/taskset_spec.rb
CHANGED
@@ -13,7 +13,7 @@ describe Gearman::TaskSet do
|
|
13
13
|
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
xit "handles a NetworkError when submitting a job" do
|
17
17
|
bad_socket = double(TCPSocket)
|
18
18
|
bad_socket.should_receive(:write) { |*args|
|
19
19
|
args[0].length
|
@@ -41,7 +41,7 @@ describe Gearman::TaskSet do
|
|
41
41
|
task_set.add_task(task)
|
42
42
|
end
|
43
43
|
|
44
|
-
|
44
|
+
xit "waits for an answer from the server" do
|
45
45
|
good_socket = double(TCPSocket)
|
46
46
|
good_socket.should_receive(:write) { |*args|
|
47
47
|
args[0].length
|
metadata
CHANGED
@@ -1,21 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gearman-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Ewart
|
8
|
-
- Colin Curtin
|
9
|
-
- Daniel Erat
|
10
|
-
- Ladislav Martincik
|
11
|
-
- Pablo Delgado
|
12
|
-
- Mauro Pompilio
|
13
|
-
- Antonio Garrote
|
14
|
-
- Kim Altintop
|
15
8
|
autorequire:
|
16
9
|
bindir: bin
|
17
10
|
cert_chain: []
|
18
|
-
date:
|
11
|
+
date: 2014-11-29 00:00:00.000000000 Z
|
19
12
|
dependencies: []
|
20
13
|
description: Library for the Gearman distributed job system
|
21
14
|
email: john@johnewart.net
|
@@ -23,54 +16,42 @@ executables: []
|
|
23
16
|
extensions: []
|
24
17
|
extra_rdoc_files:
|
25
18
|
- LICENSE
|
26
|
-
- README
|
27
|
-
- TODO
|
19
|
+
- README.md
|
28
20
|
files:
|
29
21
|
- .gitignore
|
22
|
+
- .travis.yml
|
30
23
|
- CHANGELOG.md
|
31
24
|
- Gemfile
|
32
|
-
- HOWTO
|
33
25
|
- LICENSE
|
34
|
-
- README
|
26
|
+
- README.md
|
35
27
|
- Rakefile
|
36
|
-
- TODO
|
37
|
-
- VERSION.yml
|
38
|
-
- examples/calculus_client.rb
|
39
|
-
- examples/calculus_worker.rb
|
40
|
-
- examples/client.php
|
41
28
|
- examples/client.rb
|
42
|
-
- examples/
|
43
|
-
- examples/
|
44
|
-
- examples/client_epoch.rb
|
45
|
-
- examples/client_exception.rb
|
46
|
-
- examples/client_prefix.rb
|
47
|
-
- examples/client_reverse.rb
|
48
|
-
- examples/gearman_environment.sh
|
49
|
-
- examples/scale_image.rb
|
50
|
-
- examples/scale_image_worker.rb
|
51
|
-
- examples/server.rb
|
29
|
+
- examples/client_reverse_nohost.rb
|
30
|
+
- examples/client_reverse_wait.rb
|
52
31
|
- examples/worker.rb
|
53
|
-
- examples/worker_data.rb
|
54
|
-
- examples/worker_exception.rb
|
55
|
-
- examples/worker_prefix.rb
|
56
32
|
- examples/worker_reverse_string.rb
|
57
|
-
- examples/worker_reverse_to_file.rb
|
58
|
-
- examples/worker_signals.rb
|
59
33
|
- gearman-ruby.gemspec
|
60
34
|
- lib/gearman.rb
|
61
35
|
- lib/gearman/client.rb
|
36
|
+
- lib/gearman/connection.rb
|
37
|
+
- lib/gearman/connection_pool.rb
|
38
|
+
- lib/gearman/exceptions.rb
|
39
|
+
- lib/gearman/logging.rb
|
40
|
+
- lib/gearman/packet.rb
|
62
41
|
- lib/gearman/server.rb
|
63
42
|
- lib/gearman/task.rb
|
64
|
-
- lib/gearman/
|
65
|
-
- lib/gearman/util.rb
|
43
|
+
- lib/gearman/task_set.rb
|
66
44
|
- lib/gearman/version.rb
|
67
45
|
- lib/gearman/worker.rb
|
46
|
+
- lib/gearman/worker/ability.rb
|
47
|
+
- lib/gearman/worker/callbacks.rb
|
48
|
+
- lib/gearman/worker/job.rb
|
68
49
|
- spec/client_spec.rb
|
50
|
+
- spec/connection_pool_spec.rb
|
69
51
|
- spec/spec_helper.rb
|
70
52
|
- spec/support/fake_tcp_socket.rb
|
71
53
|
- spec/task_spec.rb
|
72
54
|
- spec/taskset_spec.rb
|
73
|
-
- spec/util_spec.rb
|
74
55
|
- test/client_test.rb
|
75
56
|
- test/mock_client_test.rb
|
76
57
|
- test/mock_worker_test.rb
|
@@ -102,11 +83,11 @@ specification_version: 4
|
|
102
83
|
summary: Ruby Gearman library
|
103
84
|
test_files:
|
104
85
|
- spec/client_spec.rb
|
86
|
+
- spec/connection_pool_spec.rb
|
105
87
|
- spec/spec_helper.rb
|
106
88
|
- spec/support/fake_tcp_socket.rb
|
107
89
|
- spec/task_spec.rb
|
108
90
|
- spec/taskset_spec.rb
|
109
|
-
- spec/util_spec.rb
|
110
91
|
- test/client_test.rb
|
111
92
|
- test/mock_client_test.rb
|
112
93
|
- test/mock_worker_test.rb
|
data/HOWTO
DELETED
@@ -1,146 +0,0 @@
|
|
1
|
-
= GEARMAN
|
2
|
-
|
3
|
-
"Gearman provides a generic application framework to farm out work to other
|
4
|
-
machines or processes that are better suited to do the work. It allows you to
|
5
|
-
do work in parallel, to load balance processing, and to call functions between
|
6
|
-
languages. It can be used in a variety of applications, from high-availability
|
7
|
-
web sites to the transport of database replication events. In other words, it
|
8
|
-
is the nervous system for how distributed processing communicates."
|
9
|
-
|
10
|
-
- http://www.gearman.org/
|
11
|
-
|
12
|
-
|
13
|
-
== Setting up a basic environment
|
14
|
-
|
15
|
-
A very basic Gearman environment will look like this:
|
16
|
-
|
17
|
-
----------
|
18
|
-
| Client |
|
19
|
-
----------
|
20
|
-
|
|
21
|
-
--------------
|
22
|
-
| Job Server |
|
23
|
-
--------------
|
24
|
-
|
|
25
|
-
----------------------------------------------
|
26
|
-
| | | |
|
27
|
-
---------- ---------- ---------- ----------
|
28
|
-
| Worker | | Worker | | Worker | | Worker |
|
29
|
-
---------- ---------- ---------- ----------
|
30
|
-
|
31
|
-
And the behavior will be the following:
|
32
|
-
|
33
|
-
* JobServer: Acts as a message passing point.
|
34
|
-
* Client: Sends tasks to the JobServer. Will be connected to only one JobServer
|
35
|
-
in case more than one exits for failover purposes.
|
36
|
-
* Worker: Anounce his 'abilities' to the JobServer and waits for tasks.
|
37
|
-
|
38
|
-
For the JobServer we recommend to use the offical Perl version, there's also a
|
39
|
-
more performant C implementation of the server with support for persistent
|
40
|
-
queues, bells and whistles but is not stable enough for production use at the
|
41
|
-
time of this document was wrote.
|
42
|
-
|
43
|
-
The Client and the Worker can be implemented in any language. This way you can
|
44
|
-
send tasks from a Ruby client server, to a Perl or C worker in order to get
|
45
|
-
better performance.
|
46
|
-
|
47
|
-
== Installing the required software
|
48
|
-
|
49
|
-
For the JobServer we recommend to use the offical Perl version, to install it:
|
50
|
-
|
51
|
-
* Mac OS X: sudo port install p5-gearman-server
|
52
|
-
* Debian/Ubuntu: sudo apt-get install gearman-server
|
53
|
-
|
54
|
-
To get the Ruby libraries by Xing:
|
55
|
-
|
56
|
-
git clone git://github.com/xing/gearman-ruby.git
|
57
|
-
|
58
|
-
== Gearman demo
|
59
|
-
|
60
|
-
Now you're ready for you first experience with Gearman. In the cloned repository
|
61
|
-
you'll find an 'examples' directory.
|
62
|
-
|
63
|
-
Run the 'gearman_environment.sh' to build an environment like the one showed in
|
64
|
-
the diagram above.
|
65
|
-
|
66
|
-
* Client: Will ask you for an arithmetic operation, like: 2+3
|
67
|
-
The code of the client is in: 'examples/calculus_client.rb'
|
68
|
-
|
69
|
-
* JobServer: The Perl server.
|
70
|
-
|
71
|
-
* Workers: You'll have 4 worker, one for each of the basic arithmetic
|
72
|
-
operations.
|
73
|
-
The code of the worker is in: 'examples/calculus_worker.rb'
|
74
|
-
|
75
|
-
There are other demos in the examples folder you can give a look at. Each demo usually
|
76
|
-
consist in the client and server scripts.
|
77
|
-
|
78
|
-
=== Creating clients and tasks
|
79
|
-
|
80
|
-
In order to get a job scheduled by a Gearman server using the gearman ruby library, there
|
81
|
-
are three main objects you must interact with: Gearman::Client, Gearman::Task and Gearman::TaskSet.
|
82
|
-
Let's review all of them briefly:
|
83
|
-
|
84
|
-
- Gearman::Client -> the portion of the library storing the data about the connection to
|
85
|
-
the Gearman server.
|
86
|
-
- Gearman::Task -> a job execution request that will be dispatched by the Gearman server to
|
87
|
-
worker and whose result data will be returned to the client.
|
88
|
-
- Gearman::TaskSet -> a collection of tasks to be executed. The Taskset object will track the
|
89
|
-
execution of the tasks with the info returned from the Gearman server
|
90
|
-
and notify the client with the results or errors when all the tasks
|
91
|
-
have completed their execution.
|
92
|
-
|
93
|
-
To send a new task to the Gearman server, the client must build a new Gearman::Task object, add it to
|
94
|
-
a Gearman::TaskSet that must hold a reference to a Gearman::Client and send the wait message to
|
95
|
-
the TaskSet.
|
96
|
-
The following code taken from examples/client.rb shows the process:
|
97
|
-
|
98
|
-
----------------------------------------------------
|
99
|
-
servers = ['localhost:4730', 'localhost:4731']
|
100
|
-
|
101
|
-
client = Gearman::Client.new(servers)
|
102
|
-
taskset = Gearman::TaskSet.new(client)
|
103
|
-
|
104
|
-
task = Gearman::Task.new('sleep', 20)
|
105
|
-
task.on_complete {|d| puts d }
|
106
|
-
|
107
|
-
taskset.add_task(task)
|
108
|
-
taskset.wait(100)
|
109
|
-
----------------------------------------------------
|
110
|
-
|
111
|
-
The name of the function to be executed is the first parameter to the constructor of the Task object.
|
112
|
-
Take into account that the string you pass as a parameter will be used 'as it' by the Gearman server
|
113
|
-
to locate a suitable worker for that function.
|
114
|
-
The second parameter is the argument to be sent to the worker that will execute, if the arguments for
|
115
|
-
the task are complex, a serialization format like YAML or XML must be agreeded with the workers.
|
116
|
-
The last and optional parameter is a hash of options. The following options are currently available:
|
117
|
-
|
118
|
-
- :priority -> (:high | :low) the priority of the job, a high priority job is executed before a low on
|
119
|
-
- :background -> (true | false) a background task will return no further information to the client.
|
120
|
-
|
121
|
-
The execution of a task in a Gearman remote worker can fail, the worker can throw an exception, etc.
|
122
|
-
All these events can be handled by the client of the ruby library registering callback blocks.
|
123
|
-
The following events are currently available:
|
124
|
-
|
125
|
-
- on_complete -> the task was executed succesfully
|
126
|
-
- on_fail -> the task fail for some unknown reason
|
127
|
-
- on_retry -> after failure, the task is gonna be retried, the number of retries is passed
|
128
|
-
- on_exception -> the remote worker send an exception notification, the exception text is passed
|
129
|
-
- on_stauts -> a status update is sent by the remote worker
|
130
|
-
|
131
|
-
In order to receive exception notifications in the client, this option must be sent in the server, the
|
132
|
-
method option_request can be used this task. The following example, extracted from the examples/client_exception.rb
|
133
|
-
demo script shows the process:
|
134
|
-
|
135
|
-
----------------------------------------------------
|
136
|
-
client = Gearman::Client.new(servers)
|
137
|
-
#try this out
|
138
|
-
client.option_request("exceptions")
|
139
|
-
----------------------------------------------------
|
140
|
-
|
141
|
-
This feature will only works if the server and workers have implemented support for the OPT_REQ and WORK_EXCEPTION
|
142
|
-
messages of the Gearman protocol.
|
143
|
-
|
144
|
-
|
145
|
-
Enjoy.
|
146
|
-
|