gearman-ruby 3.0.8 → 4.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![Travis CI Build Status](https://travis-ci.org/johnewart/gearman-ruby.svg)
|
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
|