howler 1.0.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.
- 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
|