gearman-ruby 2.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/Rakefile +5 -6
  2. data/VERSION.yml +2 -2
  3. data/examples/calculus_client.rb +8 -10
  4. data/examples/calculus_worker.rb +4 -1
  5. data/examples/client.php +23 -0
  6. data/examples/client.rb +6 -10
  7. data/examples/client_background.rb +7 -7
  8. data/examples/client_data.rb +4 -4
  9. data/examples/client_epoch.rb +23 -0
  10. data/examples/client_exception.rb +4 -2
  11. data/examples/client_prefix.rb +4 -2
  12. data/examples/client_reverse.rb +27 -0
  13. data/examples/scale_image.rb +4 -3
  14. data/examples/scale_image_worker.rb +1 -1
  15. data/examples/worker.rb +2 -4
  16. data/examples/worker_data.rb +2 -2
  17. data/examples/worker_exception.rb +1 -1
  18. data/examples/worker_prefix.rb +1 -1
  19. data/examples/worker_reverse_string.rb +27 -0
  20. data/examples/worker_reverse_to_file.rb +18 -0
  21. data/examples/{evented_worker.rb → worker_signals.rb} +18 -8
  22. data/lib/gearman.rb +68 -21
  23. data/lib/gearman/client.rb +137 -65
  24. data/lib/gearman/server.rb +4 -4
  25. data/lib/gearman/task.rb +140 -20
  26. data/lib/gearman/taskset.rb +280 -5
  27. data/lib/gearman/testlib.rb +95 -0
  28. data/lib/gearman/util.rb +184 -28
  29. data/lib/gearman/worker.rb +356 -20
  30. data/test/client_test.rb +145 -0
  31. data/test/mock_client_test.rb +629 -0
  32. data/test/mock_worker_test.rb +321 -0
  33. data/test/util_test.rb +8 -3
  34. data/test/worker_test.rb +50 -34
  35. metadata +41 -41
  36. data/examples/client_echo.rb +0 -16
  37. data/examples/evented_client.rb +0 -23
  38. data/examples/worker_echo.rb +0 -20
  39. data/examples/worker_echo_pprof.rb +0 -5
  40. data/gearman-ruby.gemspec +0 -111
  41. data/lib/gearman/evented/client.rb +0 -99
  42. data/lib/gearman/evented/reactor.rb +0 -86
  43. data/lib/gearman/evented/worker.rb +0 -118
  44. data/lib/gearman/job.rb +0 -38
  45. data/lib/gearman/protocol.rb +0 -110
  46. data/test/basic_integration_test.rb +0 -121
  47. data/test/crash_test.rb +0 -69
  48. data/test/job_test.rb +0 -30
  49. data/test/protocol_test.rb +0 -132
  50. data/test/test_helper.rb +0 -31
data/lib/gearman/job.rb DELETED
@@ -1,38 +0,0 @@
1
- module Gearman
2
- # = Job
3
- #
4
- # == Description
5
- # Interface to allow a worker to report information to a job server.
6
- class Job
7
- ##
8
- # Create a new Job.
9
- #
10
- # @param sock Socket connected to job server
11
- # @param handle job server-supplied job handle
12
- def initialize(client, handle)
13
- @client = client
14
- @handle = handle
15
- end
16
- ##
17
- # Report our status to the job server.
18
- def report_status(numerator, denominator)
19
- @client.send :work_status, "#{@handle}\0#{numerator}\0#{denominator}"
20
- self
21
- end
22
-
23
- ##
24
- # Send data before job completes
25
- def send_partial(data)
26
- @client.send :work_data, "#{@handle}\0#{data}"
27
- self
28
- end
29
- alias :send_data :send_partial
30
-
31
- ##
32
- # Send a warning explicitly
33
- def report_warning(warning)
34
- @client.send :work_warning, "#{@handle}\0#{warning}"
35
- self
36
- end
37
- end
38
- end
@@ -1,110 +0,0 @@
1
- module Gearman
2
-
3
- class ProtocolError < Exception; end
4
-
5
-
6
- class Protocol
7
- # Map from Integer representations of commands used in the network
8
- # protocol to more-convenient symbols.
9
- COMMANDS = {
10
- 1 => :can_do, # W->J: FUNC
11
- 2 => :cant_do, # W->J: FUNC
12
- 3 => :reset_abilities, # W->J: --
13
- 4 => :pre_sleep, # W->J: --
14
- #5 => (unused), # - -
15
- 6 => :noop, # J->W: --
16
- 7 => :submit_job, # C->J: FUNC[0]UNIQ[0]ARGS
17
- 8 => :job_created, # J->C: HANDLE
18
- 9 => :grab_job, # W->J: --
19
- 10 => :no_job, # J->W: --
20
- 11 => :job_assign, # J->W: HANDLE[0]FUNC[0]ARG
21
- 12 => :work_status, # W->J/C: HANDLE[0]NUMERATOR[0]DENOMINATOR
22
- 13 => :work_complete, # W->J/C: HANDLE[0]RES
23
- 14 => :work_fail, # W->J/C: HANDLE
24
- 15 => :get_status, # C->J: HANDLE
25
- 16 => :echo_req, # ?->J: TEXT
26
- 17 => :echo_res, # J->?: TEXT
27
- 18 => :submit_job_bg, # C->J: FUNC[0]UNIQ[0]ARGS
28
- 19 => :error, # J->?: ERRCODE[0]ERR_TEXT
29
- 20 => :status_res, # C->J: HANDLE[0]KNOWN[0]RUNNING[0]NUM[0]DENOM
30
- 21 => :submit_job_high, # C->J: FUNC[0]UNIQ[0]ARGS
31
- 22 => :set_client_id, # W->J: [RANDOM_STRING_NO_WHITESPACE]
32
- 23 => :can_do_timeout, # W->J: FUNC[0]TIMEOUT
33
- 24 => :all_yours, # REQ Worker
34
- 25 => :work_exception, # W->J: HANDLE[0]ARG
35
- 26 => :option_req, # C->J: TEXT
36
- 27 => :option_res, # J->C: TEXT
37
- 28 => :work_data, # REQ Worker
38
- 29 => :work_warning, # W->J/C: HANDLE[0]MSG
39
- 30 => :grab_job_uniq, # REQ Worker
40
- 31 => :job_assign_uniq, # RES Worker
41
- 32 => :submit_job_high_bg, # C->J: FUNC[0]UNIQ[0]ARGS
42
- 33 => :submit_job_low, # C->J: FUNC[0]UNIQ[0]ARGS
43
- 34 => :submit_job_low_bg, # C->J: FUNC[0]UNIQ[0]ARGS
44
- 35 => :submit_job_sched, # REQ Client
45
- 36 => :submit_job_epoch # REQ Client
46
- }
47
-
48
- # Map e.g. 'can_do' => 1
49
- COMMANDS_NUMERIC = COMMANDS.invert
50
-
51
- # Default job server port.
52
- DEFAULT_PORT = 4730
53
-
54
- class << self
55
-
56
- def encode_request(type_name, arg = nil)
57
- type_num = COMMANDS_NUMERIC[type_name.to_sym]
58
- raise InvalidArgsError, "Invalid type name '#{type_name}'" unless type_num
59
- arg = '' if not arg
60
- "\0REQ" + [type_num, arg.size].pack('NN') + arg
61
- end
62
-
63
- def decode_response(data, packets = [])
64
- # p data
65
- magic, type, len = data[0..12].unpack('a4NN')
66
- raise ProtocolError, "Invalid magic '#{magic}'" unless magic == "\0RES"
67
- type = COMMANDS[type]
68
- raise ProtocolError, "Invalid packet type #{type}" unless type
69
-
70
- buf, *more = data[12, data.size].split("\0RES")
71
- handle, data = buf ? buf.split("\0", 2) : nil
72
- packets << response_packet(type, handle, data)
73
- more.each do |packet|
74
- decode_response("\0RES#{packet}", packets)
75
- end
76
- packets
77
- end
78
-
79
- def response_packet(type, handle, data)
80
- case type
81
- when :work_complete,
82
- :work_exception,
83
- :work_warning,
84
- :work_data,
85
- :error
86
- [type, handle, data]
87
- when :job_assign
88
- func, data = data.split("\0", 3)
89
- [type, handle, func.to_s, data]
90
- when :job_assign_uniq
91
- func, uuid, data = data.split("\0", 3)
92
- [type, handle, func.to_s, data, uuid]
93
- when :work_fail,
94
- :job_created,
95
- :no_job,
96
- :noop
97
- [type, handle]
98
- when :work_status
99
- num, den = data.split("\0", 3)
100
- [type, handle, num, den]
101
- when :status_res
102
- known, running, num, den = data.split("\0", 4)
103
- [type, handle, known, running, num, den]
104
- else
105
- raise ProtocolError, "Invalid packet #{type}"
106
- end
107
- end
108
- end
109
- end
110
- end
@@ -1,121 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
-
3
- class BasicIntegrationTest < Test::Unit::TestCase
4
-
5
- def setup
6
- start_gearmand
7
- @client = Gearman::Client.new("localhost:4730")
8
- @worker = Gearman::Worker.new("localhost:4730")
9
- Thread.new { EM.run } unless EM.reactor_running?
10
- end
11
-
12
- def teardown
13
- stop_gearmand
14
- end
15
-
16
- def test_ping_job
17
- response = nil
18
-
19
- @worker.add_ability("pingpong") {|data, job| "pong" }
20
- @worker.work
21
-
22
- task = Gearman::Task.new("pingpong", "ping")
23
-
24
- task.on_complete {|res| response = res }
25
- @client.run task
26
-
27
- assert_equal "pong", response
28
- end
29
-
30
- def test_exception_in_worker
31
- warning_given = nil
32
- failed = false
33
-
34
- task = Gearman::Task.new("crash", "doesntmatter")
35
-
36
- @worker.add_ability("crash") {|data, job| raise Exception.new("BOOM!") }
37
- @worker.work
38
-
39
- task.on_warning {|warning| warning_given = warning }
40
- task.on_fail { failed = true}
41
- @client.run task
42
-
43
- assert_not_nil warning_given
44
- assert_equal true, failed
45
- assert_equal 0, task.retries_done
46
- end
47
-
48
- def test_should_be_able_to_retry_on_worker_exception
49
- retry_callback_called = false
50
- fail_count = 0
51
-
52
- # Gearman::Util.debug = true
53
- task = Gearman::Task.new("crash", "doesntmatter", :retries => 1)
54
-
55
- @worker.add_ability("crash") {|data, job| raise Exception.new("BOOM!") }
56
- @worker.work
57
-
58
- task.on_retry {|i| retry_callback_called = true }
59
- task.on_fail { fail_count += 1 }
60
- @client.run task
61
-
62
- assert_equal true, retry_callback_called
63
- assert_equal 1, task.retries_done
64
- assert_equal 1, fail_count
65
- end
66
-
67
- def test_chunked_response
68
- chunks_received = 0
69
-
70
- @worker.add_ability("chunked") do |data, job|
71
- 5.times {|i| job.send_partial("chunk #{i}") }
72
- end
73
- @worker.work
74
-
75
- task = Gearman::Task.new("chunked")
76
- task.on_data do |data|
77
- assert_match /^chunk \d/, data
78
- chunks_received += 1
79
- end
80
- @client.run task
81
-
82
- assert_equal 5, chunks_received
83
- end
84
-
85
- def test_background
86
- status_received = false
87
-
88
- @worker.add_ability("fireandforget") {|data, job| "this goes to /dev/null" }
89
- @worker.work
90
-
91
- task = Gearman::Task.new('fireandforget', 'background', :background => true, :poll_status_interval => 0.1)
92
- task.on_complete {|d| flunk "on_complete should never be called for a background job!" }
93
- task.on_status {|d| status_received = true }
94
- @client.run task
95
-
96
- assert_equal true, status_received
97
- end
98
-
99
- def test_non_blocking_run
100
- @worker.add_ability("foo") {|data, job| "foo: #{data}" }
101
- @worker.work
102
-
103
- task1_complete = false
104
- task2_complete = false
105
-
106
- task1 = Gearman::Task.new("foo", 1)
107
- task1.on_complete {|d| task1_complete = true}
108
- @client.run task1, nil, true
109
-
110
- assert_equal false, task1_complete
111
-
112
- task2 = Gearman::Task.new("foo", 2)
113
- task2.on_complete {|d| task2_complete = true}
114
- @client.run task2, nil, true
115
-
116
- Thread.new { sleep 0.1 }.join
117
-
118
- assert_equal true, task1_complete
119
- assert_equal true, task2_complete
120
- end
121
- end
data/test/crash_test.rb DELETED
@@ -1,69 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
-
3
- # Gearman::Util.debug = true
4
- class CrashTest < Test::Unit::TestCase
5
-
6
- def setup
7
- teardown_gearmands
8
- Thread.new { EM.run } unless EM.reactor_running?
9
- end
10
-
11
- def teardown
12
- teardown_gearmands
13
- end
14
-
15
- def test_worker_should_reconnect_if_gearmand_goes_away
16
- start_gearmand
17
- worker = Gearman::Worker.new("localhost:4730", :reconnect_sec => 1)
18
- worker.add_ability("foo") {|data, job| "noop!" }
19
-
20
- response = nil
21
-
22
- worker.work
23
- stop_gearmand
24
- start_gearmand
25
-
26
- task = Gearman::Task.new("foo", "ping")
27
- task.on_complete {|res| response = res }
28
- Gearman::Client.new("localhost:4730").run task
29
-
30
- assert_equal "noop!", response
31
- stop_gearmand
32
- end
33
-
34
- def test_client_and_worker_should_use_failover_gearmand_if_primary_is_not_available
35
- start_gearmand 4731
36
-
37
- worker = Gearman::Worker.new(["localhost:4730", "localhost:4731"], :reconnect_sec => 1)
38
- worker.add_ability("foo") {|data, job| "noop!" }
39
-
40
- response = nil
41
- worker.work
42
- task = Gearman::Task.new("foo", "ping")
43
- task.on_complete {|res| response = res }
44
- Gearman::Client.new(["localhost:4730", "localhost:4731"]).run task
45
-
46
- assert_equal "noop!", response
47
- stop_gearmand 4731
48
- end
49
-
50
- def test_client_and_worker_should_switch_to_failover_gearmand_if_primary_goes_down
51
- start_gearmand 4730
52
- start_gearmand 4731
53
-
54
- worker = Gearman::Worker.new(["localhost:4730", "localhost:4731"], :reconnect_sec => 1)
55
- worker.add_ability("foo") {|data, job| "noop!" }
56
-
57
- response = nil
58
- worker.work
59
-
60
- stop_gearmand 4730
61
-
62
- task = Gearman::Task.new("foo", "ping")
63
- task.on_complete {|res| response = res }
64
- Gearman::Client.new(["localhost:4730", "localhost:4731"]).run task
65
-
66
- assert_equal "noop!", response
67
- stop_gearmand 4731
68
- end
69
- end
data/test/job_test.rb DELETED
@@ -1,30 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
-
3
- class JobTest < Test::Unit::TestCase
4
-
5
- def setup
6
- @handle = "H:foo:1"
7
- @mock_client = mock()
8
- @job = Gearman::Job.new(@mock_client, @handle)
9
- end
10
-
11
- def test_supports_report_status
12
- @mock_client.expects(:send).with(:work_status, [@handle, 1, 5].join("\0"))
13
- @job.report_status(1, 5)
14
- end
15
-
16
- def test_supports_send_partial
17
- @mock_client.expects(:send).with(:work_data, [@handle, "bar"].join("\0"))
18
- @job.send_partial("bar")
19
- end
20
-
21
- def test_supports_send_data
22
- @mock_client.expects(:send).with(:work_data, [@handle, "bar"].join("\0"))
23
- @job.send_data("bar")
24
- end
25
-
26
- def test_supports_report_warning
27
- @mock_client.expects(:send).with(:work_warning, [@handle, "danger"].join("\0"))
28
- @job.report_warning("danger")
29
- end
30
- end
@@ -1,132 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
-
3
- class ProtocolTest < Test::Unit::TestCase
4
-
5
- def test_encode_request
6
- payload = ["foo", "123", "bar"].join("\0")
7
- expected = "\0REQ" + [Gearman::Protocol::COMMANDS_NUMERIC[:submit_job], payload.size].pack("NN") + payload
8
- assert_equal expected, Gearman::Protocol.encode_request(:submit_job, payload)
9
- end
10
-
11
- def test_decode_response
12
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:work_data], 3].pack("NN") + handle + "\0foo"
13
- packets = Gearman::Protocol.decode_response(response)
14
- assert_equal 1, packets.size
15
- assert_equal [:work_data, "H:wrk.acme:1", "foo"], packets.first
16
- end
17
-
18
- def test_decodes_multiple_response_packets
19
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:work_data], 3].pack("NN") + handle + "\0foo"
20
- response << "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:work_data], 3].pack("NN") + handle + "\0bar"
21
- response << "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:work_data], 3].pack("NN") + handle + "\0baz"
22
-
23
- assert_equal 3, Gearman::Protocol.decode_response(response).size
24
- end
25
-
26
- def test_response_packet
27
- packet = [:work_data, handle, "foo"]
28
- assert_equal packet, Gearman::Protocol.response_packet(*packet)
29
- end
30
-
31
- def test_decodes_work_complete
32
- data = "esta complet"
33
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:work_complete], data.size].pack("NN") + [handle, data].join("\0")
34
- assert_equal [:work_complete, handle, data], Gearman::Protocol.decode_response(response).first
35
- end
36
-
37
- def test_decodes_work_exception
38
- data = "{native perl exception object}"
39
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:work_exception], data.size].pack("NN") + [handle, data].join("\0")
40
- assert_equal [:work_exception, handle, data], Gearman::Protocol.decode_response(response).first
41
- end
42
-
43
- def test_decodes_work_warning
44
- data = "I warn you, dude"
45
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:work_warning], data.size].pack("NN") + [handle, data].join("\0")
46
- assert_equal [:work_warning, handle, data], Gearman::Protocol.decode_response(response).first
47
- end
48
-
49
- def test_decodes_work_data
50
- data = "foo"
51
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:work_data], data.size].pack("NN") + [handle, data].join("\0")
52
- assert_equal [:work_data, handle, data], Gearman::Protocol.decode_response(response).first
53
- end
54
-
55
- def test_decodes_error
56
- data = "error"
57
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:error], data.size].pack("NN") + [handle, data].join("\0")
58
- assert_equal [:error, handle, data], Gearman::Protocol.decode_response(response).first
59
- end
60
-
61
- def test_decodes_job_assign
62
- function = "foo_function"
63
- arguments = "arguments"
64
-
65
- payload = [handle, function, arguments].join("\0")
66
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:job_assign], payload.size].pack("NN") + payload
67
- assert_equal [:job_assign, handle, function, arguments], Gearman::Protocol.decode_response(response).first
68
- end
69
-
70
- def test_decodes_job_assign_uniq
71
- function = "foo_function"
72
- arguments = "arguments"
73
- unique_id = "123-657"
74
-
75
- payload = [handle, function, unique_id, arguments].join("\0")
76
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:job_assign_uniq], payload.size].pack("NN") + payload
77
- assert_equal [:job_assign_uniq, handle, function, arguments, unique_id], Gearman::Protocol.decode_response(response).first
78
- end
79
-
80
- def test_decodes_work_fail
81
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:work_fail], 0].pack("NN") + handle
82
- assert_equal [:work_fail, handle], Gearman::Protocol.decode_response(response).first
83
- end
84
-
85
- def test_decodes_job_created
86
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:job_created], 0].pack("NN") + handle
87
- assert_equal [:job_created, handle], Gearman::Protocol.decode_response(response).first
88
- end
89
-
90
- def test_decodes_no_job
91
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:no_job], 0].pack("NN") + handle
92
- assert_equal [:no_job, handle], Gearman::Protocol.decode_response(response).first
93
- end
94
-
95
- def test_decodes_noop
96
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:noop], 0].pack("NN") + handle
97
- assert_equal [:noop, handle], Gearman::Protocol.decode_response(response).first
98
- end
99
-
100
- def test_decodes_work_status
101
- numerator = "1"
102
- denominator = "5"
103
-
104
- payload = [handle, numerator, denominator].join("\0")
105
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:work_status], payload.size].pack("NN") + payload
106
-
107
- assert_equal [:work_status, handle, numerator, denominator], Gearman::Protocol.decode_response(response).first
108
- end
109
-
110
- def test_decodes_status_res
111
- known = "1"
112
- running = "0"
113
- numerator = "1"
114
- denominator = "4"
115
-
116
- payload = [handle, known, running, numerator, denominator].join("\0")
117
- response = "\0RES" + [Gearman::Protocol::COMMANDS_NUMERIC[:status_res], payload.size].pack("NN") + payload
118
-
119
- assert_equal [:status_res, handle, known, running, numerator, denominator], Gearman::Protocol.decode_response(response).first
120
- end
121
-
122
- def test_raises_on_invalid_command
123
- response = "\0RES" + [6969, 0].pack("NN")
124
- assert_raises(Gearman::ProtocolError) { Gearman::Protocol.decode_response(response) }
125
- assert_raises(Gearman::ProtocolError) { Gearman::Protocol.response_packet(*[6969, handle, ''])}
126
- end
127
-
128
- private
129
- def handle
130
- "H:wrk.acme:1"
131
- end
132
- end