disque_jockey 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c49083bcd86ac5171c257bd78eeded4abbd5c99f
4
- data.tar.gz: 868ababcc280ffa34de1b8270c07b00c04bc299c
3
+ metadata.gz: e595757036b4f0fa828fcb9dda551db3f211ed7e
4
+ data.tar.gz: 81687ba961860e23ffd2b877b81166b8c8f3ea31
5
5
  SHA512:
6
- metadata.gz: 8fa502414a8a708a693cff041773bb2ae9201d7d0be70dd5fd5eafe2bedd3b6dc31852f7e9f1f516f2dffe52e7998e70923f49eb2a07817d3b768bc683dd632e
7
- data.tar.gz: 8dec61c2d6e36a1347147114f00e6290aa2cd2c2d4ae83b76124fdc4f68581e3727208c1f5554b2aa376fd76c212aa2e8e87ed0681bd0e2d1dc00a6f5058f43c
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.
@@ -13,10 +13,26 @@ module DisqueJockey
13
13
 
14
14
  def acknowledge(job_id)
15
15
  response = @client.call('ACKJOB', job_id)
16
- # If there is an error acking the job the Disque client
17
- # *returns* an error object but doesn't raise it,
18
- # so we raise it here ourselves.
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
@@ -1,3 +1,3 @@
1
1
  module DisqueJockey
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
@@ -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 "returns removes job from queue and returns true if it succeeds" do
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("WorkerClass", thread_count: 1, new: @mock_worker, timeout_seconds: 1, queue_name: 'q')
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,9 +6,10 @@ shared_context "worker setup" do
6
6
  subscribe_to "test"
7
7
  def handle(job); end
8
8
  end
9
-
9
+
10
10
  class SecondSpecWorker < DisqueJockey::Worker
11
11
  subscribe_to "other-test"
12
+ fast_ack true
12
13
  threads 1
13
14
  timeout 1
14
15
  def handle(job); 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 "sets a default for timeout" do
27
+ it "timeout is 30 seconds" do
28
28
  expect(SpecWorker.timeout_seconds).to be(30)
29
29
  end
30
30
 
31
- it "sets a default for thread_count" do
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
- it "allows overrides for timeout, and thread_count" do
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: disque_jockey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Devin Riley