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
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZWIzNDljYTkyOTdjY2ZlMmJmYzMzNTIwMTlmOTdkMmQwZGE1MGViNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ODc1MGU0ZjM2OWQ4ZmYxZjlmYTNkOTNhZjk1OGEyZDlkNDRhYjYzZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YThkMjM1NGY4NGRlM2M4MGE0ODg5YzRiZDJlYWZkNzU2YmViNDlkZjhmZDk3
|
10
|
+
NjQ5MWE4YmNmOTJlNzM2OGI5ODI2NzBjNTAxZTRhNGY1MWU5ZWM4NTA4MDQy
|
11
|
+
MjI2MTk3YzNkZWNlNzkzZjFlMjAzOWIxZmZiNGY4MDYwNGI3ZTE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MmE3MmU0OTVkNDljMGEwODg2YWQ4OGQ1MjI3YWVhZWEyMDZlZjliYzIzYTk2
|
14
|
+
ZGUxNjkzZjgwNDRlMWY5OTAwMTM5NzI0NThiYmFhM2NkOWQ3YmUzODhhYzY2
|
15
|
+
NWZkODg5YjgzMzEyMDNhY2QwYzAxZTM3MmNhMTk1OWNkODMzOTM=
|
data/.travis.yml
ADDED
data/CHANGELOG.md
CHANGED
data/README.md
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
# gearman-ruby
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
## What is this?
|
6
|
+
|
7
|
+
This is a pure-Ruby library for the [gearman][Gearman] distributed job system.
|
8
|
+
|
9
|
+
## What needs to be done?
|
10
|
+
|
11
|
+
More testing, some code cleanup.
|
12
|
+
|
13
|
+
## What's in this?
|
14
|
+
|
15
|
+
Right now, this library has both client and worker support for Ruby apps.
|
16
|
+
|
17
|
+
## Getting Started
|
18
|
+
|
19
|
+
### Client
|
20
|
+
|
21
|
+
A very simple client that submits a "sleep" job and waits for 100 seconds for results:
|
22
|
+
|
23
|
+
``` ruby
|
24
|
+
require 'rubygems'
|
25
|
+
require 'gearman'
|
26
|
+
|
27
|
+
servers = ['localhost:4730', 'localhost:4731']
|
28
|
+
|
29
|
+
client = Gearman::Client.new(servers)
|
30
|
+
taskset = Gearman::TaskSet.new(client)
|
31
|
+
|
32
|
+
task = Gearman::Task.new('sleep', 20)
|
33
|
+
task.on_complete {|d| puts d }
|
34
|
+
|
35
|
+
taskset.add_task(task)
|
36
|
+
taskset.wait(100)
|
37
|
+
```
|
38
|
+
|
39
|
+
### Worker
|
40
|
+
|
41
|
+
A worker that will process jobs in the 'sleep' queue:
|
42
|
+
|
43
|
+
``` ruby
|
44
|
+
require 'rubygems'
|
45
|
+
require 'logger'
|
46
|
+
require 'gearman'
|
47
|
+
|
48
|
+
servers = ['localhost:4730']
|
49
|
+
|
50
|
+
w = Gearman::Worker.new(servers)
|
51
|
+
logger = Logger.new(STDOUT)
|
52
|
+
|
53
|
+
# Add a handler for a "sleep" function that takes a single argument, the
|
54
|
+
# number of seconds to sleep before reporting success.
|
55
|
+
w.add_ability("sleep") do |data,job|
|
56
|
+
seconds = 10
|
57
|
+
logger.info "Sleeping for #{seconds} seconds"
|
58
|
+
(1..seconds.to_i).each do |i|
|
59
|
+
sleep 1
|
60
|
+
# Report our progress to the job server every second.
|
61
|
+
job.report_status(i, seconds)
|
62
|
+
end
|
63
|
+
# Report success.
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
loop { w.work }
|
68
|
+
```
|
69
|
+
|
70
|
+
[gearman]: http://gearman.org
|
71
|
+
|
72
|
+
## Authors
|
73
|
+
|
74
|
+
* John Ewart <john@johnewart.net> (current maintainer, author of re-write)
|
75
|
+
|
76
|
+
<<<<<<< HEAD
|
77
|
+
## Contributors (past and present)
|
78
|
+
|
79
|
+
* Kim Altintop
|
80
|
+
=======
|
81
|
+
## Contributors
|
82
|
+
|
83
|
+
>>>>>>> New version (4.0) -- substantial rewrite
|
84
|
+
* Josh Black (raskchanky)
|
85
|
+
* Colin Curtin (perplexes)
|
86
|
+
* Brian Cobb (bcobb)
|
87
|
+
* Pablo A. Delgado (pablete)
|
88
|
+
<<<<<<< HEAD
|
89
|
+
* Daniel Erat
|
90
|
+
* Antonio Garrote
|
91
|
+
* Stefan Kaes (skaes)
|
92
|
+
* Ladislav Martincik
|
93
|
+
=======
|
94
|
+
* Stefan Kaes (skaes)
|
95
|
+
>>>>>>> New version (4.0) -- substantial rewrite
|
96
|
+
* Mauro Pompilio (malditogeek)
|
97
|
+
* Lee Reilly (leereilly)
|
98
|
+
* Clint Shryock (catsby)
|
99
|
+
* Andy Triggs (andyt)
|
100
|
+
|
101
|
+
|
102
|
+
<<<<<<< HEAD
|
103
|
+
|
104
|
+
## License
|
105
|
+
|
106
|
+
Released under the MIT license, originally developed by XING AG. See the LICENSE file for further details.
|
107
|
+
=======
|
108
|
+
## License
|
109
|
+
|
110
|
+
Released under the MIT license. See the file LICENSE for further details.
|
111
|
+
>>>>>>> New version (4.0) -- substantial rewrite
|
data/examples/client.rb
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require '../lib/gearman'
|
4
|
+
l = Logger.new($stdout)
|
5
|
+
l.level = Logger::DEBUG
|
6
|
+
Gearman::Util.logger=l
|
7
|
+
|
8
|
+
# Client using Gearman SUBMIT_JOB_EPOCH (currently requires the gearmand branch lp:~jewart/gearmand/scheduled_jobs_support/)
|
9
|
+
|
10
|
+
t = nil
|
11
|
+
threadcounter = 0
|
12
|
+
|
13
|
+
client = Gearman::Client.new('192.168.1.1:4730')
|
14
|
+
|
15
|
+
|
16
|
+
myid = threadcounter
|
17
|
+
threadcounter += 1
|
18
|
+
taskset = Gearman::TaskSet.new(client)
|
19
|
+
|
20
|
+
(1..1000).each do |jid|
|
21
|
+
data = rand(36**8).to_s(36)
|
22
|
+
result = data.reverse
|
23
|
+
|
24
|
+
task = Gearman::BackgroundTask.new("reverse_string", data)
|
25
|
+
puts "#{jid} #{data}"
|
26
|
+
|
27
|
+
#time = Time.now() + rand(120) + 10
|
28
|
+
#task.schedule(time)
|
29
|
+
taskset.add_task(task)
|
30
|
+
end
|
@@ -1,27 +1,25 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require '
|
2
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', "lib" )
|
3
|
+
require 'gearman'
|
4
4
|
|
5
5
|
# Client using Gearman SUBMIT_JOB_EPOCH (currently requires the gearmand branch lp:~jewart/gearmand/scheduled_jobs_support/)
|
6
6
|
|
7
7
|
t = nil
|
8
8
|
threadcounter = 0
|
9
9
|
|
10
|
-
client = Gearman::Client.new('localhost')
|
10
|
+
client = Gearman::Client.new('localhost:4730')
|
11
11
|
|
12
12
|
|
13
13
|
myid = threadcounter
|
14
14
|
threadcounter += 1
|
15
15
|
taskset = Gearman::TaskSet.new(client)
|
16
16
|
|
17
|
-
(1..
|
17
|
+
(1..100).each do |jid|
|
18
18
|
data = rand(36**8).to_s(36)
|
19
|
-
result = data.reverse
|
20
|
-
|
21
|
-
task = Gearman::Task.new("reverse_string", data)
|
22
19
|
puts "#{jid} #{data}"
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
taskset.add_task(task)
|
20
|
+
task = Gearman::Task.new("reverse_string", data)
|
21
|
+
task.on_complete {|d| puts d }
|
22
|
+
client.do_task(task)
|
27
23
|
end
|
24
|
+
|
25
|
+
|
data/examples/worker.rb
CHANGED
@@ -1,21 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift("../lib")
|
1
2
|
require 'rubygems'
|
2
|
-
|
3
|
+
require 'logger'
|
3
4
|
require '../lib/gearman'
|
5
|
+
servers = ['localhost:4730']
|
4
6
|
|
5
|
-
servers = ['localhost:4730',]
|
6
7
|
w = Gearman::Worker.new(servers)
|
8
|
+
logger = Logger.new(STDOUT)
|
7
9
|
|
8
10
|
# Add a handler for a "sleep" function that takes a single argument, the
|
9
11
|
# number of seconds to sleep before reporting success.
|
10
|
-
w.add_ability(
|
11
|
-
seconds =
|
12
|
+
w.add_ability("sleep") do |data,job|
|
13
|
+
seconds = 10
|
14
|
+
logger.info "Sleeping for #{seconds} seconds"
|
12
15
|
(1..seconds.to_i).each do |i|
|
13
16
|
sleep 1
|
14
|
-
print i
|
15
17
|
# Report our progress to the job server every second.
|
16
18
|
job.report_status(i, seconds)
|
17
19
|
end
|
18
20
|
# Report success.
|
19
21
|
true
|
20
22
|
end
|
23
|
+
|
21
24
|
loop { w.work }
|
@@ -1,27 +1,22 @@
|
|
1
|
-
|
2
|
-
require '
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', "lib" )
|
2
|
+
require 'gearman'
|
3
3
|
|
4
4
|
# String reverse worker
|
5
5
|
|
6
|
-
servers = ['
|
6
|
+
servers = ['127.0.0.1:4730']
|
7
7
|
|
8
8
|
t = nil
|
9
9
|
jobnum = 0
|
10
10
|
|
11
|
-
(
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
jobnum += 1
|
19
|
-
result
|
20
|
-
end
|
21
|
-
loop { w.work }
|
22
|
-
}
|
11
|
+
w = Gearman::Worker.new(servers)
|
12
|
+
w.add_ability('reverse_string') do |data,job|
|
13
|
+
result = data.reverse
|
14
|
+
puts "Job: #{job.inspect} Data: #{data.inspect} Reverse: #{result} "
|
15
|
+
puts "Completed job ##{jobnum}"
|
16
|
+
jobnum += 1
|
17
|
+
result
|
23
18
|
end
|
24
19
|
|
25
|
-
|
26
|
-
|
20
|
+
loop { w.work }
|
21
|
+
|
27
22
|
|
data/gearman-ruby.gemspec
CHANGED
@@ -5,8 +5,8 @@ Gem::Specification.new do |s|
|
|
5
5
|
s.name = %q{gearman-ruby}
|
6
6
|
s.version = Gearman::VERSION
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
|
-
s.authors = ["John Ewart"
|
9
|
-
s.date = %q{
|
8
|
+
s.authors = ["John Ewart"]
|
9
|
+
s.date = %q{2014-11-29}
|
10
10
|
s.summary = %q{Ruby Gearman library}
|
11
11
|
s.description = %q{Library for the Gearman distributed job system}
|
12
12
|
s.email = %q{john@johnewart.net}
|
@@ -15,14 +15,12 @@ Gem::Specification.new do |s|
|
|
15
15
|
|
16
16
|
s.extra_rdoc_files = [
|
17
17
|
"LICENSE",
|
18
|
-
"README"
|
19
|
-
"TODO"
|
18
|
+
"README.md"
|
20
19
|
]
|
21
20
|
|
22
21
|
s.files = `git ls-files`.split("\n")
|
23
22
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
23
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
24
|
s.require_paths = ["lib"]
|
26
|
-
s.require_paths = ["lib"]
|
27
25
|
end
|
28
26
|
|
data/lib/gearman.rb
CHANGED
@@ -1,82 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# = Name
|
4
|
-
# Gearman
|
5
|
-
#
|
6
|
-
# == Description
|
7
|
-
# This file provides a Ruby interface for communicating with the Gearman
|
8
|
-
# distributed job system.
|
9
|
-
#
|
10
|
-
# "Gearman is a system to farm out work to other machines, dispatching
|
11
|
-
# function calls to machines that are better suited to do work, to do work
|
12
|
-
# in parallel, to load balance lots of function calls, or to call functions
|
13
|
-
# between languages." -- http://www.danga.com/gearman/
|
14
|
-
#
|
15
|
-
# == Version
|
16
|
-
# 0.0.1
|
17
|
-
#
|
18
|
-
# == Author
|
19
|
-
# Daniel Erat <dan-ruby@erat.org>
|
20
|
-
#
|
21
|
-
# == License
|
22
|
-
# This program is free software; you can redistribute it and/or modify it
|
23
|
-
# under the terms of either:
|
24
|
-
#
|
25
|
-
# a) the GNU General Public License as published by the Free Software
|
26
|
-
# Foundation; either version 1, or (at your option) any later version,
|
27
|
-
# or
|
28
|
-
#
|
29
|
-
# b) the "Artistic License" which comes with Perl.
|
30
2
|
|
31
|
-
|
32
|
-
#
|
33
|
-
# == Usage
|
34
|
-
# require 'gearman'
|
35
|
-
#
|
36
|
-
# # Create a new client and tell it about two job servers.
|
37
|
-
# c = Gearman::Client.new
|
38
|
-
# c.job_servers = ['127.0.0.1:7003', '127.0.0.1:7004']
|
39
|
-
#
|
40
|
-
# # Create two tasks, using an "add" function to sum two numbers.
|
41
|
-
# t1 = Gearman::Task.new('add', '5 + 2')
|
42
|
-
# t2 = Gearman::Task.new('add', '1 + 3')
|
43
|
-
#
|
44
|
-
# # Make the tasks print the data they get back from the server.
|
45
|
-
# t1.on_complete {|d| puts "t1 got #{d}" }
|
46
|
-
# t2.on_complete {|d| puts "t2 got #{d}" }
|
47
|
-
#
|
48
|
-
# # Create a taskset, add the two tasks to it, and wait until they finish.
|
49
|
-
# ts = Gearman::TaskSet.new(c)
|
50
|
-
# ts.add_task(t1)
|
51
|
-
# ts.add_task(t2)
|
52
|
-
# ts.wait
|
53
|
-
#
|
54
|
-
# Or, a more simple example:
|
55
|
-
#
|
56
|
-
# c = Gearman::Client.new('127.0.0.1')
|
57
|
-
# puts c.do_task('add', '2 + 2')
|
58
|
-
#
|
59
|
-
module Gearman
|
60
|
-
|
61
|
-
require File.dirname(__FILE__) + '/gearman/client'
|
62
|
-
require File.dirname(__FILE__) + '/gearman/task'
|
63
|
-
require File.dirname(__FILE__) + '/gearman/taskset'
|
64
|
-
require File.dirname(__FILE__) + '/gearman/util'
|
65
|
-
require File.dirname(__FILE__) + '/gearman/worker'
|
66
|
-
|
67
|
-
class InvalidArgsError < Exception
|
68
|
-
end
|
69
|
-
|
70
|
-
class ProtocolError < Exception
|
71
|
-
end
|
3
|
+
require 'logger'
|
72
4
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
5
|
+
module Gearman
|
6
|
+
class << self
|
7
|
+
attr_writer :logger
|
8
|
+
def logger
|
9
|
+
@logger ||= Logger.new(STDOUT)
|
10
|
+
end
|
11
|
+
end
|
80
12
|
end
|
81
13
|
|
82
|
-
|
14
|
+
require 'gearman/exceptions'
|
15
|
+
require 'gearman/logging'
|
16
|
+
require 'gearman/packet'
|
17
|
+
require 'gearman/connection'
|
18
|
+
require 'gearman/connection_pool'
|
19
|
+
require 'gearman/client'
|
20
|
+
require 'gearman/task'
|
21
|
+
require 'gearman/task_set'
|
22
|
+
require 'gearman/worker'
|
data/lib/gearman/client.rb
CHANGED
@@ -1,169 +1,151 @@
|
|
1
|
-
require '
|
1
|
+
require 'time'
|
2
2
|
|
3
3
|
module Gearman
|
4
|
+
class Client
|
5
|
+
include Logging
|
6
|
+
|
7
|
+
attr_accessor :task_create_timeout_sec
|
8
|
+
|
9
|
+
##
|
10
|
+
# Create a new client.
|
11
|
+
#
|
12
|
+
# @param job_servers "host:port"; either a single server or an array
|
13
|
+
def initialize(job_servers=nil)
|
14
|
+
@coalesce_connections = {} # Unique ID => Connection
|
15
|
+
@connection_pool = ConnectionPool.new(job_servers)
|
16
|
+
@current_task = nil
|
17
|
+
@task_create_timeout_sec = 10
|
18
|
+
end
|
4
19
|
|
5
|
-
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
@job_servers = [] # "host:port"
|
16
|
-
self.job_servers = job_servers if job_servers
|
17
|
-
@sockets = {} # "host:port" -> [sock1, sock2, ...]
|
18
|
-
@socket_to_hostport = {} # sock -> "host:port"
|
19
|
-
@task_create_timeout_sec = 10
|
20
|
-
@server_counter = -1
|
21
|
-
@bad_servers = []
|
22
|
-
end
|
23
|
-
attr_reader :job_servers, :bad_servers
|
24
|
-
attr_accessor :task_create_timeout_sec
|
25
|
-
|
26
|
-
##
|
27
|
-
# Set the options
|
28
|
-
#
|
29
|
-
# @options options to pass to the servers "exeptions"
|
30
|
-
def option_request(opts)
|
31
|
-
Util.logger.debug "GearmanRuby: Send options request with #{opts}"
|
32
|
-
request = Util.pack_request("option_req", opts)
|
33
|
-
sock= self.get_socket(self.get_job_server)
|
34
|
-
Util.send_request(sock, request)
|
35
|
-
response = Util.read_response(sock, 20)
|
36
|
-
raise ProtocolError, response[1] if response[0]==:error
|
37
|
-
end
|
38
|
-
|
39
|
-
##
|
40
|
-
# Set the job servers to be used by this client.
|
41
|
-
#
|
42
|
-
# @param servers "host:port"; either a single server or an array
|
43
|
-
def job_servers=(servers)
|
44
|
-
@job_servers = Util.normalize_job_servers(servers)
|
45
|
-
self
|
46
|
-
end
|
47
|
-
|
48
|
-
##
|
49
|
-
# Get connection info about an arbitrary (currently random, but maybe
|
50
|
-
# we'll do something smarter later) job server.
|
51
|
-
#
|
52
|
-
# @return "host:port"
|
53
|
-
def get_job_server
|
54
|
-
if @job_servers.empty? && !@bad_servers.empty?
|
55
|
-
Util.logger.debug "GearmanRuby: No more good job servers, trying bad ones: #{@bad_servers.inspect}."
|
56
|
-
# Try to reconnect to the bad servers
|
57
|
-
@bad_servers.each do |bad_server|
|
58
|
-
Util.logger.debug "GearmanRuby: Trying server: #{bad_server.inspect}"
|
59
|
-
begin
|
60
|
-
request = Util.pack_request("echo_req", "ping")
|
61
|
-
sock = self.get_socket(bad_server)
|
62
|
-
Util.send_request(sock, request)
|
63
|
-
response = Util.read_response(sock, 20)
|
64
|
-
if response[0] == :echo_res
|
65
|
-
@job_servers << bad_server
|
66
|
-
@bad_servers.delete bad_server
|
67
|
-
end
|
68
|
-
rescue NetworkError
|
69
|
-
Util.logger.debug "GearmanRuby: Error trying server: #{bad_server.inspect}"
|
70
|
-
end
|
20
|
+
##
|
21
|
+
# Set the options
|
22
|
+
#
|
23
|
+
# @options options to pass to the servers i.e "exceptions"
|
24
|
+
def set_options(opts)
|
25
|
+
@connection_pool.with_all_connections do |conn|
|
26
|
+
logger.debug "Send options request with #{opts}"
|
27
|
+
request = Packet.pack_request("option_req", opts)
|
28
|
+
response = conn.send_request(request)
|
29
|
+
raise ProtocolError, response[1] if response[0]==:error
|
71
30
|
end
|
72
31
|
end
|
73
32
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
@
|
78
|
-
|
33
|
+
##
|
34
|
+
# Perform a single task.
|
35
|
+
#
|
36
|
+
# @param args A Task to complete
|
37
|
+
# @return output of the task, or nil on failure
|
38
|
+
def do_task(task)
|
79
39
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
40
|
+
result = nil
|
41
|
+
failed = false
|
42
|
+
|
43
|
+
task.on_complete {|v| result = v }
|
44
|
+
task.on_fail { failed = true }
|
45
|
+
|
46
|
+
task_set = TaskSet.new(self)
|
47
|
+
if task_set.add_task(task)
|
48
|
+
task_set.wait_forever
|
49
|
+
else
|
50
|
+
raise JobQueueError, "Unable to enqueue job."
|
51
|
+
end
|
84
52
|
|
85
|
-
|
86
|
-
# Get a socket for a job server.
|
87
|
-
#
|
88
|
-
# @param hostport job server "host:port"
|
89
|
-
# @return a Socket
|
90
|
-
def get_socket(hostport, num_retries=3)
|
91
|
-
# If we already have an open socket to this host, return it.
|
92
|
-
if @sockets[hostport]
|
93
|
-
sock = @sockets[hostport].shift
|
94
|
-
@sockets.delete(hostport) if @sockets[hostport].size == 0
|
95
|
-
return sock
|
53
|
+
failed ? nil : result
|
96
54
|
end
|
97
55
|
|
98
|
-
|
56
|
+
def submit_job(task, reset_state = false, timeout = nil)
|
57
|
+
task.reset_state if reset_state
|
58
|
+
req = task.get_submit_packet()
|
59
|
+
req_timeout = timeout || task_create_timeout_sec
|
60
|
+
# Target the same job manager when submitting jobs
|
61
|
+
# with the same unique id so that we can coalesce
|
62
|
+
coalesce_key = task.get_uniq_hash
|
63
|
+
|
64
|
+
end_time = if timeout
|
65
|
+
Time.now.to_f + timeout
|
66
|
+
else
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
99
70
|
begin
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
71
|
+
|
72
|
+
connection = @connection_pool.get_connection(coalesce_key)
|
73
|
+
logger.debug "Using #{connection} to submit job"
|
74
|
+
|
75
|
+
type, data = connection.send_request(req, timeout)
|
76
|
+
logger.debug "Got #{type.to_s} from #{connection}"
|
77
|
+
|
78
|
+
if type == :job_created
|
79
|
+
|
80
|
+
task.handle_created(data)
|
81
|
+
|
82
|
+
if(!task.background)
|
83
|
+
begin
|
84
|
+
remaining = if end_time
|
85
|
+
(t = end_time - Time.now.to_f) > 0 ? t : 0
|
86
|
+
else
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
type, data = connection.read_response(remaining)
|
90
|
+
handle_response(task, type, data)
|
91
|
+
end while [:work_status, :work_data].include? type
|
92
|
+
end
|
93
|
+
|
94
|
+
else
|
95
|
+
# This shouldn't happen
|
96
|
+
message = "Received #{type.to_s} when we were expecting JOB_CREATED"
|
97
|
+
logger.error message
|
98
|
+
raise ProtocolError, message
|
99
|
+
end
|
100
|
+
rescue NetworkError
|
101
|
+
message = "Network error on read from #{hostport} while adding job, marking server bad"
|
102
|
+
logger.error message
|
103
|
+
raise NetworkError, message
|
104
|
+
rescue NoJobServersError
|
105
|
+
logger.error "No servers available."
|
106
|
+
raise NoJobServersError
|
107
107
|
end
|
108
|
+
|
109
|
+
true
|
108
110
|
end
|
109
|
-
raise NetworkError, "Unable to connect to job server #{hostport}"
|
110
|
-
end
|
111
111
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
112
|
+
def handle_response(task, type, data)
|
113
|
+
case type
|
114
|
+
when :work_complete
|
115
|
+
handle, message = data.split("\0", 2)
|
116
|
+
logger.debug("Received WORK_COMPLETE for #{handle}")
|
117
|
+
task.handle_completion(message)
|
118
|
+
when :work_exception
|
119
|
+
handle, exception = data.split("\0", 2)
|
120
|
+
logger.debug("Received WORK_EXCEPTION for #{handle}")
|
121
|
+
task.handle_exception(exception)
|
122
|
+
when :work_fail
|
123
|
+
logger.debug("Received WORK_FAIL for #{handle}")
|
124
|
+
requeue = task.handle_failure
|
125
|
+
add_task(task) if requeue
|
126
|
+
when :work_status
|
127
|
+
handle, numerator, denominator = data.split("\0", 3)
|
128
|
+
logger.debug("Received WORK_STATUS for #{handle}: #{numerator} / #{denominator}")
|
129
|
+
task.handle_status(numerator, denominator)
|
130
|
+
when :work_warning
|
131
|
+
handle, message = data.split("\0", 2)
|
132
|
+
Util.logger.debug "Got WORK_WARNING for #{handle}: '#{message}'"
|
133
|
+
task.handle_warning(message)
|
134
|
+
when :work_data
|
135
|
+
handle, work_data = data.split("\0", 2)
|
136
|
+
Util.logger.debug "Got WORK_DATA for #{handle} with #{work_data ? work_data.size : '0'} byte(s) of data"
|
137
|
+
task.handle_data(work_data)
|
138
|
+
else
|
139
|
+
# Not good.
|
140
|
+
message = "Got #{type.to_s} from #{connection} but it was not an expected type."
|
141
|
+
logger.error message
|
142
|
+
raise ProtocolError, message
|
143
|
+
end
|
125
144
|
end
|
126
|
-
(@sockets[hostport] ||= []) << sock
|
127
|
-
end
|
128
145
|
|
129
|
-
def close_socket(sock)
|
130
|
-
sock.close
|
131
|
-
@socket_to_hostport.delete(sock)
|
132
|
-
nil
|
133
146
|
end
|
134
147
|
|
135
|
-
##
|
136
|
-
# Given a socket from Client#get_socket, return its host and port.
|
137
|
-
#
|
138
|
-
# @param sock Socket
|
139
|
-
# @return "host:port", or nil if unregistered (which shouldn't happen)
|
140
|
-
def get_hostport_for_socket(sock)
|
141
|
-
@socket_to_hostport[sock]
|
142
|
-
end
|
143
148
|
|
144
|
-
##
|
145
|
-
# Perform a single task.
|
146
|
-
#
|
147
|
-
# @param args either a Task or arguments for Task.new
|
148
|
-
# @return output of the task, or nil on failure
|
149
|
-
def do_task(*args)
|
150
|
-
task = Util::get_task_from_args(*args)
|
151
|
-
|
152
|
-
result = nil
|
153
|
-
failed = false
|
154
|
-
task.on_complete {|v| result = v }
|
155
|
-
task.on_fail { failed = true }
|
156
|
-
|
157
|
-
taskset = TaskSet.new(self)
|
158
|
-
if taskset.add_task(task)
|
159
|
-
taskset.wait
|
160
|
-
else
|
161
|
-
raise JobQueueError, "Unable to enqueue job."
|
162
|
-
end
|
163
149
|
|
164
|
-
failed ? nil : result
|
165
|
-
end
|
166
150
|
|
167
151
|
end
|
168
|
-
|
169
|
-
end
|