banter 0.5.0 → 0.7.0
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/.travis.yml +6 -0
- data/Gemfile +9 -0
- data/README.md +37 -3
- data/lib/banter.rb +4 -0
- data/lib/banter/cli.rb +13 -3
- data/lib/banter/configuration.rb +10 -0
- data/lib/banter/middleware.rb +9 -1
- data/lib/banter/publisher.rb +45 -4
- data/lib/banter/rabbit_logger.rb +22 -4
- data/lib/banter/railtie.rb +6 -1
- data/lib/banter/server/client_queue_listener.rb +31 -7
- data/lib/banter/server/rabbit_mq_subscriber.rb +2 -1
- data/lib/banter/server/subscriber_server.rb +55 -23
- data/lib/banter/subscriber.rb +0 -1
- data/lib/banter/version.rb +1 -1
- data/lib/banter/web.rb +28 -0
- data/lib/banter/web/application.rb +36 -0
- data/lib/banter/web/helpers.rb +9 -0
- data/lib/banter/web/models/banter_message.rb +82 -0
- data/lib/banter/web/models/banter_worker.rb +68 -0
- data/spec/banter/cli_spec.rb +28 -6
- data/spec/banter/publisher_spec.rb +78 -0
- data/spec/banter/rabbit_logger_spec.rb +27 -2
- data/spec/banter/server/client_queue_listener_spec.rb +86 -22
- data/spec/banter/server/subscriber_server_spec.rb +87 -0
- data/spec/banter/web/application_spec.rb +10 -0
- data/spec/factories/banter_workers.rb +13 -0
- data/spec/mongoid.yml +7 -0
- data/spec/spec_helper.rb +28 -9
- data/web/assets/stylesheets/banter.css +66 -0
- data/web/views/index.haml +32 -0
- data/web/views/layout.haml +45 -0
- data/web/views/message.haml +52 -0
- data/web/views/messages.haml +20 -0
- data/web/views/subscribers.haml +17 -0
- data/web/views/worker.haml +51 -0
- metadata +24 -2
@@ -12,8 +12,9 @@ describe Banter::RabbitLogger do
|
|
12
12
|
before do
|
13
13
|
allow(Banter.logger).to receive(:debug)
|
14
14
|
allow(Banter.logger).to receive(:info)
|
15
|
-
allow(Banter.logger).to receive(:
|
15
|
+
allow(Banter.logger).to receive(:warn)
|
16
16
|
allow(Banter.logger).to receive(:error)
|
17
|
+
allow(Banter.logger).to receive(:log)
|
17
18
|
end
|
18
19
|
|
19
20
|
describe "#log_publish" do
|
@@ -24,7 +25,7 @@ describe Banter::RabbitLogger do
|
|
24
25
|
end
|
25
26
|
|
26
27
|
it "should write a row to the log" do
|
27
|
-
expect(Banter.logger).to have_received(:
|
28
|
+
expect(Banter.logger).to have_received(:warn).with(anything)
|
28
29
|
end
|
29
30
|
|
30
31
|
end
|
@@ -51,6 +52,30 @@ describe Banter::RabbitLogger do
|
|
51
52
|
expect{ result }.not_to raise_error()
|
52
53
|
end
|
53
54
|
|
55
|
+
it "should respect the log level of the file" do
|
56
|
+
expect(Banter.logger).to have_received(:warn).with(anything)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#log_complete" do
|
61
|
+
let!(:result) { subject.log_complete(routing_key, message)}
|
62
|
+
|
63
|
+
it "should not fail" do
|
64
|
+
expect{ result }.not_to raise_error()
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should respect the log level of the file" do
|
68
|
+
expect(Banter.logger).to have_received(:warn).with(anything)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#log" do
|
73
|
+
let!(:result) { subject.log(::Logger::DEBUG, message)}
|
74
|
+
|
75
|
+
it "should not fail" do
|
76
|
+
expect{ result }.not_to raise_error()
|
77
|
+
end
|
78
|
+
|
54
79
|
it "should respect the log level of the file" do
|
55
80
|
expect(Banter.logger).to have_received(:debug).with(anything)
|
56
81
|
end
|
@@ -3,13 +3,34 @@ require 'spec_helper'
|
|
3
3
|
describe Banter::Server::ClientQueueListener do
|
4
4
|
describe "#message_received" do
|
5
5
|
|
6
|
-
subject { -> { queue_listener.message_received(
|
6
|
+
subject { -> { queue_listener.message_received({}, { routing_key: routing_key }, { context: context, payload: payload }) } }
|
7
7
|
let(:queue_listener) { Banter::Server::ClientQueueListener.new(Klass, routing_key, 'queue') }
|
8
8
|
let(:routing_key) { 'some.test.key' }
|
9
|
-
let(:context) { {} }
|
10
|
-
let(:payload) { {hello: 'moto'} }
|
11
|
-
let(:context_before){}
|
12
|
-
let(:validators){ [] }
|
9
|
+
let(:context) { { app: 'test' } }
|
10
|
+
let(:payload) { { hello: 'moto' } }
|
11
|
+
let(:context_before) { }
|
12
|
+
let(:validators) { [] }
|
13
|
+
let(:banter_worker) { FactoryGirl.create(:banter_worker, process_name: 'test') }
|
14
|
+
let(:enable_banter_web) {
|
15
|
+
Banter::Configuration.web_enabled = true
|
16
|
+
allow(BanterWorker).to receive(:current).and_return(banter_worker)
|
17
|
+
}
|
18
|
+
let(:banter_message) { BanterMessage.last }
|
19
|
+
|
20
|
+
after(:each) { Banter::Configuration.web_enabled = false }
|
21
|
+
|
22
|
+
def self.banter_message_fields_are_correct(status, error_message = nil)
|
23
|
+
it { expect(BanterMessage.count).to eq 1 }
|
24
|
+
it { expect(banter_message.subscriber_class).to eq('Klass') }
|
25
|
+
it { expect(banter_message.queue_name).to eq('banter_test_foo') }
|
26
|
+
it { expect(banter_message.subscribed_key).to eq('test.foo') }
|
27
|
+
it { expect(banter_message.payload).to eq({ "hello" => "moto" }) }
|
28
|
+
it { expect(banter_message.started_at.to_s).to eq(Time.now.to_s) }
|
29
|
+
it { expect(banter_message.done_at.to_s).to eq(Time.now.to_s) }
|
30
|
+
it { expect(banter_message.worker_id).to eq(BanterWorker.current.id) }
|
31
|
+
it { expect(banter_message.status).to eq(status) }
|
32
|
+
it { expect(banter_message.error_message).to eq(error_message) }
|
33
|
+
end
|
13
34
|
|
14
35
|
before do
|
15
36
|
context_before
|
@@ -17,6 +38,7 @@ describe Banter::Server::ClientQueueListener do
|
|
17
38
|
validators.each do |validator|
|
18
39
|
Klass.validates_payload_with validator
|
19
40
|
end
|
41
|
+
Klass.subscribe_to "test.foo"
|
20
42
|
|
21
43
|
klass_instance
|
22
44
|
|
@@ -29,47 +51,89 @@ describe Banter::Server::ClientQueueListener do
|
|
29
51
|
end
|
30
52
|
|
31
53
|
context "Normal execution" do
|
32
|
-
let!(:klass_instance){
|
33
|
-
instance = Klass.new({},{}, {})
|
54
|
+
let!(:klass_instance) {
|
55
|
+
instance = Klass.new({}, {}, {})
|
34
56
|
allow(instance).to receive(:perform!)
|
35
57
|
instance
|
36
58
|
}
|
37
59
|
|
38
|
-
context "
|
39
|
-
|
40
|
-
|
60
|
+
context "banter web disabled" do
|
61
|
+
context "test exception" do
|
62
|
+
let(:no_call) { true }
|
63
|
+
it { should_not raise_exception }
|
64
|
+
end
|
65
|
+
|
66
|
+
context "call" do
|
67
|
+
it { expect(klass_instance).to have_received(:perform!).with(payload) }
|
68
|
+
it { expect(BanterMessage.count).to eq(0) }
|
69
|
+
end
|
41
70
|
end
|
42
71
|
|
43
|
-
context "
|
44
|
-
|
72
|
+
context "banter web enabled" do
|
73
|
+
let(:context_before) { enable_banter_web }
|
74
|
+
|
75
|
+
context "test exception" do
|
76
|
+
let(:no_call) { true }
|
77
|
+
it { should_not raise_exception }
|
78
|
+
end
|
79
|
+
|
80
|
+
context "call" do
|
81
|
+
banter_message_fields_are_correct(BanterMessage::STATUS_SUCCESS)
|
82
|
+
end
|
45
83
|
end
|
84
|
+
|
46
85
|
end
|
47
86
|
|
48
87
|
context "Exception during execution" do
|
49
88
|
let!(:klass_instance) {
|
50
|
-
instance = Klass.new({},{}, {})
|
51
|
-
allow(instance).to receive(:perform){
|
52
|
-
raise StandardError.new("test")
|
89
|
+
instance = Klass.new({}, {}, {})
|
90
|
+
allow(instance).to receive(:perform!) {
|
91
|
+
raise StandardError.new("test exception")
|
53
92
|
}
|
54
93
|
instance
|
55
94
|
}
|
56
|
-
let(:no_call) { true }
|
57
95
|
|
58
|
-
|
96
|
+
context "web disabled" do
|
97
|
+
before do
|
98
|
+
allow(Banter::RabbitLogger).to receive(:log)
|
99
|
+
end
|
100
|
+
it { should_not raise_exception }
|
101
|
+
it { expect(BanterMessage.count).to eq(0) }
|
102
|
+
end
|
103
|
+
|
104
|
+
context "banter web enabled" do
|
105
|
+
let(:context_before) { enable_banter_web }
|
106
|
+
|
107
|
+
it { should_not raise_exception }
|
108
|
+
it { expect(klass_instance).to have_received(:perform!).with(payload) }
|
109
|
+
banter_message_fields_are_correct(BanterMessage::STATUS_ERROR, 'test exception')
|
110
|
+
end
|
59
111
|
end
|
60
112
|
|
61
113
|
context "Payload error" do
|
62
114
|
let!(:klass_instance) {
|
63
|
-
instance = Klass.new({},{}, {})
|
64
|
-
allow(instance).to receive(:perform)
|
115
|
+
instance = Klass.new({}, {}, {})
|
116
|
+
allow(instance).to receive(:perform!).and_raise(Banter::PayloadValidationError.new("validation failed"))
|
65
117
|
instance
|
66
118
|
}
|
67
119
|
|
68
|
-
let!(:validators) { [lambda{ |payload| false }]
|
120
|
+
let!(:validators) { [lambda { |payload| false }] }
|
121
|
+
context "web disabled" do
|
122
|
+
let(:context_before) { allow(Airbrake).to receive(:notify) }
|
123
|
+
it { expect(Airbrake).to have_received(:notify) }
|
124
|
+
end
|
69
125
|
|
70
|
-
|
126
|
+
context "web enabled" do
|
127
|
+
let(:context_before) do
|
128
|
+
allow(Airbrake).to receive(:notify)
|
129
|
+
enable_banter_web
|
130
|
+
end
|
71
131
|
|
72
|
-
|
132
|
+
it { expect(Airbrake).to have_received(:notify) }
|
133
|
+
it { should_not raise_exception }
|
134
|
+
it { expect(klass_instance).to have_received(:perform!).with(payload) }
|
135
|
+
banter_message_fields_are_correct(BanterMessage::STATUS_VALIDATION_FAILED, "validation failed")
|
136
|
+
end
|
73
137
|
end
|
74
138
|
end
|
75
139
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# There isn't a good way to stub and mock methods in classes that include Celluloid
|
4
|
+
# The only workaround I have right now, is to check other methods that get called
|
5
|
+
|
6
|
+
describe Banter::Server::SubscriberServer do
|
7
|
+
subject { Banter::Server::SubscriberServer.instance }
|
8
|
+
describe '#set_workers' do
|
9
|
+
before {
|
10
|
+
allow(Banter::Server::ClientQueueListener).to receive(:new)
|
11
|
+
subject.set_workers([MyTestSubscriber1, MyTestSubscriber2])
|
12
|
+
}
|
13
|
+
|
14
|
+
it "creates queue listeners" do
|
15
|
+
expect(Banter::Server::ClientQueueListener).to have_received(:new).with(MyTestSubscriber1, "foo.bar.one", 'banter_foo_bar_one')
|
16
|
+
expect(Banter::Server::ClientQueueListener).to have_received(:new).with(MyTestSubscriber2, "foo.bar.two", 'banter_foo_bar_two')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#set_information' do
|
21
|
+
before { subject.send(:set_information)}
|
22
|
+
it { expect(subject.process_name).not_to be_nil }
|
23
|
+
it { expect(subject.pid).not_to be_nil }
|
24
|
+
it { expect(subject.hostname).not_to be_nil }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#register_workers' do
|
28
|
+
|
29
|
+
context "web not enabled" do
|
30
|
+
before { subject.send(:register_workers)}
|
31
|
+
it "doesn't create BanterWorker" do
|
32
|
+
expect(BanterWorker.count).to eq(0)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "web enabled" do
|
37
|
+
before {
|
38
|
+
Banter::Configuration.web_enabled = true
|
39
|
+
subject.set_workers([MyTestSubscriber1, MyTestSubscriber2])
|
40
|
+
subject.instance_variable_set(:@pid, 123)
|
41
|
+
subject.instance_variable_set(:@hostname, 'mymachine')
|
42
|
+
subject.send(:register_workers)
|
43
|
+
}
|
44
|
+
|
45
|
+
after {
|
46
|
+
Banter::Configuration.web_enabled = false
|
47
|
+
}
|
48
|
+
|
49
|
+
let(:banter_worker) { BanterWorker.last }
|
50
|
+
|
51
|
+
it "creates banter worker" do
|
52
|
+
expect(BanterWorker.count).to eq(1)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "sets up BanterWorker.current" do
|
56
|
+
expect(BanterWorker.current).to eq(banter_worker)
|
57
|
+
end
|
58
|
+
|
59
|
+
it { expect(banter_worker.pid).to eq(123)}
|
60
|
+
it { expect(banter_worker.hostname).to eq("mymachine")}
|
61
|
+
it { expect(banter_worker.started_at.to_s).to eq(Time.now.to_s)}
|
62
|
+
it { expect(banter_worker.worker_classes).to eq(["MyTestSubscriber1", "MyTestSubscriber2"])}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#unregister_current_worker' do
|
67
|
+
context "web enabled" do
|
68
|
+
|
69
|
+
let(:banter_worker) { FactoryGirl.create(:banter_worker) }
|
70
|
+
before {
|
71
|
+
Banter::Configuration.web_enabled = true
|
72
|
+
BanterWorker.class_variable_set(:@@current, banter_worker)
|
73
|
+
subject.send(:unregister_current_worker)
|
74
|
+
}
|
75
|
+
|
76
|
+
after {
|
77
|
+
Banter::Configuration.web_enabled = false
|
78
|
+
}
|
79
|
+
|
80
|
+
it "sets stopped_at" do
|
81
|
+
expect(banter_worker.stopped_at.to_s).to eq(Time.now.to_s)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :banter_worker do
|
3
|
+
process_name "yo whats up"
|
4
|
+
pid 123
|
5
|
+
worker_classes [ 'MyTestSubscriber1', 'MyTestSubscriber2']
|
6
|
+
hostname "example.com"
|
7
|
+
started_at { Time.now }
|
8
|
+
|
9
|
+
trait :stopped do
|
10
|
+
stopped_at { Time.now }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/spec/mongoid.yml
ADDED
data/spec/spec_helper.rb
CHANGED
@@ -5,32 +5,50 @@
|
|
5
5
|
#
|
6
6
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
7
|
|
8
|
+
|
8
9
|
require 'awesome_print'
|
9
10
|
require 'banter'
|
10
11
|
require 'banter/server'
|
11
12
|
ENV['RAILS_ENV'] ||= "test"
|
12
13
|
ENV['RACK_ENV'] ||= "test"
|
14
|
+
require 'rack/test'
|
15
|
+
require 'banter/web'
|
16
|
+
require 'timecop'
|
17
|
+
require 'factory_girl'
|
18
|
+
|
19
|
+
module RSpecMixin
|
20
|
+
include Rack::Test::Methods
|
21
|
+
def app() Banter::Web::Application end
|
22
|
+
end
|
13
23
|
|
24
|
+
# FactoryGirl.definition_file_paths = %w(../factories)
|
25
|
+
FactoryGirl.find_definitions
|
14
26
|
|
15
27
|
RSpec.configure do |config|
|
16
|
-
# config.treat_symbols_as_metadata_keys_with_true_values = true
|
17
28
|
config.run_all_when_everything_filtered = true
|
18
|
-
# Don't want to filter on anything right now.
|
19
29
|
config.filter_run :focus
|
20
|
-
|
21
|
-
# Run specs in random order to surface order dependencies. If you find an
|
22
|
-
# order dependency and want to debug it, you can fix the order by providing
|
23
|
-
# the seed, which is printed after each run.
|
24
|
-
# --seed 1234
|
25
|
-
# For now, always in same order
|
26
30
|
config.order = 'random'
|
31
|
+
config.include RSpecMixin
|
32
|
+
config.before(:each) {
|
33
|
+
BanterWorker.delete_all
|
34
|
+
BanterMessage.delete_all
|
35
|
+
}
|
36
|
+
|
37
|
+
config.before(:each) {
|
38
|
+
t = Time.new
|
39
|
+
allow(Time).to receive(:now).and_return(t)
|
40
|
+
}
|
41
|
+
|
27
42
|
end
|
28
43
|
|
29
44
|
Banter::Configuration.configure_with("test", File.expand_path("../config.yml", __FILE__))
|
30
45
|
Banter::Configuration.logger = ActiveSupport::TaggedLogging.new(Logger.new(nil))
|
31
46
|
|
32
|
-
|
47
|
+
Mongoid.load!(File.expand_path("../mongoid.yml", __FILE__))
|
48
|
+
|
49
|
+
# Test subscriber classes to make testing easier
|
33
50
|
class MyTestSubscriber1 < Banter::Subscriber
|
51
|
+
subscribe_to "foo.bar.one"
|
34
52
|
|
35
53
|
def perform(payload)
|
36
54
|
|
@@ -38,6 +56,7 @@ class MyTestSubscriber1 < Banter::Subscriber
|
|
38
56
|
end
|
39
57
|
|
40
58
|
class MyTestSubscriber2 < Banter::Subscriber
|
59
|
+
subscribe_to "foo.bar.two"
|
41
60
|
def perform(payload)
|
42
61
|
|
43
62
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
body {
|
2
|
+
font-family: 'Open Sans', sans-serif;
|
3
|
+
}
|
4
|
+
|
5
|
+
.bold {
|
6
|
+
font-weight: 700;
|
7
|
+
}
|
8
|
+
|
9
|
+
.extra-bold {
|
10
|
+
font-weight: 800;
|
11
|
+
}
|
12
|
+
|
13
|
+
.padding-large {
|
14
|
+
padding: 15px;
|
15
|
+
}
|
16
|
+
|
17
|
+
.font-size-md {
|
18
|
+
font-size: 20px;
|
19
|
+
}
|
20
|
+
|
21
|
+
.rounded-corners-md {
|
22
|
+
border-radius: 4px;
|
23
|
+
}
|
24
|
+
|
25
|
+
.spin{
|
26
|
+
-webkit-transform-origin: 50% 58%;
|
27
|
+
transform-origin:50% 58%;
|
28
|
+
-ms-transform-origin:50% 58%; /* IE 9 */
|
29
|
+
-webkit-animation: spin 2s infinite linear;
|
30
|
+
-moz-animation: spin 2s infinite linear;
|
31
|
+
-o-animation: spin 2s infinite linear;
|
32
|
+
animation: spin 2s infinite linear;
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
@-moz-keyframes spin {
|
37
|
+
from {
|
38
|
+
-moz-transform: rotate(0deg);
|
39
|
+
}
|
40
|
+
to {
|
41
|
+
-moz-transform: rotate(360deg);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
@-webkit-keyframes spin {
|
46
|
+
from {
|
47
|
+
-webkit-transform: rotate(0deg);
|
48
|
+
}
|
49
|
+
to {
|
50
|
+
-webkit-transform: rotate(360deg);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
@keyframes spin {
|
55
|
+
from {
|
56
|
+
transform: rotate(0deg);
|
57
|
+
}
|
58
|
+
to {
|
59
|
+
transform: rotate(360deg);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
pre > kbd {
|
64
|
+
background-color: transparent;
|
65
|
+
box-shadow: none;
|
66
|
+
}
|