howler 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemrc +1 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +68 -0
- data/LICENSE +19 -0
- data/README.md +104 -0
- data/bin/howler +3 -0
- data/howler.gemspec +24 -0
- data/lib/howler.rb +34 -0
- data/lib/howler/async.rb +15 -0
- data/lib/howler/config.ru +4 -0
- data/lib/howler/exceptions.rb +5 -0
- data/lib/howler/exceptions/error.rb +25 -0
- data/lib/howler/exceptions/failed.rb +9 -0
- data/lib/howler/exceptions/notify.rb +15 -0
- data/lib/howler/exceptions/retry.rb +12 -0
- data/lib/howler/manager.rb +123 -0
- data/lib/howler/message.rb +15 -0
- data/lib/howler/queue.rb +138 -0
- data/lib/howler/runner.rb +34 -0
- data/lib/howler/support/config.rb +33 -0
- data/lib/howler/support/logger.rb +57 -0
- data/lib/howler/support/util.rb +23 -0
- data/lib/howler/support/version.rb +3 -0
- data/lib/howler/web.rb +47 -0
- data/lib/howler/web/public/application.css +24 -0
- data/lib/howler/web/public/bootstrap.css +3990 -0
- data/lib/howler/web/public/bootstrap.min.css +689 -0
- data/lib/howler/web/public/queues.css +19 -0
- data/lib/howler/web/views/failed_messages.erb +27 -0
- data/lib/howler/web/views/html.erb +10 -0
- data/lib/howler/web/views/index.erb +11 -0
- data/lib/howler/web/views/navigation.erb +25 -0
- data/lib/howler/web/views/notification_messages.erb +24 -0
- data/lib/howler/web/views/notifications.erb +15 -0
- data/lib/howler/web/views/pending_messages.erb +24 -0
- data/lib/howler/web/views/processed_messages.erb +28 -0
- data/lib/howler/web/views/queue.erb +36 -0
- data/lib/howler/web/views/queue_table.erb +27 -0
- data/lib/howler/web/views/queues.erb +15 -0
- data/lib/howler/worker.rb +17 -0
- data/spec/models/async_spec.rb +76 -0
- data/spec/models/exceptions/failed_spec.rb +15 -0
- data/spec/models/exceptions/message_spec.rb +53 -0
- data/spec/models/exceptions/notify_spec.rb +26 -0
- data/spec/models/exceptions/retry_spec.rb +49 -0
- data/spec/models/howler_spec.rb +69 -0
- data/spec/models/manager_spec.rb +397 -0
- data/spec/models/message_spec.rb +78 -0
- data/spec/models/queue_spec.rb +539 -0
- data/spec/models/runner_spec.rb +109 -0
- data/spec/models/support/config_spec.rb +56 -0
- data/spec/models/support/logger_spec.rb +147 -0
- data/spec/models/support/util_spec.rb +44 -0
- data/spec/models/worker_spec.rb +54 -0
- data/spec/requests/web_spec.rb +220 -0
- data/spec/spec_helper.rb +93 -0
- metadata +265 -0
@@ -0,0 +1,109 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Howler::Runner do
|
4
|
+
before do
|
5
|
+
subject.stub(:require)
|
6
|
+
subject.stub(:sleep)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#run" do
|
10
|
+
let!(:manager) { Howler::Manager.current }
|
11
|
+
|
12
|
+
before do
|
13
|
+
Howler::Manager.stub(:current).and_return(manager)
|
14
|
+
manager.stub(:run!)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should create a manager" do
|
18
|
+
Howler::Manager.should_receive(:current)
|
19
|
+
|
20
|
+
subject.run
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should run the manager" do
|
24
|
+
manager.should_receive(:run!)
|
25
|
+
|
26
|
+
subject.run
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should sleep forever" do
|
30
|
+
subject.should_receive(:sleep).with(no_args)
|
31
|
+
|
32
|
+
subject.run
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should load the Rails 3 environment" do
|
36
|
+
subject.should_receive(:require).with("./config/environment.rb")
|
37
|
+
|
38
|
+
subject.run
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "when the runner receives an Interrupt" do
|
42
|
+
before do
|
43
|
+
manager.stub(:run!).and_raise(Interrupt)
|
44
|
+
Howler::Manager.current.stub(:chewing).and_return([])
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should trap the interrupt" do
|
48
|
+
expect {
|
49
|
+
subject.run
|
50
|
+
}.not_to raise_error
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "logging" do
|
54
|
+
let!(:plain_log) { Howler::Logger.new }
|
55
|
+
let!(:log) { mock(Howler::Logger::Proxy, :info => nil, :debug => nil) }
|
56
|
+
|
57
|
+
before do
|
58
|
+
Howler::Logger.stub(:new).and_return(plain_log)
|
59
|
+
plain_log.stub(:log).and_yield(log)
|
60
|
+
|
61
|
+
Howler::Config[:shutdown_timeout] = 6
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should log information" do
|
65
|
+
log.should_receive(:info).with("INT - Stopping all workers")
|
66
|
+
plain_log.should_receive(:info).with("INT - All workers have shut down - Exiting")
|
67
|
+
|
68
|
+
subject.run
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should log debugging" do
|
72
|
+
log.should_receive(:debug).ordered.with("INT - 0 workers still working.")
|
73
|
+
|
74
|
+
subject.run
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "when there are workers still working" do
|
78
|
+
before do
|
79
|
+
Howler::Config[:concurrency] = 4
|
80
|
+
|
81
|
+
@chewing = 1.times.collect { mock(Howler::Worker) }
|
82
|
+
|
83
|
+
Howler::Manager.current.stub(:chewing).and_return(@chewing)
|
84
|
+
Howler::Manager.current.stub(:shutdown).and_return(3)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should log the number of seconds it will wait" do
|
88
|
+
log.should_receive(:info).with("INT - Waiting 6 seconds for workers to complete.")
|
89
|
+
|
90
|
+
subject.run
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should wait the specified number of seconds" do
|
94
|
+
subject.should_receive(:sleep).with(6)
|
95
|
+
|
96
|
+
subject.run
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should notify the user about the number of worker still working" do
|
100
|
+
log.should_receive(:debug).with("INT - 3 workers were shutdown immediately.")
|
101
|
+
log.should_receive(:debug).with("INT - 1 workers still working.")
|
102
|
+
|
103
|
+
subject.run
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Howler::Config do
|
4
|
+
it "should have an attribute white-list" do
|
5
|
+
Howler::Config::WHITELIST.should == %w(concurrency shutdown_timeout)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".[]" do
|
9
|
+
before do
|
10
|
+
Howler.redis.with {|redis| redis.hset("howler:config", "concurrency", "10") }
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should configure options" do
|
14
|
+
Howler::Config[:concurrency].should == "10"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe ".[]=" do
|
19
|
+
before do
|
20
|
+
Howler::Config[:message] = '{"key": 3}'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should configure options" do
|
24
|
+
Howler.redis.with {|redis| redis.hget("howler:config", "message") }.should == '{"key": 3}'
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "when the value is nil" do
|
28
|
+
it "should remove the key" do
|
29
|
+
Howler.redis.with {|redis| redis.hexists("howler:config", "message") }.should == true
|
30
|
+
|
31
|
+
Howler::Config[:message] = nil
|
32
|
+
|
33
|
+
Howler.redis.with {|redis| redis.hexists("howler:config", "message") }.should == false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ".flush" do
|
39
|
+
before do
|
40
|
+
Howler::Config[:concurrency] = 10
|
41
|
+
|
42
|
+
[:message, :flag, :boolean].each do |key|
|
43
|
+
Howler::Config[key] = "unimportant value"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
it "should clear all non-whitelisted config" do
|
47
|
+
Howler::Config.flush
|
48
|
+
|
49
|
+
[:message, :flag, :boolean].each do |key|
|
50
|
+
Howler.redis.with {|redis| redis.hget("howler:config", key.to_s) }.should be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
Howler::Config[:concurrency].to_i.should == 10
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Howler::Logger do
|
4
|
+
let!(:logger) { mock(Logger, :info => nil, :formatter= => nil) }
|
5
|
+
|
6
|
+
before do
|
7
|
+
Logger.stub(:new).and_return(logger)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".new" do
|
11
|
+
it "should log to stdout" do
|
12
|
+
Logger.should_receive(:new).with(STDOUT)
|
13
|
+
|
14
|
+
Howler::Logger.new
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should use a custom formatter" do
|
18
|
+
logger.should_receive(:formatter=).with(Howler::Logger::DefaultFormatter)
|
19
|
+
|
20
|
+
Howler::Logger.new
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "when there is log output" do
|
24
|
+
let!(:logger) { Logger.new(STDOUT) }
|
25
|
+
|
26
|
+
before do
|
27
|
+
Logger.stub(:new).and_return(logger)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#info" do
|
33
|
+
describe "when called with a message" do
|
34
|
+
it "should log to info" do
|
35
|
+
logger.should_receive(:info).with("A pertinent piece of information.")
|
36
|
+
|
37
|
+
subject.info("A pertinent piece of information.")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#debug" do
|
43
|
+
describe "when called with a message" do
|
44
|
+
it "should log to debug" do
|
45
|
+
logger.should_receive(:debug).with("A pertinent piece of debug information.")
|
46
|
+
|
47
|
+
subject.debug("A pertinent piece of debug information.")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#log" do
|
53
|
+
let(:worker) { "#<Worker id: 1>" }
|
54
|
+
|
55
|
+
describe "when given a block" do
|
56
|
+
describe "when on the main process" do
|
57
|
+
it "should log to the main process" do
|
58
|
+
logger.should_receive(:info).with("#<Worker id: 0 name: 'supervisor'>\n INFO: A supervisor level information bite.")
|
59
|
+
|
60
|
+
subject.log do |log|
|
61
|
+
log.info("A supervisor level information bite.")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should log information" do
|
67
|
+
logger.should_receive(:info).with("#<Worker id: 1>\n INFO: A pertinent piece of information.")
|
68
|
+
|
69
|
+
subject.log(worker) do |log|
|
70
|
+
log.info("A pertinent piece of information.")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "debugging" do
|
75
|
+
before do
|
76
|
+
Howler::Config[:log] = 'debug'
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should be true" do
|
80
|
+
subject.log(worker) do |log|
|
81
|
+
log.debug("anything").should == true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should log debugging information" do
|
86
|
+
logger.should_receive(:info).with("#<Worker id: 1>\n DBUG: A pertinent piece of debug information.")
|
87
|
+
|
88
|
+
subject.log(worker) do |log|
|
89
|
+
log.debug("A pertinent piece of debug information.")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should log information and debugging information" do
|
94
|
+
logger.should_receive(:info).with("#<Worker id: 1>\n INFO: A pertinent piece of information.\n DBUG: A pertinent piece of debug information.")
|
95
|
+
|
96
|
+
subject.log(worker) do |log|
|
97
|
+
log.info("A pertinent piece of information.")
|
98
|
+
log.debug("A pertinent piece of debug information.")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "information" do
|
104
|
+
before do
|
105
|
+
Howler::Config[:log] = 'info'
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should only log information" do
|
109
|
+
logger.should_not_receive(:info)
|
110
|
+
|
111
|
+
subject.log(worker) do |log|
|
112
|
+
log.debug("It's a debug thing.")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "when there is debugging" do
|
117
|
+
it "should return false" do
|
118
|
+
subject.log(worker) do |log|
|
119
|
+
log.debug("It's a debug thing.").should == false
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should not store the debug string" do
|
124
|
+
subject.log(worker) do |log|
|
125
|
+
log.info("something")
|
126
|
+
log.debug("It's a debug thing.")
|
127
|
+
|
128
|
+
log.flush.should_not match(/It's a debug thing\./)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe Howler::Logger::DefaultFormatter do
|
138
|
+
describe ".call" do
|
139
|
+
it "should have a compact format" do
|
140
|
+
Timecop.freeze(DateTime.now) do
|
141
|
+
format = Howler::Logger::DefaultFormatter.call(nil, Time.now, nil, "A Message")
|
142
|
+
format.should =~ /\[#{Time.now.strftime('%Y-%m-%d %H:%I:%M:%9N')}\]/
|
143
|
+
format.should =~ /A Message\n/
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Howler::Util do
|
4
|
+
describe ".constantize" do
|
5
|
+
it "should convert a string into a constant" do
|
6
|
+
Howler::Util.constantize("Array").should == Array
|
7
|
+
Howler::Util.constantize("Howler").should == Howler
|
8
|
+
Howler::Util.constantize("::Howler").should == Howler
|
9
|
+
Howler::Util.constantize("Howler::Util").should == Howler::Util
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should raise a NameError" do
|
13
|
+
expect {
|
14
|
+
Howler::Util.constantize("a")
|
15
|
+
}.to raise_error(NameError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise a NoMethodError" do
|
19
|
+
expect {
|
20
|
+
Howler::Util.constantize(nil)
|
21
|
+
}.to raise_error(NoMethodError)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ".now" do
|
26
|
+
it "should be properly formatted" do
|
27
|
+
Timecop.freeze(2012, 3, 24, 14, 30, 55) do
|
28
|
+
Howler::Util.now.should == "Mar 24 2012 14:30:55"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe ".at" do
|
34
|
+
it "should be properly formatted" do
|
35
|
+
Timecop.freeze(2012, 3, 24, 14, 30, 55) do
|
36
|
+
Howler::Util.at(Time.now.to_f).should == "Mar 24 2012 14:30:55"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should handle a nil time" do
|
41
|
+
Howler::Util.at(nil).should == ""
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Howler::Worker do
|
4
|
+
describe "#perform" do
|
5
|
+
let!(:queue) { Howler::Queue.new }
|
6
|
+
|
7
|
+
def build_message
|
8
|
+
Howler::Message.new(
|
9
|
+
"class" => "Howler",
|
10
|
+
"method" => "length",
|
11
|
+
"args" => [1234]
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
before do
|
16
|
+
Howler::Manager.current.wrapped_object.stub(:done_chewing)
|
17
|
+
Howler::Queue.stub(:new).and_return(queue)
|
18
|
+
@message = build_message
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should setup a Queue with the given queue name" do
|
22
|
+
Howler::Queue.should_receive(:new).with("a_queue")
|
23
|
+
|
24
|
+
subject.perform(@message, "a_queue")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should log statistics" do
|
28
|
+
queue.should_receive(:statistics).with(Howler, :length, [1234])
|
29
|
+
|
30
|
+
subject.perform(@message, "a_queue")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should execute the given message" do
|
34
|
+
array = mock(Howler)
|
35
|
+
Howler.should_receive(:new).and_return(array)
|
36
|
+
|
37
|
+
array.should_receive(:length).with(1234)
|
38
|
+
|
39
|
+
subject.perform(@message, "a_queue")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should use the specified queue" do
|
43
|
+
Howler::Queue.should_not_receive(:new)
|
44
|
+
|
45
|
+
subject.perform(@message, queue)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should register with the manager when done" do
|
49
|
+
Howler::Manager.current.wrapped_object.should_receive(:done_chewing).with(subject)
|
50
|
+
|
51
|
+
subject.perform(@message, "a_queue")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "web" do
|
4
|
+
include Capybara::DSL
|
5
|
+
let!(:queue) { Howler::Queue.new }
|
6
|
+
let(:message) do
|
7
|
+
Howler::Message.new(
|
8
|
+
'class' => 'Array',
|
9
|
+
'method' => :length,
|
10
|
+
'args' => [2345]
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#root" do
|
15
|
+
it "when viewing the navigation bar" do
|
16
|
+
visit "/"
|
17
|
+
|
18
|
+
within "#navigation" do
|
19
|
+
page.should have_content("Howler")
|
20
|
+
page.should have_content("Queues")
|
21
|
+
page.should have_content("Notifications")
|
22
|
+
page.should have_content("Statistics")
|
23
|
+
page.should have_content("Settings")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "when navigating to Queues#index" do
|
28
|
+
visit "/"
|
29
|
+
click_link "Queues"
|
30
|
+
|
31
|
+
current_path.should == "/queues"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "when navigating to Notifications#index" do
|
35
|
+
visit "/"
|
36
|
+
click_link "Notifications"
|
37
|
+
|
38
|
+
current_path.should == "/notifications"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "when navigating to Statistics#index" do
|
42
|
+
visit "/"
|
43
|
+
click_link "Statistics"
|
44
|
+
|
45
|
+
current_path.should == "/statistics"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "when navigating to Settings#index" do
|
49
|
+
visit "/"
|
50
|
+
click_link "Settings"
|
51
|
+
|
52
|
+
current_path.should == "/settings"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "Queues#index" do
|
57
|
+
it "when navigating to Queues#show" do
|
58
|
+
visit "/queues"
|
59
|
+
|
60
|
+
within "#queue_#{queue.id}" do
|
61
|
+
click_link "More..."
|
62
|
+
end
|
63
|
+
|
64
|
+
current_path.should == "/queues/#{queue.id}"
|
65
|
+
|
66
|
+
within "##{queue.id}" do
|
67
|
+
page.should have_content(queue.id)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it "when viewing queue statistics" do
|
72
|
+
6.times { queue.statistics { lambda {}}}
|
73
|
+
4.times { queue.statistics { raise "failed" }}
|
74
|
+
|
75
|
+
visit "/queues"
|
76
|
+
|
77
|
+
within "#queue_#{queue.id}" do
|
78
|
+
page.should have_content(queue.id)
|
79
|
+
page.should have_content(queue.created_at.to_s)
|
80
|
+
page.should have_content("6")
|
81
|
+
|
82
|
+
within ".error" do
|
83
|
+
page.should have_content("4")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "Queues#show" do
|
90
|
+
before do
|
91
|
+
Timecop.travel(DateTime.now)
|
92
|
+
@time = Time.now.to_f
|
93
|
+
|
94
|
+
queue.statistics(Fiber, :yield, [4567], @time) { raise Howler::Message::Retry }
|
95
|
+
|
96
|
+
Benchmark.stub(:measure).and_return("1.1 1.3 1.5 ( 1.7)", "2.1 2.3 2.5 ( 2.7)")
|
97
|
+
|
98
|
+
[[Hash, :keys, [1234]], [Array, :length, [2345]]].each do |(klass, method, args)|
|
99
|
+
queue.statistics(klass, method, args, @time) { lambda {}}
|
100
|
+
end
|
101
|
+
|
102
|
+
Howler::Manager.current.push(Logger, :info, [3456])
|
103
|
+
end
|
104
|
+
|
105
|
+
it "when viewing processed messages" do
|
106
|
+
visit "/queues/#{queue.id}"
|
107
|
+
|
108
|
+
within "#processed_messages" do
|
109
|
+
within ".table_title" do
|
110
|
+
page.should have_content("Processed Messages")
|
111
|
+
end
|
112
|
+
|
113
|
+
within ".table tr" do
|
114
|
+
["Message", "Created At", "System Runtime", "Real Runtime", "Status"].each do |value|
|
115
|
+
page.should have_content(value)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
within ".table tbody" do
|
120
|
+
page.should have_content(Howler::Util.at(@time))
|
121
|
+
|
122
|
+
%w(Hash.keys(1234) 1.5 1.7 success).each do |value|
|
123
|
+
page.should have_content(value)
|
124
|
+
end
|
125
|
+
|
126
|
+
%w(Array.length(2345) 2.5 2.7 success).each do |value|
|
127
|
+
page.should have_content(value)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
it "when viewing pending messages" do
|
134
|
+
visit "/queues/#{queue.id}"
|
135
|
+
|
136
|
+
within "#pending_messages" do
|
137
|
+
within ".table_title" do
|
138
|
+
page.should have_content("Pending Messages")
|
139
|
+
end
|
140
|
+
|
141
|
+
within ".table tr" do
|
142
|
+
["Message", "Created At", "Status"].each do |value|
|
143
|
+
page.should have_content(value)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
within ".table tbody" do
|
148
|
+
page.should have_content(Howler::Util.at(@time))
|
149
|
+
|
150
|
+
%w(Logger.info(3456) pending).each do |value|
|
151
|
+
page.should have_content(value)
|
152
|
+
end
|
153
|
+
|
154
|
+
%w(Fiber.yield(4567) retrying).each do |value|
|
155
|
+
page.should have_content(value)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
it "when viewing failed messages" do
|
162
|
+
Benchmark.unstub(:measure)
|
163
|
+
queue.statistics(Array, :length, [2345], @time) { raise Howler::Message::Failed }
|
164
|
+
|
165
|
+
visit "/queues/#{queue.id}"
|
166
|
+
|
167
|
+
within "#failed_messages" do
|
168
|
+
within ".table_title" do
|
169
|
+
page.should have_content("Failed Messages")
|
170
|
+
end
|
171
|
+
|
172
|
+
within ".table tr" do
|
173
|
+
["Message", "Created At", "Failed At", "Cause", "Status"].each do |value|
|
174
|
+
page.should have_content(value)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
within ".table tbody" do
|
179
|
+
within ".failed_at" do
|
180
|
+
page.should have_content(Howler::Util.at(@time))
|
181
|
+
end
|
182
|
+
|
183
|
+
%w(Array.length(2345) Howler::Message::Failed failed).each do |value|
|
184
|
+
page.should have_content(value)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "Notifications#index" do
|
192
|
+
describe "when there are notifications" do
|
193
|
+
before do
|
194
|
+
[:length, :collect, :max].each_with_index do |method, i|
|
195
|
+
queue.statistics(Array, method, [i*10]) { raise Howler::Message::Notify.new(generate_exception, :type => method)}
|
196
|
+
end
|
197
|
+
|
198
|
+
visit "/notifications"
|
199
|
+
end
|
200
|
+
|
201
|
+
it "when viewing the notifications table" do
|
202
|
+
within "#notifications" do
|
203
|
+
within ".table tr" do
|
204
|
+
%w(Message Notification Occurred).each do |value|
|
205
|
+
page.should have_content(value)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
within ".table tbody" do
|
210
|
+
page.should have_content(Howler::Util.at(@time))
|
211
|
+
|
212
|
+
%w(Array.length(0) Array.collect(10) Array.max(20) notified).each do |value|
|
213
|
+
page.should have_content(value)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|