disque_jockey 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -0
- data/lib/disque_jockey/broker.rb +20 -4
- data/lib/disque_jockey/version.rb +1 -1
- data/lib/disque_jockey/worker.rb +8 -2
- data/lib/disque_jockey/worker_pool.rb +3 -3
- data/spec/disque_jockey/broker_spec.rb +29 -4
- data/spec/disque_jockey/worker_pool_spec.rb +15 -2
- data/spec/disque_jockey/worker_shared_setup.rb +2 -1
- data/spec/disque_jockey/worker_spec.rb +15 -7
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e595757036b4f0fa828fcb9dda551db3f211ed7e
|
4
|
+
data.tar.gz: 81687ba961860e23ffd2b877b81166b8c8f3ea31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bbd8ab91aba802d6f1c7364fe833eef0f20ee0813593cdad4fe3bb7c63c1508cf34db86f73530461283d5946c3520c472a5cfe48e0a1474c775c7b618972bd7
|
7
|
+
data.tar.gz: 4f294a19102ce434dd3c55d97425cde430680903e1241a2ef44d02c53dae2a7eecd9f8a796570d9cbba161ba0974889c2c732349ac8e5e807926f1c5d331c345
|
data/README.md
CHANGED
@@ -63,6 +63,26 @@ disque_jockey start --env=production --daemonize=true --worker-groups=10 --node
|
|
63
63
|
````
|
64
64
|
|
65
65
|
Messages successfully handled by a worker (ie no exceptions raised from the handle method) will be acknowledged and removed from the queue.
|
66
|
+
## Worker Configuration
|
67
|
+
DisqueJockey::Worker implements some class methods that help you configure your worker. You call them the same way you call the `subscribe_to` method, at the top of your class.
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
require 'disque_jockey'
|
71
|
+
class HighlyConfiguredWorker < DisqueJockey::Worker
|
72
|
+
subscribe_to 'example-queue'
|
73
|
+
threads 7
|
74
|
+
fast_ack true
|
75
|
+
timeout 5
|
76
|
+
|
77
|
+
def handle(job)
|
78
|
+
logger.info("Peforming job: #{job}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
```
|
82
|
+
- *Fast Acknowledgements*: call ````fast_ack true```` to use FASTACKs (https://github.com/antirez/disque#fast-acknowledges) in disque to acknowledge your messages. Please note that fast_ack will make it more likely you will process a job more than once in the event of a network partition. fast_ack is false by default.
|
83
|
+
- *Threads*: To devote more threads to your worker class use ````threads 5```` . Threads are set to two by default and have a maximum value of 10.
|
84
|
+
- *Timeout*: To set the number of seconds your worker will process a job until raising a TimeoutError, use ````timeout 45````. Timeout is set to 30 seconds by default and has a maximum value of 3600 seconds (one hour).
|
85
|
+
|
66
86
|
|
67
87
|
##Roadmap:
|
68
88
|
DisqueJockey is not a currently a production-ready system, and there are a number of goals for it that have not been met yet.
|
data/lib/disque_jockey/broker.rb
CHANGED
@@ -13,10 +13,26 @@ module DisqueJockey
|
|
13
13
|
|
14
14
|
def acknowledge(job_id)
|
15
15
|
response = @client.call('ACKJOB', job_id)
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
raise_error_or_return_true(response)
|
17
|
+
end
|
18
|
+
|
19
|
+
def fast_acknowledge(job_id)
|
20
|
+
response = @client.call('FASTACK', job_id)
|
21
|
+
raise_error_or_return_true(response)
|
22
|
+
end
|
23
|
+
|
24
|
+
def publish(*args)
|
25
|
+
@client.push(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# If there is an error acking the job the Disque client
|
31
|
+
# *returns* an error object but doesn't raise it,
|
32
|
+
# so we raise it here ourselves.
|
33
|
+
def raise_error_or_return_true(response)
|
19
34
|
response.is_a?(RuntimeError) ? raise(response) : true
|
20
35
|
end
|
36
|
+
|
21
37
|
end
|
22
|
-
end
|
38
|
+
end
|
data/lib/disque_jockey/worker.rb
CHANGED
@@ -11,13 +11,18 @@ module DisqueJockey
|
|
11
11
|
end
|
12
12
|
|
13
13
|
class << self
|
14
|
-
attr_reader :queue_name, :thread_count, :timeout_seconds
|
14
|
+
attr_reader :queue_name, :thread_count, :timeout_seconds, :use_fast_ack
|
15
15
|
|
16
16
|
# This worker class will subscribe to queue
|
17
17
|
def subscribe_to(queue)
|
18
18
|
@queue_name = queue
|
19
19
|
end
|
20
20
|
|
21
|
+
# whehter to use Disque fast acknowledgements
|
22
|
+
def fast_ack(value)
|
23
|
+
@use_fast_ack = !!value
|
24
|
+
end
|
25
|
+
|
21
26
|
# minimum number of worker instances of a given worker class.
|
22
27
|
def threads(size)
|
23
28
|
@thread_count = [[size, 1].max, 10].min
|
@@ -36,10 +41,11 @@ module DisqueJockey
|
|
36
41
|
# these are the defaults
|
37
42
|
type.threads 2
|
38
43
|
type.timeout 30
|
44
|
+
type.fast_ack false
|
39
45
|
# register the new worker type so we can start giving it jobs
|
40
46
|
Supervisor.register_worker(type)
|
41
47
|
end
|
42
48
|
end
|
43
49
|
|
44
50
|
end
|
45
|
-
end
|
51
|
+
end
|
@@ -37,7 +37,7 @@ module DisqueJockey
|
|
37
37
|
def handle_job(worker, job, job_id)
|
38
38
|
begin
|
39
39
|
Timeout::timeout(@worker_class.timeout_seconds) { worker.handle(job) }
|
40
|
-
@broker.acknowledge(job_id)
|
40
|
+
@worker_class.use_fast_ack ? @broker.fast_acknowledge(job_id) : @broker.acknowledge(job_id)
|
41
41
|
rescue StandardError => exception
|
42
42
|
worker.log_exception(exception)
|
43
43
|
# TODO: Need to implement retry logic
|
@@ -47,8 +47,8 @@ module DisqueJockey
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def build_worker_pool
|
50
|
-
@worker_class.thread_count.times { @pool << @worker_class.new(Logger) }
|
50
|
+
@worker_class.thread_count.times { @pool << @worker_class.new(Logger) }
|
51
51
|
end
|
52
52
|
|
53
53
|
end
|
54
|
-
end
|
54
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
module DisqueJockey
|
3
3
|
describe Broker do
|
4
|
-
# Note: You actually have to run a Disque server
|
4
|
+
# Note: You actually have to run a Disque server
|
5
5
|
# locally for these tests to pass
|
6
6
|
before(:all) do
|
7
7
|
begin
|
@@ -34,7 +34,7 @@ module DisqueJockey
|
|
34
34
|
end
|
35
35
|
|
36
36
|
describe '#acknowledge' do
|
37
|
-
it "
|
37
|
+
it "removes job from queue and returns true if it succeeds" do
|
38
38
|
@client.call('DEBUG', 'FLUSHALL')
|
39
39
|
job_id = @client.push('test_queue', 'test job', 1000)
|
40
40
|
expect(@client.call('QLEN', 'test_queue')).to eq 1
|
@@ -43,9 +43,34 @@ module DisqueJockey
|
|
43
43
|
end
|
44
44
|
|
45
45
|
it "raises an error for a bad job id" do
|
46
|
-
expect{@broker.acknowledge('bad_id')}.to raise_error(RuntimeError)
|
46
|
+
expect{ @broker.acknowledge('bad_id') }.to raise_error(RuntimeError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#publish" do
|
51
|
+
it "publishes a job to Disque" do
|
52
|
+
test_queue = 'publish_test_queue'
|
53
|
+
test_job = 'job'
|
54
|
+
@broker.publish(test_queue, test_job, 1000)
|
55
|
+
fetched = @client.fetch(from: ['publish_test_queue']).first
|
56
|
+
expect(fetched.first).to eq test_queue
|
57
|
+
expect(fetched.last).to eq test_job
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#fast_acknowledge" do
|
62
|
+
it "raises an error for a bad job id" do
|
63
|
+
expect{@broker.fast_acknowledge('bad_id')}.to raise_error(RuntimeError)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "acknowledges jobs" do
|
67
|
+
@client.call('DEBUG', 'FLUSHALL')
|
68
|
+
job_id = @client.push('test_queue', 'test job', 1000)
|
69
|
+
expect(@client.call('QLEN', 'test_queue')).to eq 1
|
70
|
+
expect(@broker.fast_acknowledge(job_id)).to eq true
|
71
|
+
expect(@client.call('QLEN', 'test_queue')).to eq 0
|
47
72
|
end
|
48
73
|
end
|
49
74
|
|
50
75
|
end
|
51
|
-
end
|
76
|
+
end
|
@@ -24,7 +24,13 @@ module DisqueJockey
|
|
24
24
|
|
25
25
|
it "gives workers jobs to perform" do
|
26
26
|
@mock_worker = double("Worker", handle: true)
|
27
|
-
@mock_worker_class = double(
|
27
|
+
@mock_worker_class = double(
|
28
|
+
"WorkerClass",
|
29
|
+
thread_count: 1,
|
30
|
+
new: @mock_worker,
|
31
|
+
timeout_seconds: 1,
|
32
|
+
queue_name: 'q',
|
33
|
+
use_fast_ack: false)
|
28
34
|
worker_pool = WorkerPool.new(@mock_worker_class)
|
29
35
|
expect(@mock_worker).to receive(:handle)
|
30
36
|
worker_pool.work!
|
@@ -36,9 +42,16 @@ module DisqueJockey
|
|
36
42
|
end
|
37
43
|
|
38
44
|
it "acknowledges jobs if they are processed without errors" do
|
45
|
+
SecondSpecWorker.fast_ack(false)
|
39
46
|
expect_any_instance_of(Broker).to receive(:acknowledge).with('test_id').at_least(:once)
|
40
47
|
WorkerPool.new(SecondSpecWorker).work!
|
41
48
|
end
|
42
49
|
|
50
|
+
it "fast_acknowledges jobs if the worker uses fast_ack" do
|
51
|
+
SecondSpecWorker.fast_ack(true)
|
52
|
+
expect_any_instance_of(Broker).to receive(:fast_acknowledge).with('test_id').at_least(:once)
|
53
|
+
WorkerPool.new(SecondSpecWorker).work!
|
54
|
+
end
|
55
|
+
|
43
56
|
end
|
44
|
-
end
|
57
|
+
end
|
@@ -6,8 +6,8 @@ describe DisqueJockey::Worker do
|
|
6
6
|
include_context "worker setup"
|
7
7
|
|
8
8
|
it "defines class methods" do
|
9
|
-
[ :queue_name, :thread_count, :timeout_seconds,
|
10
|
-
:subscribe_to, :timeout, :threads
|
9
|
+
[ :queue_name, :thread_count, :timeout_seconds,
|
10
|
+
:subscribe_to, :timeout, :threads, :fast_ack, :use_fast_ack
|
11
11
|
].each do |method|
|
12
12
|
expect(DisqueJockey::Worker).to respond_to(method)
|
13
13
|
end
|
@@ -24,26 +24,34 @@ describe DisqueJockey::Worker do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
context "defaults" do
|
27
|
-
it "
|
27
|
+
it "timeout is 30 seconds" do
|
28
28
|
expect(SpecWorker.timeout_seconds).to be(30)
|
29
29
|
end
|
30
30
|
|
31
|
-
it "
|
31
|
+
it "thread_count is 2" do
|
32
32
|
expect(SpecWorker.thread_count).to be(2)
|
33
33
|
end
|
34
|
+
|
35
|
+
it "use_fast_ack is false" do
|
36
|
+
expect(SpecWorker.use_fast_ack).to eq false
|
37
|
+
end
|
38
|
+
|
34
39
|
end
|
35
40
|
|
36
41
|
context "class methods"
|
37
42
|
context "overrides" do
|
38
|
-
|
43
|
+
|
44
|
+
it "allows overrides for timeout, threads, and fast_ack" do
|
45
|
+
# These traits are set in worker_shared_setup.rb
|
39
46
|
expect(SecondSpecWorker.timeout_seconds).to be(1)
|
40
47
|
expect(SecondSpecWorker.thread_count).to be(1)
|
48
|
+
expect(SecondSpecWorker.use_fast_ack).to be(true)
|
41
49
|
end
|
42
50
|
end
|
43
|
-
|
51
|
+
|
44
52
|
context "instance methods"
|
45
53
|
describe "#initialize" do
|
46
|
-
before do
|
54
|
+
before do
|
47
55
|
@logger = double(:logger, info: true, error: true, warn: true)
|
48
56
|
allow(@logger).to receive(:new).and_return(@logger)
|
49
57
|
end
|