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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +20 -0
  3. data/.hound.yml +2 -0
  4. data/.rubocop.yml +50 -0
  5. data/.travis.yml +6 -0
  6. data/CHANGELOG.md +363 -0
  7. data/Gemfile +25 -0
  8. data/LICENSE.txt +1 -1
  9. data/README.md +32 -3
  10. data/Rakefile +38 -0
  11. data/dispatch-rider.gemspec +46 -0
  12. data/lib/dispatch-rider/notification_services/aws_sns.rb +9 -0
  13. data/lib/dispatch-rider/version.rb +1 -1
  14. data/spec/fixtures/handlers/another_test_handler.rb +2 -0
  15. data/spec/fixtures/handlers/test_handler.rb +2 -0
  16. data/spec/lib/dispatch-rider/airbrake_error_handler_spec.rb +16 -0
  17. data/spec/lib/dispatch-rider/callbacks/access_spec.rb +62 -0
  18. data/spec/lib/dispatch-rider/callbacks/storage_spec.rb +43 -0
  19. data/spec/lib/dispatch-rider/configuration_spec.rb +74 -0
  20. data/spec/lib/dispatch-rider/default_error_handler_spec.rb +14 -0
  21. data/spec/lib/dispatch-rider/demultiplexer_spec.rb +117 -0
  22. data/spec/lib/dispatch-rider/dispatcher_spec.rb +69 -0
  23. data/spec/lib/dispatch-rider/handlers/base_spec.rb +81 -0
  24. data/spec/lib/dispatch-rider/handlers/inheritance_tracking_spec.rb +27 -0
  25. data/spec/lib/dispatch-rider/message_spec.rb +59 -0
  26. data/spec/lib/dispatch-rider/notification_services/aws_sns_spec.rb +28 -0
  27. data/spec/lib/dispatch-rider/notification_services/base_spec.rb +65 -0
  28. data/spec/lib/dispatch-rider/notification_services/file_system/channel_spec.rb +28 -0
  29. data/spec/lib/dispatch-rider/notification_services/file_system/notifier_spec.rb +14 -0
  30. data/spec/lib/dispatch-rider/notification_services/file_system_spec.rb +23 -0
  31. data/spec/lib/dispatch-rider/notification_services_spec.rb +4 -0
  32. data/spec/lib/dispatch-rider/publisher/base_spec.rb +79 -0
  33. data/spec/lib/dispatch-rider/publisher/configuration/destination_spec.rb +100 -0
  34. data/spec/lib/dispatch-rider/publisher/configuration/notification_service_spec.rb +53 -0
  35. data/spec/lib/dispatch-rider/publisher/configuration_reader_spec.rb +129 -0
  36. data/spec/lib/dispatch-rider/publisher/configuration_spec.rb +149 -0
  37. data/spec/lib/dispatch-rider/publisher/configuration_support_spec.rb +89 -0
  38. data/spec/lib/dispatch-rider/publisher_spec.rb +123 -0
  39. data/spec/lib/dispatch-rider/queue_services/aws_sqs_spec.rb +193 -0
  40. data/spec/lib/dispatch-rider/queue_services/base_spec.rb +147 -0
  41. data/spec/lib/dispatch-rider/queue_services/file_system_spec.rb +88 -0
  42. data/spec/lib/dispatch-rider/queue_services/received_message_spec.rb +23 -0
  43. data/spec/lib/dispatch-rider/queue_services/simple_spec.rb +63 -0
  44. data/spec/lib/dispatch-rider/queue_services_spec.rb +6 -0
  45. data/spec/lib/dispatch-rider/registrars/base_spec.rb +68 -0
  46. data/spec/lib/dispatch-rider/registrars/file_system_channel_spec.rb +12 -0
  47. data/spec/lib/dispatch-rider/registrars/handler_spec.rb +16 -0
  48. data/spec/lib/dispatch-rider/registrars/notification_service_spec.rb +13 -0
  49. data/spec/lib/dispatch-rider/registrars/publishing_destination_spec.rb +11 -0
  50. data/spec/lib/dispatch-rider/registrars/queue_service_spec.rb +13 -0
  51. data/spec/lib/dispatch-rider/registrars/sns_channel_spec.rb +14 -0
  52. data/spec/lib/dispatch-rider/registrars_spec.rb +4 -0
  53. data/spec/lib/dispatch-rider/runner_spec.rb +25 -0
  54. data/spec/lib/dispatch-rider/subscriber_spec.rb +140 -0
  55. data/spec/lib/dispatch-rider_spec.rb +27 -0
  56. data/spec/spec_helper.rb +21 -0
  57. metadata +107 -86
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::QueueServices::FileSystem do
4
+ let(:queue_path) { "tmp/queue" }
5
+
6
+ subject(:file_system_queue) do
7
+ DispatchRider::QueueServices::FileSystem.new(:path => queue_path)
8
+ end
9
+
10
+ before { file_system_queue.send(:queue).send(:file_paths).each{|file| File.unlink(file)} }
11
+
12
+ describe "#assign_storage" do
13
+ it "should return an empty array" do
14
+ file_system_queue.assign_storage({:path => queue_path}).should be_a DispatchRider::QueueServices::FileSystem::Queue
15
+ end
16
+ end
17
+
18
+ describe "#insert" do
19
+ it "should insert a serialized object into the queue" do
20
+ file_system_queue.insert({'subject' => 'foo', 'body' => 'bar'}.to_json)
21
+ result = JSON.parse(file_system_queue.queue.pop.read)
22
+ result['subject'].should eq('foo')
23
+ result['body'].should eq('bar')
24
+ end
25
+ end
26
+
27
+ describe "#raw_head" do
28
+ before :each do
29
+ file_system_queue.insert({'subject' => 'foo', 'body' => 'bar'}.to_json)
30
+ end
31
+
32
+ it "should return the first item from the queue" do
33
+ result = JSON.parse(file_system_queue.raw_head.read)
34
+ result['subject'].should eq('foo')
35
+ result['body'].should eq('bar')
36
+ end
37
+ end
38
+
39
+ describe "#construct_message_from" do
40
+ let(:new_file) do
41
+ file = Tempfile.new('item')
42
+ file.write({'subject' => 'foo', 'body' => 'bar'}.to_json)
43
+ file.rewind
44
+ file
45
+ end
46
+
47
+ it "should return the item casted as a message" do
48
+ result = file_system_queue.construct_message_from(new_file)
49
+ result.subject.should eq('foo')
50
+ result.body.should eq('bar')
51
+ end
52
+ end
53
+
54
+ describe "#put_back" do
55
+ before :each do
56
+ file_system_queue.insert({'subject' => 'foo', 'body' => 'bar'}.to_json)
57
+ end
58
+
59
+ it "should remove and re-add the item" do
60
+ file = file_system_queue.raw_head
61
+ file_system_queue.should be_empty
62
+ file_system_queue.put_back(file)
63
+ file_system_queue.size.should eq(1)
64
+ end
65
+ end
66
+
67
+ describe "#delete" do
68
+ before :each do
69
+ file_system_queue.insert({'subject' => 'foo', 'body' => 'bar'}.to_json)
70
+ end
71
+
72
+ it "should remove the item from the queue" do
73
+ file = File.new(Dir["#{queue_path}/*.ready"].first, "w")
74
+ file_system_queue.delete(file)
75
+ file_system_queue.should be_empty
76
+ end
77
+ end
78
+
79
+ describe "#size" do
80
+ before :each do
81
+ file_system_queue.insert({'subject' => 'foo', 'body' => 'bar'}.to_json)
82
+ end
83
+
84
+ it "should return the size of the queue" do
85
+ file_system_queue.size.should eq(1)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::QueueServices::ReceivedMessage do
4
+
5
+ subject{ described_class.new("test_message", double(:item)) }
6
+
7
+ describe "#extend_timeout" do
8
+ example do
9
+ expect{
10
+ subject.extend_timeout(10)
11
+ }.to raise_error NotImplementedError
12
+ end
13
+ end
14
+
15
+ describe "#return_to_queue" do
16
+ example do
17
+ expect{
18
+ subject.return_to_queue
19
+ }.to raise_error NotImplementedError
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::QueueServices::Simple do
4
+ subject(:simple_queue) do
5
+ DispatchRider::QueueServices::Simple.new
6
+ end
7
+
8
+ describe "#assign_storage" do
9
+ it "should return an empty array" do
10
+ simple_queue.assign_storage({}).should eq([])
11
+ end
12
+ end
13
+
14
+ describe "#insert" do
15
+ it "should insert a serialized object into the queue" do
16
+ simple_queue.insert({'subject' => 'foo', 'body' => 'bar'}.to_json)
17
+ result = JSON.parse(simple_queue.queue.pop)
18
+ result['subject'].should eq('foo')
19
+ result['body'].should eq('bar')
20
+ end
21
+ end
22
+
23
+ describe "#raw_head" do
24
+ before :each do
25
+ simple_queue.insert({'subject' => 'foo', 'body' => 'bar'}.to_json)
26
+ end
27
+
28
+ it "should return the first item from the queue" do
29
+ result = JSON.parse(simple_queue.raw_head)
30
+ result['subject'].should eq('foo')
31
+ result['body'].should eq('bar')
32
+ end
33
+ end
34
+
35
+ describe "#construct_message_from" do
36
+ it "should return the item casted as a message" do
37
+ result = simple_queue.construct_message_from({'subject' => 'foo', 'body' => 'bar'}.to_json)
38
+ result.subject.should eq('foo')
39
+ result.body.should eq('bar')
40
+ end
41
+ end
42
+
43
+ describe "#delete" do
44
+ before :each do
45
+ simple_queue.insert({'subject' => 'foo', 'body' => 'bar'}.to_json)
46
+ end
47
+
48
+ it "should remove the item from the queue" do
49
+ simple_queue.delete({'subject' => 'foo', 'body' => 'bar'}.to_json)
50
+ simple_queue.should be_empty
51
+ end
52
+ end
53
+
54
+ describe "#size" do
55
+ before :each do
56
+ simple_queue.insert({'subject' => 'foo', 'body' => 'bar'}.to_json)
57
+ end
58
+
59
+ it "should return the size of the queue" do
60
+ simple_queue.size.should eq(1)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::QueueServices do
4
+ it "should work" do
5
+ end
6
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::Registrars::Base do
4
+ subject do
5
+ described_class.new
6
+ end
7
+
8
+ describe "#initialize" do
9
+ it "assigns store" do
10
+ subject.store.should be_empty
11
+ end
12
+ end
13
+
14
+ describe "#register" do
15
+ it "registers the value" do
16
+ subject.should_receive(:value).with(:foo, {}).and_return("bar")
17
+ subject.register(:foo)
18
+ subject.fetch(:foo).should eq('bar')
19
+ end
20
+
21
+ it "should return the registrar" do
22
+ subject.should_receive(:value).with(:foo, {}).and_return("bar")
23
+ subject.register(:foo).should eq(subject)
24
+ end
25
+
26
+ context "when there is a missing constant while registering" do
27
+ it "raises an exception" do
28
+ subject.should_receive(:value).with(:foo, {}) { 'bar'.camelize.constantize }
29
+ expect { subject.register(:foo) }.to raise_exception(DispatchRider::NotFound)
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "#unregister" do
35
+ before :each do
36
+ subject.stub(:value).and_return('bar')
37
+ subject.register(:foo)
38
+ end
39
+
40
+ it "unregisters the key/value pair from the registrar" do
41
+ subject.unregister(:foo)
42
+ expect { subject.fetch(:foo) }.to raise_exception(DispatchRider::NotRegistered)
43
+ end
44
+
45
+ it "returns the registrar" do
46
+ subject.unregister(:foo).should eq(subject)
47
+ end
48
+ end
49
+
50
+ describe "#fetch" do
51
+ context "when a key/value pair is registered" do
52
+ before :each do
53
+ subject.stub(:value).and_return('bar')
54
+ subject.register(:foo)
55
+ end
56
+
57
+ it "return the value for the key" do
58
+ subject.fetch(:foo).should eq('bar')
59
+ end
60
+ end
61
+
62
+ context "when a key/value pair is not registered" do
63
+ it "raises an exception" do
64
+ expect { subject.fetch(:foo) }.to raise_exception(DispatchRider::NotRegistered)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::Registrars::FileSystemChannel do
4
+ describe "#value" do
5
+ let(:path){ "/foo/bar" }
6
+ let(:channel_options){ {path: path} }
7
+
8
+ it "returns the expanded path from the options" do
9
+ subject.value(:foo, channel_options).should eq("/foo/bar")
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::Registrars::Handler do
4
+ module CustomTestHandler
5
+ end
6
+
7
+ subject do
8
+ described_class.new
9
+ end
10
+
11
+ describe "#value" do
12
+ it "returns the value for the key/value pair while registering a handler" do
13
+ subject.value(:custom_test_handler).should eq(CustomTestHandler)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::Registrars::NotificationService do
4
+ subject do
5
+ described_class.new
6
+ end
7
+
8
+ describe "#value" do
9
+ it "returns the value for the key/value pair while registering a notification service" do
10
+ subject.value(:aws_sns).should be_a(DispatchRider::NotificationServices::AwsSns)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::Registrars::PublishingDestination do
4
+ describe "#value" do
5
+ it "returns an object which has information about a notification service and a channel" do
6
+ result = subject.value('foo', :service => :aws_sns, :channel => :bar)
7
+ result.service.should eq(:aws_sns)
8
+ result.channel.should eq(:bar)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::Registrars::QueueService do
4
+ subject do
5
+ described_class.new
6
+ end
7
+
8
+ describe "#value" do
9
+ it "returns the value for the key/value pair while registering a queue service" do
10
+ subject.value(:simple).should be_a(DispatchRider::QueueServices::Simple)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::Registrars::SnsChannel do
4
+ describe "#value" do
5
+ let(:account){ "123456789012" }
6
+ let(:region){ "us-west-2" }
7
+ let(:topic_name){ "GeneralTopic" }
8
+ let(:channel_options){ {account: account, region: region, topic: topic_name} }
9
+
10
+ it "returns the value for the key/value pair while registering an amazon sns channel" do
11
+ subject.value(:foo, channel_options).should eq("arn:aws:sns:us-west-2:123456789012:GeneralTopic")
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::Registrars do
4
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::Runner do
4
+
5
+ describe ".run" do
6
+ let(:subscriber){ double(:subscriber) }
7
+
8
+ before :each do
9
+ DispatchRider.configure do |config|
10
+ config.subscriber = subscriber
11
+ end
12
+ end
13
+
14
+ example do
15
+ subscriber.should_receive(:new).once.and_return(subscriber)
16
+ subscriber.should_receive(:register_queue).once
17
+ subscriber.should_receive(:setup_demultiplexer).once
18
+ subscriber.should_receive(:process).once
19
+ subscriber.stub(:register_handler)
20
+
21
+ described_class.run
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,140 @@
1
+ require "spec_helper"
2
+
3
+ describe DispatchRider::Subscriber do
4
+
5
+ before do
6
+ DispatchRider::Handlers::Base.stub(:subclasses){ Set.new }
7
+
8
+ stub_const("FooBar", Class.new(DispatchRider::Handlers::Base) {
9
+ def process(options)
10
+ throw :process_was_called
11
+ end
12
+ })
13
+ end
14
+
15
+ describe "#initialize" do
16
+ it "should assign a new queue service registrar" do
17
+ subject.queue_service_registrar.store.should be_empty
18
+ end
19
+ end
20
+
21
+ describe "#register_queue" do
22
+ it "should register a queue service with the queue service registrar" do
23
+ subject.register_queue(:simple)
24
+ subject.queue_service_registrar.fetch(:simple).should be_empty
25
+ end
26
+ end
27
+
28
+ describe "#register_handler" do
29
+ it "should register a handler" do
30
+ subject.register_handler(:foo_bar)
31
+ expect { subject.dispatcher.dispatch(DispatchRider::Message.new(:subject => :foo_bar, :body => {'foo' => 'bar'})) }.to throw_symbol(:process_was_called)
32
+ end
33
+ end
34
+
35
+ describe "#register_handlers" do
36
+ it "should register all the handlers" do
37
+ subject.register_handlers(:foo_bar)
38
+ expect { subject.dispatcher.dispatch(DispatchRider::Message.new(:subject => :foo_bar, :body => {'foo' => 'bar'})) }.to throw_symbol(:process_was_called)
39
+ end
40
+ end
41
+
42
+ describe "#setup_demultiplexer" do
43
+ context "when a queue is registered" do
44
+ before :each do
45
+ subject.register_queue(:simple)
46
+ subject.register_handler(:foo_bar)
47
+ end
48
+
49
+ it "should assign a demultiplexer" do
50
+ subject.setup_demultiplexer(:simple)
51
+ subject.demultiplexer.queue.should be_empty
52
+ subject.demultiplexer.dispatcher.fetch(:foo_bar).should eq(FooBar)
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "#process" do
58
+ before :each do
59
+ subject.register_queue(:simple)
60
+ subject.register_handler(:foo_bar)
61
+ subject.setup_demultiplexer(:simple)
62
+ end
63
+
64
+ describe "processing" do
65
+ before do
66
+ subject.queue_service_registrar.fetch(:simple).push(DispatchRider::Message.new(subject: :foo_bar, body: {'baz' => 'blah'}))
67
+ end
68
+
69
+ it "should process the queue" do
70
+ expect { subject.process }.to throw_symbol(:process_was_called)
71
+ end
72
+ end
73
+
74
+ # kills travis sometimes so leaving it here as tested documentation
75
+ describe "process termination", if: false do
76
+ before { subject.demultiplexer.stub(:stop){ throw :got_stopped } }
77
+
78
+ context "when process quits" do
79
+ before do
80
+ stub_const("Quiter", Class.new(DispatchRider::Handlers::Base) {
81
+ def process(options)
82
+ Process.kill("QUIT", 0)
83
+ end
84
+ })
85
+
86
+ subject.register_handler(:quiter)
87
+ subject.queue_service_registrar.fetch(:simple).push(DispatchRider::Message.new(subject: :quiter, body: {}))
88
+ end
89
+
90
+ example { expect { subject.process }.to throw_symbol(:got_stopped) }
91
+ end
92
+
93
+ context "when process terminates" do
94
+ before do
95
+ stub_const("Terminator", Class.new(DispatchRider::Handlers::Base) {
96
+ def process(options)
97
+ Process.kill("TERM", 0)
98
+ end
99
+ })
100
+ subject.register_handler(:terminator)
101
+ subject.queue_service_registrar.fetch(:simple).push(DispatchRider::Message.new(subject: :terminator, body: {}))
102
+ end
103
+
104
+ example { expect { subject.process }.to throw_symbol(:got_stopped) }
105
+ end
106
+
107
+ context "when process is interupted" do
108
+ before do
109
+ stub_const("Interupter", Class.new(DispatchRider::Handlers::Base) {
110
+ def process(options)
111
+ Process.kill("INT", 0)
112
+ end
113
+ })
114
+ subject.register_handler(:interupter)
115
+ subject.queue_service_registrar.fetch(:simple).push(DispatchRider::Message.new(subject: :interupter, body: {}))
116
+ end
117
+
118
+ example { expect { subject.process }.to throw_symbol(:got_stopped) }
119
+ end
120
+
121
+ context "when process is interupted twice" do
122
+ before do
123
+ subject.demultiplexer.stub(:stop) # do nothing just ignore the interuption
124
+ subject.stub(:exit){ throw :got_forcefully_stopped }
125
+
126
+ stub_const("TwiceInterupter", Class.new(DispatchRider::Handlers::Base) {
127
+ def process(options)
128
+ 2.times { Process.kill("INT", 0) }
129
+ end
130
+ })
131
+ subject.register_handler(:twice_interupter)
132
+ subject.queue_service_registrar.fetch(:simple).push(DispatchRider::Message.new(subject: :twice_interupter, body: {}))
133
+ end
134
+
135
+ example { expect { subject.process }.to throw_symbol(:got_forcefully_stopped) }
136
+ end
137
+ end
138
+ end
139
+
140
+ end