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.
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