dispatch-rider 1.4.0 → 1.4.2
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 +4 -4
- data/.gitignore +20 -0
- data/.hound.yml +2 -0
- data/.rubocop.yml +50 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +363 -0
- data/Gemfile +25 -0
- data/LICENSE.txt +1 -1
- data/README.md +32 -3
- data/Rakefile +38 -0
- data/dispatch-rider.gemspec +46 -0
- data/lib/dispatch-rider/notification_services/aws_sns.rb +9 -0
- data/lib/dispatch-rider/version.rb +1 -1
- data/spec/fixtures/handlers/another_test_handler.rb +2 -0
- data/spec/fixtures/handlers/test_handler.rb +2 -0
- data/spec/lib/dispatch-rider/airbrake_error_handler_spec.rb +16 -0
- data/spec/lib/dispatch-rider/callbacks/access_spec.rb +62 -0
- data/spec/lib/dispatch-rider/callbacks/storage_spec.rb +43 -0
- data/spec/lib/dispatch-rider/configuration_spec.rb +74 -0
- data/spec/lib/dispatch-rider/default_error_handler_spec.rb +14 -0
- data/spec/lib/dispatch-rider/demultiplexer_spec.rb +117 -0
- data/spec/lib/dispatch-rider/dispatcher_spec.rb +69 -0
- data/spec/lib/dispatch-rider/handlers/base_spec.rb +81 -0
- data/spec/lib/dispatch-rider/handlers/inheritance_tracking_spec.rb +27 -0
- data/spec/lib/dispatch-rider/message_spec.rb +59 -0
- data/spec/lib/dispatch-rider/notification_services/aws_sns_spec.rb +28 -0
- data/spec/lib/dispatch-rider/notification_services/base_spec.rb +65 -0
- data/spec/lib/dispatch-rider/notification_services/file_system/channel_spec.rb +28 -0
- data/spec/lib/dispatch-rider/notification_services/file_system/notifier_spec.rb +14 -0
- data/spec/lib/dispatch-rider/notification_services/file_system_spec.rb +23 -0
- data/spec/lib/dispatch-rider/notification_services_spec.rb +4 -0
- data/spec/lib/dispatch-rider/publisher/base_spec.rb +79 -0
- data/spec/lib/dispatch-rider/publisher/configuration/destination_spec.rb +100 -0
- data/spec/lib/dispatch-rider/publisher/configuration/notification_service_spec.rb +53 -0
- data/spec/lib/dispatch-rider/publisher/configuration_reader_spec.rb +129 -0
- data/spec/lib/dispatch-rider/publisher/configuration_spec.rb +149 -0
- data/spec/lib/dispatch-rider/publisher/configuration_support_spec.rb +89 -0
- data/spec/lib/dispatch-rider/publisher_spec.rb +123 -0
- data/spec/lib/dispatch-rider/queue_services/aws_sqs_spec.rb +193 -0
- data/spec/lib/dispatch-rider/queue_services/base_spec.rb +147 -0
- data/spec/lib/dispatch-rider/queue_services/file_system_spec.rb +88 -0
- data/spec/lib/dispatch-rider/queue_services/received_message_spec.rb +23 -0
- data/spec/lib/dispatch-rider/queue_services/simple_spec.rb +63 -0
- data/spec/lib/dispatch-rider/queue_services_spec.rb +6 -0
- data/spec/lib/dispatch-rider/registrars/base_spec.rb +68 -0
- data/spec/lib/dispatch-rider/registrars/file_system_channel_spec.rb +12 -0
- data/spec/lib/dispatch-rider/registrars/handler_spec.rb +16 -0
- data/spec/lib/dispatch-rider/registrars/notification_service_spec.rb +13 -0
- data/spec/lib/dispatch-rider/registrars/publishing_destination_spec.rb +11 -0
- data/spec/lib/dispatch-rider/registrars/queue_service_spec.rb +13 -0
- data/spec/lib/dispatch-rider/registrars/sns_channel_spec.rb +14 -0
- data/spec/lib/dispatch-rider/registrars_spec.rb +4 -0
- data/spec/lib/dispatch-rider/runner_spec.rb +25 -0
- data/spec/lib/dispatch-rider/subscriber_spec.rb +140 -0
- data/spec/lib/dispatch-rider_spec.rb +27 -0
- data/spec/spec_helper.rb +21 -0
- metadata +107 -86
data/Gemfile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
# only add dev/test gems here, runtime gems should go in the gemspec
|
6
|
+
|
7
|
+
# Base
|
8
|
+
gem "bundler"
|
9
|
+
gem "rake"
|
10
|
+
|
11
|
+
# Gem Stuff
|
12
|
+
gem 'rubygems-tasks'
|
13
|
+
gem 'github_changelog_generator'
|
14
|
+
gem 'yard'
|
15
|
+
|
16
|
+
# Testing
|
17
|
+
gem "rspec", "~> 2.0"
|
18
|
+
gem 'rspec-its', "~> 1.0"
|
19
|
+
|
20
|
+
# CI
|
21
|
+
gem "travis-lint"
|
22
|
+
|
23
|
+
# Dev/Debugging
|
24
|
+
gem "byebug", platform: :ruby_20, require: !ENV['CI']
|
25
|
+
gem "aws-sdk", "~> 1"
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -257,7 +257,7 @@ class ReadNews < DispatchRider::Handlers::Base
|
|
257
257
|
puts headline
|
258
258
|
end
|
259
259
|
end
|
260
|
-
|
260
|
+
|
261
261
|
def retry_timeout
|
262
262
|
10.minutes
|
263
263
|
end
|
@@ -277,7 +277,7 @@ extend_timeout will tell the queue you wish to hold this item longer.
|
|
277
277
|
class LongRunning < DispatchRider::Handlers::Base
|
278
278
|
def process(body)
|
279
279
|
my_loop.each do |item|
|
280
|
-
|
280
|
+
|
281
281
|
#... do some work ...
|
282
282
|
extend_timeout(1.hour)
|
283
283
|
end
|
@@ -344,6 +344,35 @@ DispatchRider.config do |config|
|
|
344
344
|
config.error_handler = DispatchRider::AirbrakeErrorHandler
|
345
345
|
end
|
346
346
|
```
|
347
|
+
## Deployment
|
348
|
+
|
349
|
+
In order to deploy a new version of the gem into the wild ...
|
350
|
+
|
351
|
+
You will need to configure your github api token for the changelog.
|
352
|
+
|
353
|
+
Generate a new token for changelogs [here](https://github.com/settings/tokens/new).
|
354
|
+
|
355
|
+
add:
|
356
|
+
|
357
|
+
```bash
|
358
|
+
export CHANGELOG_GITHUB_TOKEN=YOUR_CHANGELOG_API_TOKEN
|
359
|
+
```
|
360
|
+
|
361
|
+
somewhere in your shell init. (ie .zshrc or simillar)
|
362
|
+
|
363
|
+
|
364
|
+
```bash
|
365
|
+
vim lib/dispatch-rider/version.rb
|
366
|
+
# set the new version
|
367
|
+
rake gemspec
|
368
|
+
# commit any changed files (should be only version and the gemspec)
|
369
|
+
# name your commit with the version number eg: "1.8.0"
|
370
|
+
rake release
|
371
|
+
# to push the gem to rubygems.org
|
372
|
+
rake changelog
|
373
|
+
# commit the changed changelog
|
374
|
+
# name your commit with the version again eg: "changelog for 1.8.0"
|
375
|
+
```
|
347
376
|
|
348
377
|
## Contributing
|
349
378
|
|
@@ -357,7 +386,7 @@ end
|
|
357
386
|
|
358
387
|
### Licence
|
359
388
|
|
360
|
-
Copyright (c)
|
389
|
+
Copyright (c) 2015 PayrollHero Pte. Ltd.
|
361
390
|
|
362
391
|
MIT License
|
363
392
|
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler'
|
7
|
+
rescue LoadError => e
|
8
|
+
warn e.message
|
9
|
+
warn "Run `gem install bundler` to install Bundler."
|
10
|
+
exit -1
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
Bundler.setup(:development)
|
15
|
+
rescue Bundler::BundlerError => e
|
16
|
+
warn e.message
|
17
|
+
warn "Run `bundle install` to install missing gems."
|
18
|
+
exit e.status_code
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake'
|
22
|
+
require 'rubygems/tasks'
|
23
|
+
Gem::Tasks.new
|
24
|
+
|
25
|
+
require 'rspec/core/rake_task'
|
26
|
+
RSpec::Core::RakeTask.new
|
27
|
+
|
28
|
+
task :test => :spec
|
29
|
+
task :default => :spec
|
30
|
+
|
31
|
+
require 'yard'
|
32
|
+
YARD::Rake::YardocTask.new
|
33
|
+
task :doc => :yard
|
34
|
+
|
35
|
+
desc "Updates the changelog"
|
36
|
+
task :changelog do
|
37
|
+
sh "github_changelog_generator payrollhero/dispatch-rider"
|
38
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path('../lib/dispatch-rider/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = "dispatch-rider"
|
7
|
+
gem.version = DispatchRider::VERSION
|
8
|
+
|
9
|
+
gem.summary = %q{
|
10
|
+
Messaging system that is customizable based on which
|
11
|
+
queueing system we are using.
|
12
|
+
}
|
13
|
+
gem.description = %q{
|
14
|
+
Messaging system based on the reactor pattern.
|
15
|
+
|
16
|
+
You can publish messages to a queue and then a demultiplexer
|
17
|
+
runs an event loop which pops items from the queue and hands
|
18
|
+
it over to a dispatcher.
|
19
|
+
|
20
|
+
The dispatcher hands over the message to the appropriate
|
21
|
+
handler.
|
22
|
+
|
23
|
+
You can choose your own queueing service.
|
24
|
+
}
|
25
|
+
gem.license = "MIT"
|
26
|
+
gem.authors = [
|
27
|
+
"Suman Mukherjee",
|
28
|
+
"Dane Natoli",
|
29
|
+
"Piotr Banasik",
|
30
|
+
"Ronald Maravilla",
|
31
|
+
]
|
32
|
+
gem.email = [
|
33
|
+
"piotr@payrollhero.com",
|
34
|
+
"rmaravilla@payrollhero.com",
|
35
|
+
]
|
36
|
+
gem.homepage = "https://github.com/payrollhero/dispatch-rider"
|
37
|
+
gem.files = `git ls-files`.split($/)
|
38
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
39
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
40
|
+
gem.require_paths = ['lib']
|
41
|
+
|
42
|
+
gem.add_runtime_dependency('activesupport', ">= 0")
|
43
|
+
gem.add_runtime_dependency('activemodel', ">= 0")
|
44
|
+
gem.add_runtime_dependency('daemons', ">= 0")
|
45
|
+
gem.add_runtime_dependency('retries', ">= 0")
|
46
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'retries'
|
1
2
|
# This is a basic implementation of the Notification service using Amazon SNS.
|
2
3
|
# The expected usage is as follows :
|
3
4
|
# notification_service = DispatchRider::NotificationServices::AwsSns.new
|
@@ -15,6 +16,14 @@ module DispatchRider
|
|
15
16
|
Registrars::SnsChannel
|
16
17
|
end
|
17
18
|
|
19
|
+
def publish(options)
|
20
|
+
channels(options[:to]).each do |channel|
|
21
|
+
with_retries(max_retries: 10, rescue: AWS::Errors::MissingCredentialsError) do
|
22
|
+
channel.publish(serialize(message(options[:message])))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
18
27
|
# not really happy with this, but the notification service registrar system is way too rigid to do this cleaner
|
19
28
|
# since you only can have one notifier for the whole service, but you need to create a new one for each region
|
20
29
|
def channel(name)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe DispatchRider::AirbrakeErrorHandler do
|
4
|
+
|
5
|
+
describe ".call" do
|
6
|
+
let(:message){ DispatchRider::Message.new(subject: "TestMessage", body: "foo" )}
|
7
|
+
let(:exception){ Exception.new("Something went terribly wrong") }
|
8
|
+
|
9
|
+
example do
|
10
|
+
Airbrake.should_receive(:notify).with(exception, controller: "DispatchRider", action: "TestMessage", parameters: { subject: "TestMessage", body: "foo" }, cgi_data: anything)
|
11
|
+
|
12
|
+
described_class.call(message, exception)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DispatchRider::Callbacks::Access do
|
4
|
+
describe "#invoke" do
|
5
|
+
|
6
|
+
let(:callback_a1) { proc { |x| x.call } }
|
7
|
+
let(:callback_a2) { proc { |x| x.call } }
|
8
|
+
let(:callback_a3) { proc { |x| x.call } }
|
9
|
+
let(:callbacks_a) { [callback_a1, callback_a2, callback_a3] }
|
10
|
+
|
11
|
+
let(:callback_b1) { proc { |x| x.call } }
|
12
|
+
let(:callbacks_b) { [callback_b1] }
|
13
|
+
|
14
|
+
let(:storage) { DispatchRider::Callbacks::Storage.new }
|
15
|
+
let(:action) { proc { } }
|
16
|
+
|
17
|
+
subject { described_class.new(storage) }
|
18
|
+
|
19
|
+
before do
|
20
|
+
callbacks_a.each do |cb|
|
21
|
+
storage.around :event1, cb
|
22
|
+
end
|
23
|
+
callbacks_b.each do |cb|
|
24
|
+
storage.around :event2, cb
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
example "a bunch of handlers" do
|
29
|
+
callback_a1.should_receive(:call).once.and_call_original
|
30
|
+
callback_a2.should_receive(:call).once.and_call_original
|
31
|
+
callback_a3.should_receive(:call).once.and_call_original
|
32
|
+
callback_b1.should_not_receive(:call)
|
33
|
+
|
34
|
+
action.should_receive(:call).once.and_call_original
|
35
|
+
|
36
|
+
subject.invoke(:event1, &action)
|
37
|
+
end
|
38
|
+
|
39
|
+
example "single handler" do
|
40
|
+
callback_a1.should_not_receive(:call)
|
41
|
+
callback_a2.should_not_receive(:call)
|
42
|
+
callback_a3.should_not_receive(:call)
|
43
|
+
callback_b1.should_receive(:call).once.and_call_original
|
44
|
+
|
45
|
+
action.should_receive(:call).once.and_call_original
|
46
|
+
|
47
|
+
subject.invoke(:event2, &action)
|
48
|
+
end
|
49
|
+
|
50
|
+
example "no handlers" do
|
51
|
+
callback_a1.should_not_receive(:call)
|
52
|
+
callback_a2.should_not_receive(:call)
|
53
|
+
callback_a3.should_not_receive(:call)
|
54
|
+
callback_b1.should_not_receive(:call)
|
55
|
+
|
56
|
+
action.should_receive(:call).once.and_call_original
|
57
|
+
|
58
|
+
subject.invoke(:event3, &action)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DispatchRider::Callbacks::Storage do
|
4
|
+
|
5
|
+
subject{ described_class.new }
|
6
|
+
|
7
|
+
describe "adding callbacks" do
|
8
|
+
|
9
|
+
let!(:log) { [] }
|
10
|
+
let(:actual) { proc { log << :actual } }
|
11
|
+
|
12
|
+
describe "#around" do
|
13
|
+
example do
|
14
|
+
subject.around(:initialize) do |job|
|
15
|
+
log << :abefore
|
16
|
+
job.call
|
17
|
+
log << :aafter
|
18
|
+
end
|
19
|
+
subject.for(:initialize).first[actual]
|
20
|
+
log.should == [:abefore, :actual, :aafter]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#before" do
|
25
|
+
example do
|
26
|
+
subject.before(:initialize) { log << :before }
|
27
|
+
subject.for(:initialize).first[actual]
|
28
|
+
log.should == [:before, :actual]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#after" do
|
33
|
+
example do
|
34
|
+
subject.after(:initialize) { log << :after }
|
35
|
+
subject.for(:initialize).first[actual]
|
36
|
+
log.should == [:actual, :after]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DispatchRider::Configuration do
|
4
|
+
|
5
|
+
subject{ described_class.new }
|
6
|
+
|
7
|
+
describe "defaults" do
|
8
|
+
example do
|
9
|
+
subject.handler_path.should =~ /\/app\/handlers/
|
10
|
+
subject.error_handler.should == DispatchRider::DefaultErrorHandler
|
11
|
+
subject.queue_kind.should == :file_system
|
12
|
+
subject.queue_info.should == { path: "tmp/dispatch-rider-queue" }
|
13
|
+
subject.subscriber.should == DispatchRider::Subscriber
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#before" do
|
18
|
+
example do
|
19
|
+
subject.should respond_to(:before)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#after" do
|
24
|
+
example do
|
25
|
+
subject.should respond_to(:after)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#around" do
|
30
|
+
example do
|
31
|
+
subject.should respond_to(:around)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#handlers" do
|
36
|
+
before :each do
|
37
|
+
subject.handler_path = "./spec/fixtures/handlers"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "loads the files and converts their names to symbols" do
|
41
|
+
subject.handlers.should include(:test_handler, :another_test_handler)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#default_retry_timeout" do
|
46
|
+
it "sets the default timeout" do
|
47
|
+
subject.default_retry_timeout = 60
|
48
|
+
TestHandler.instance_methods.should include(:retry_timeout)
|
49
|
+
#Need to do this so that all the other tests don't have this as default!
|
50
|
+
DispatchRider::Handlers::Base.send(:remove_method,:retry_timeout)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#logger" do
|
55
|
+
|
56
|
+
describe "default" do
|
57
|
+
example { subject.logger.should be_kind_of(Logger) }
|
58
|
+
end
|
59
|
+
|
60
|
+
example { subject.should respond_to(:logger) }
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#logger=" do
|
64
|
+
let(:new_logger) { double(:logger) }
|
65
|
+
|
66
|
+
example { subject.should respond_to(:logger=) }
|
67
|
+
|
68
|
+
example do
|
69
|
+
subject.logger = new_logger
|
70
|
+
subject.logger.should == new_logger
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe DispatchRider::DefaultErrorHandler do
|
4
|
+
|
5
|
+
describe ".call" do
|
6
|
+
let(:exception){ Exception.new("Something went terribly wrong") }
|
7
|
+
example do
|
8
|
+
expect{
|
9
|
+
described_class.call("Error", exception)
|
10
|
+
}.to raise_exception exception
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DispatchRider::Demultiplexer, :nodb => true do
|
4
|
+
class TestHandler < DispatchRider::Handlers::Base
|
5
|
+
def process(options)
|
6
|
+
raise "OMG!!!" if options["raise_exception"]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:dispatcher) do
|
11
|
+
dispatcher = DispatchRider::Dispatcher.new
|
12
|
+
dispatcher.register(:test_handler)
|
13
|
+
dispatcher
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:queue) do
|
17
|
+
DispatchRider::QueueServices::Simple.new
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:message){ DispatchRider::Message.new(:subject => "test_handler", :body => {}) }
|
21
|
+
|
22
|
+
let(:demultiplexer_thread) do
|
23
|
+
demultiplexer
|
24
|
+
thread = Thread.new do
|
25
|
+
demultiplexer.start
|
26
|
+
end
|
27
|
+
thread[:demultiplexer] = demultiplexer
|
28
|
+
thread
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:error_handler){ ->(message, exception){ raise exception }}
|
32
|
+
|
33
|
+
subject(:demultiplexer) { DispatchRider::Demultiplexer.new(queue, dispatcher, error_handler) }
|
34
|
+
|
35
|
+
describe "#initialize" do
|
36
|
+
it "should assign the queue" do
|
37
|
+
demultiplexer.queue.should be_empty
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should assign the dispatcher" do
|
41
|
+
demultiplexer.dispatcher.fetch(:test_handler).should eq(TestHandler)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#start" do
|
46
|
+
after do
|
47
|
+
demultiplexer_thread[:demultiplexer].stop
|
48
|
+
demultiplexer_thread.join
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when the queue is not empty" do
|
52
|
+
|
53
|
+
before do
|
54
|
+
queue.push message
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should be sending the message to the dispatcher" do
|
58
|
+
demultiplexer.should_receive(:dispatch_message).with(message).at_least(:once)
|
59
|
+
demultiplexer_thread.run
|
60
|
+
sleep 0.01 # give it a chance to process the job async before killing the demux
|
61
|
+
end
|
62
|
+
|
63
|
+
# THIS ALSO TESTS THAT THE JOB IS NOT RUN MULTIPLE TIMES
|
64
|
+
# IF THIS FAILS, BE CAREFUL NOT TO INTRODUCE BUGS
|
65
|
+
it "should call the correct handler" do
|
66
|
+
TestHandler.any_instance.should_receive(:process).with(message.body).at_least(1).times
|
67
|
+
demultiplexer_thread.run
|
68
|
+
sleep 0.01 # give it a chance to process the job async before killing the demux
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when the queue is empty" do
|
73
|
+
it "should not be sending any message to the dispatcher" do
|
74
|
+
demultiplexer.should_receive(:dispatch_message).exactly(0).times
|
75
|
+
demultiplexer_thread.run
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when the handler crashes" do
|
80
|
+
before do
|
81
|
+
message.body = { "raise_exception" => true }
|
82
|
+
queue.push message
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should call the error handler" do
|
86
|
+
error_handler.should_receive(:call).at_least(:once).and_return(true)
|
87
|
+
queue.should_not_receive(:delete)
|
88
|
+
demultiplexer_thread.run
|
89
|
+
sleep 0.01 # give it a chance to process the job async before killing the demux
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "when the queue crashes" do
|
94
|
+
before do
|
95
|
+
queue.stub(:pop){ raise "OMG!!!"}
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should call the error handler" do
|
99
|
+
error_handler.should_receive(:call).once
|
100
|
+
demultiplexer_thread.run
|
101
|
+
|
102
|
+
sleep 0.01 # give it a chance to process the job async before killing the demux
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe ".stop" do
|
108
|
+
it "should stop the demultiplexer" do
|
109
|
+
demultiplexer_thread.run
|
110
|
+
demultiplexer_thread.should be_alive # looper should be looping
|
111
|
+
demultiplexer_thread[:demultiplexer].stop
|
112
|
+
demultiplexer_thread.join
|
113
|
+
demultiplexer_thread.should_not be_alive # looper should close the loop
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|