que-web 0.1.0 → 0.2.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 +8 -0
- data/README.md +1 -1
- data/Rakefile +2 -0
- data/examples/rack/config.ru +8 -0
- data/lib/que/web/pager.rb +23 -0
- data/lib/que/web/sql.rb +56 -0
- data/lib/que/web/viewmodels/dashboard.rb +5 -17
- data/lib/que/web/viewmodels/job.rb +1 -1
- data/lib/que/web/viewmodels/job_list.rb +5 -21
- data/lib/que/web.rb +57 -7
- data/que-web.gemspec +2 -2
- data/spec/pager_spec.rb +53 -0
- data/spec/viewmodels/dashboard_spec.rb +10 -18
- data/spec/viewmodels/job_list_spec.rb +6 -26
- data/web/public/styles/application.css +3 -0
- data/web/views/_pager.erb +15 -0
- data/web/views/failing.erb +16 -6
- data/web/views/running.erb +29 -0
- data/web/views/scheduled.erb +48 -0
- data/web/views/show.erb +53 -0
- metadata +24 -2
- data/lib/que/web/version.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af7d992b8d986583e4673a431360507a4b9cf2f1
|
4
|
+
data.tar.gz: 3443eae0f23c8d246dc9fabad39fa3f9ac0b47d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: efaeba725f9552e3d69bfd9a538f5b4256496905fddb5513db980aba1c728a65b0172a3db16f4c41c792f2aca72e79763f066b16883aabe9f31df7d78fab6c8d
|
7
|
+
data.tar.gz: d8b54ec2bbb50f3d2741369f5c80ab6185404ffec06a31d6d2948bf4426fd97f11350a5ea86a268a28da6e751b239867c839edefc7e74be994e32643dd8d5248
|
data/.travis.yml
ADDED
data/README.md
CHANGED
data/Rakefile
CHANGED
data/examples/rack/config.ru
CHANGED
@@ -33,6 +33,14 @@ map '/slow' do
|
|
33
33
|
}
|
34
34
|
end
|
35
35
|
|
36
|
+
|
37
|
+
map '/delayslow' do
|
38
|
+
run lambda { |env|
|
39
|
+
SlowJob.enqueue 'arg1', {name: 'delayslow', age: 20}, run_at: Time.now + 10
|
40
|
+
[200, {}, ['Failing job queued']]
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
36
44
|
run lambda { |env|
|
37
45
|
[200, {}, ['Hello']]
|
38
46
|
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Que::Web::Pager
|
2
|
+
attr_reader :current_page, :page_size, :total, :page_count
|
3
|
+
|
4
|
+
def initialize(page_no, page_size, total)
|
5
|
+
@current_page = page_no > 1 ? page_no : 1
|
6
|
+
@page_size = page_size
|
7
|
+
@total = total
|
8
|
+
|
9
|
+
@page_count = total > 0 ? (total / page_size.to_f).ceil : 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def next_page
|
13
|
+
@current_page < @page_count ? (@current_page + 1) : nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def prev_page
|
17
|
+
@current_page > 1 ? (@current_page - 1) : nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def offset
|
21
|
+
(@current_page - 1) * @page_size
|
22
|
+
end
|
23
|
+
end
|
data/lib/que/web/sql.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
Que::Web::SQL = {
|
2
|
+
:dashboard_stats => %{
|
3
|
+
SELECT count(*) AS total,
|
4
|
+
count(locks.job_id) AS running,
|
5
|
+
sum((error_count > 0 AND locks.job_id IS NULL)::int) AS failing,
|
6
|
+
sum((error_count = 0 AND locks.job_id IS NULL)::int) AS scheduled
|
7
|
+
FROM que_jobs
|
8
|
+
LEFT JOIN (
|
9
|
+
SELECT (classid::bigint << 32) + objid::bigint AS job_id
|
10
|
+
FROM pg_locks
|
11
|
+
WHERE locktype = 'advisory'
|
12
|
+
) locks USING (job_id)
|
13
|
+
}.freeze,
|
14
|
+
:failing_jobs => %{
|
15
|
+
SELECT que_jobs.*
|
16
|
+
FROM que_jobs
|
17
|
+
LEFT JOIN (
|
18
|
+
SELECT (classid::bigint << 32) + objid::bigint AS job_id
|
19
|
+
FROM pg_locks
|
20
|
+
WHERE locktype = 'advisory'
|
21
|
+
) locks USING (job_id)
|
22
|
+
WHERE locks.job_id IS NULL AND error_count > 0
|
23
|
+
ORDER BY run_at
|
24
|
+
LIMIT $1::int
|
25
|
+
OFFSET $2::int
|
26
|
+
}.freeze,
|
27
|
+
:scheduled_jobs => %{
|
28
|
+
SELECT que_jobs.*
|
29
|
+
FROM que_jobs
|
30
|
+
LEFT JOIN (
|
31
|
+
SELECT (classid::bigint << 32) + objid::bigint AS job_id
|
32
|
+
FROM pg_locks
|
33
|
+
WHERE locktype = 'advisory'
|
34
|
+
) locks USING (job_id)
|
35
|
+
WHERE locks.job_id IS NULL AND error_count = 0
|
36
|
+
ORDER BY run_at
|
37
|
+
LIMIT $1::int
|
38
|
+
OFFSET $2::int
|
39
|
+
}.freeze,
|
40
|
+
:delete_job => %{
|
41
|
+
DELETE
|
42
|
+
FROM que_jobs
|
43
|
+
WHERE job_id = $1::bigint
|
44
|
+
}.freeze,
|
45
|
+
:reschedule_job => %{
|
46
|
+
UPDATE que_jobs
|
47
|
+
SET run_at = $2::timestamptz
|
48
|
+
WHERE job_id = $1::bigint
|
49
|
+
}.freeze,
|
50
|
+
:fetch_job => %{
|
51
|
+
SELECT *
|
52
|
+
FROM que_jobs
|
53
|
+
WHERE job_id = $1::bigint
|
54
|
+
LIMIT 1
|
55
|
+
}.freeze,
|
56
|
+
}.freeze
|
@@ -1,21 +1,9 @@
|
|
1
1
|
module Que::Web::Viewmodels
|
2
|
-
class Dashboard
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
@failing = failing_count
|
8
|
-
end
|
9
|
-
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def calculate_running(job_stats)
|
14
|
-
job_stats.map{|s| s["count_working"]}.reduce(0, :+)
|
15
|
-
end
|
16
|
-
|
17
|
-
def calculate_scheduled(job_stats)
|
18
|
-
job_stats.map{|s| s["count"]}.reduce(0, :+)
|
2
|
+
class Dashboard < Struct.new(:running, :scheduled, :failing)
|
3
|
+
def initialize(stats)
|
4
|
+
members.each do |m|
|
5
|
+
self[m] = stats[m.to_s]
|
6
|
+
end
|
19
7
|
end
|
20
8
|
end
|
21
9
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Que::Web::Viewmodels
|
2
2
|
class Job < Struct.new(
|
3
|
-
:args, :error_count, :job_class, :job_id, :last_error,
|
3
|
+
:args, :error_count, :job_class, :job_id, :last_error,
|
4
4
|
:pg_backend_pid, :pg_last_query, :pg_last_query_started_at, :pg_state,
|
5
5
|
:pg_state_changed_at, :pg_transaction_started_at, :pg_waiting_on_lock,
|
6
6
|
:priority, :queue, :run_at)
|
@@ -1,29 +1,13 @@
|
|
1
1
|
module Que::Web::Viewmodels
|
2
2
|
class JobList
|
3
|
-
|
3
|
+
extend Forwardable
|
4
|
+
attr_reader :page_jobs, :pager
|
4
5
|
|
5
|
-
|
6
|
+
def_delegators :@pager, :total, :next_page, :prev_page, :current_page, :page_count
|
6
7
|
|
7
|
-
def initialize(page_jobs,
|
8
|
+
def initialize(page_jobs, pager)
|
8
9
|
@page_jobs = page_jobs.map{|j| Job.new(j)}
|
9
|
-
@
|
10
|
-
@page = page
|
11
|
-
end
|
12
|
-
|
13
|
-
def next_page
|
14
|
-
page.succ
|
15
|
-
end
|
16
|
-
|
17
|
-
def prev_page
|
18
|
-
page.pred
|
19
|
-
end
|
20
|
-
|
21
|
-
def has_next?
|
22
|
-
@page_jobs.length >= PAGE_SIZE
|
23
|
-
end
|
24
|
-
|
25
|
-
def has_prev?
|
26
|
-
@page > 0
|
10
|
+
@pager = pager
|
27
11
|
end
|
28
12
|
end
|
29
13
|
end
|
data/lib/que/web.rb
CHANGED
@@ -2,6 +2,9 @@ require "sinatra"
|
|
2
2
|
|
3
3
|
module Que
|
4
4
|
class Web < Sinatra::Base
|
5
|
+
VERSION = "0.2.0"
|
6
|
+
PAGE_SIZE = 10
|
7
|
+
|
5
8
|
use Rack::MethodOverride
|
6
9
|
|
7
10
|
set :root, File.expand_path("../../../web", __FILE__)
|
@@ -9,28 +12,73 @@ module Que
|
|
9
12
|
set :views, proc { File.expand_path("views", root) }
|
10
13
|
|
11
14
|
get "/" do
|
12
|
-
|
13
|
-
|
14
|
-
@dashboard = Viewmodels::Dashboard.new(job_stats, failing_count)
|
15
|
+
stats = Que.execute SQL[:dashboard_stats]
|
16
|
+
@dashboard = Viewmodels::Dashboard.new(stats[0])
|
15
17
|
erb :index
|
16
18
|
end
|
17
19
|
|
20
|
+
get "/running" do
|
21
|
+
worker_states = Que.worker_states
|
22
|
+
pager = get_pager worker_states.count
|
23
|
+
@list = Viewmodels::JobList.new(worker_states, pager)
|
24
|
+
erb :running
|
25
|
+
end
|
26
|
+
|
18
27
|
get "/failing" do
|
19
|
-
|
20
|
-
|
21
|
-
|
28
|
+
stats = Que.execute SQL[:dashboard_stats]
|
29
|
+
pager = get_pager stats[0]["failing"]
|
30
|
+
failing_jobs = Que.execute SQL[:failing_jobs], [pager.page_size, pager.offset]
|
31
|
+
@list = Viewmodels::JobList.new(failing_jobs, pager)
|
22
32
|
erb :failing
|
23
33
|
end
|
24
34
|
|
35
|
+
get "/scheduled" do
|
36
|
+
stats = Que.execute SQL[:dashboard_stats]
|
37
|
+
pager = get_pager stats[0]["scheduled"]
|
38
|
+
scheduled_jobs = Que.execute SQL[:scheduled_jobs], [pager.page_size, pager.offset]
|
39
|
+
|
40
|
+
@list = Viewmodels::JobList.new(scheduled_jobs, pager)
|
41
|
+
erb :scheduled
|
42
|
+
end
|
43
|
+
|
44
|
+
get "/jobs/:id" do |id|
|
45
|
+
job_id = id.to_i
|
46
|
+
jobs = []
|
47
|
+
if job_id > 0
|
48
|
+
jobs = Que.execute SQL[:fetch_job], [job_id]
|
49
|
+
end
|
50
|
+
|
51
|
+
if jobs.empty?
|
52
|
+
redirect to "", 303
|
53
|
+
else
|
54
|
+
@job = Viewmodels::Job.new(jobs.first)
|
55
|
+
erb :show
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
put "/jobs/:id" do |id|
|
60
|
+
job_id = id.to_i
|
61
|
+
if job_id > 0
|
62
|
+
Que.execute SQL[:reschedule_job], [job_id, Time.now]
|
63
|
+
end
|
64
|
+
|
65
|
+
redirect request.referrer, 303
|
66
|
+
end
|
67
|
+
|
25
68
|
delete "/jobs/:id" do |id|
|
26
69
|
job_id = id.to_i
|
27
70
|
if job_id > 0
|
28
|
-
Que.execute
|
71
|
+
Que.execute SQL[:delete_job], [job_id]
|
29
72
|
end
|
30
73
|
|
31
74
|
redirect request.referrer, 303
|
32
75
|
end
|
33
76
|
|
77
|
+
def get_pager(record_count)
|
78
|
+
page = (params[:page] || 1).to_i
|
79
|
+
Pager.new(page, PAGE_SIZE, record_count)
|
80
|
+
end
|
81
|
+
|
34
82
|
helpers do
|
35
83
|
def root_path
|
36
84
|
"#{env['SCRIPT_NAME']}/"
|
@@ -46,3 +94,5 @@ module Que
|
|
46
94
|
end
|
47
95
|
|
48
96
|
require "que/web/viewmodels"
|
97
|
+
require "que/web/sql"
|
98
|
+
require "que/web/pager"
|
data/que-web.gemspec
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'que/web/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
6
|
spec.name = "que-web"
|
8
|
-
spec.version = "0.
|
7
|
+
spec.version = "0.2.0"
|
9
8
|
spec.authors = ["Jason Staten"]
|
10
9
|
spec.email = ["jstaten07@gmail.com"]
|
11
10
|
spec.summary = %q{A web interface for the que queue}
|
@@ -23,4 +22,5 @@ Gem::Specification.new do |spec|
|
|
23
22
|
|
24
23
|
spec.add_development_dependency "bundler", "~> 1.6"
|
25
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "minitest", "~> 5.4"
|
26
26
|
end
|
data/spec/pager_spec.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "que/web/pager"
|
3
|
+
|
4
|
+
describe Que::Web::Pager do
|
5
|
+
subject { Que::Web::Pager.new(4, 10, 105) }
|
6
|
+
|
7
|
+
it "provides passed values" do
|
8
|
+
subject.current_page.must_equal 4
|
9
|
+
subject.page_size.must_equal 10
|
10
|
+
subject.total.must_equal 105
|
11
|
+
end
|
12
|
+
|
13
|
+
it "provides a page count" do
|
14
|
+
subject.page_count.must_equal 11
|
15
|
+
end
|
16
|
+
|
17
|
+
it "defaults to page count of 1 if total is 0" do
|
18
|
+
pager = Que::Web::Pager.new(4, 10, 0)
|
19
|
+
pager.page_count.must_equal 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it "increments next page if it exists" do
|
23
|
+
subject.next_page.must_equal 5
|
24
|
+
end
|
25
|
+
|
26
|
+
it "provides nil next page if on last page" do
|
27
|
+
pager = Que::Web::Pager.new(11, 10, 105)
|
28
|
+
pager.next_page.must_be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "decrements prev page if it exists" do
|
32
|
+
subject.prev_page.must_equal 3
|
33
|
+
end
|
34
|
+
|
35
|
+
it "provides nil prev page if on first page" do
|
36
|
+
pager = Que::Web::Pager.new(1, 10, 105)
|
37
|
+
pager.prev_page.must_be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it "determines offset" do
|
41
|
+
subject.offset.must_equal 30
|
42
|
+
end
|
43
|
+
|
44
|
+
it "sets page_no less than 1 to 1 for current page" do
|
45
|
+
pager = Que::Web::Pager.new(-3, 10, 105)
|
46
|
+
pager.current_page.must_equal 1
|
47
|
+
end
|
48
|
+
|
49
|
+
it "provides range centering current page" do
|
50
|
+
pager = Que::Web::Pager.new(-3, 10, 105)
|
51
|
+
pager.current_page.must_equal 1
|
52
|
+
end
|
53
|
+
end
|
@@ -1,25 +1,17 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Que::Web::Viewmodels::Dashboard do
|
4
|
-
let(:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
let(:dashboard_stats) {
|
5
|
+
{
|
6
|
+
"total" => 10,
|
7
|
+
"running" => 6,
|
8
|
+
"failing" => 2,
|
9
|
+
"scheduled" => 2
|
10
|
+
}
|
10
11
|
}
|
11
|
-
let(:
|
12
|
-
let(:subject) { Que::Web::Viewmodels::Dashboard.new(job_stats, failing_count) }
|
12
|
+
let(:subject) { Que::Web::Viewmodels::Dashboard.new(dashboard_stats) }
|
13
13
|
|
14
|
-
it '
|
15
|
-
subject.
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'tallies scheduled jobs' do
|
19
|
-
subject.scheduled.must_equal 17
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'uses failing jobs' do
|
23
|
-
subject.failing.must_equal failing_count
|
14
|
+
it 'passes through values' do
|
15
|
+
subject.scheduled.must_equal 2
|
24
16
|
end
|
25
17
|
end
|
@@ -10,40 +10,20 @@ describe Que::Web::Viewmodels::JobList do
|
|
10
10
|
"queue"=>"foo"
|
11
11
|
}
|
12
12
|
}
|
13
|
-
let(:
|
13
|
+
let(:pager) { Que::Web::Pager.new(1,10,105) }
|
14
|
+
let(:subject) { Que::Web::Viewmodels::JobList.new([job], pager) }
|
14
15
|
|
15
16
|
it "maps jobs" do
|
16
17
|
subject.page_jobs.length.must_equal 1
|
17
18
|
subject.page_jobs.first.queue.must_equal "foo"
|
18
19
|
end
|
19
20
|
|
20
|
-
it "
|
21
|
-
subject.
|
21
|
+
it "exposes pager" do
|
22
|
+
subject.pager.must_equal pager
|
22
23
|
end
|
23
24
|
|
24
|
-
it "
|
25
|
-
subject.
|
25
|
+
it "maps total from pager" do
|
26
|
+
subject.total.must_equal pager.total
|
26
27
|
end
|
27
28
|
|
28
|
-
it "has next when full page" do
|
29
|
-
subject.page_jobs.concat [job] * 9
|
30
|
-
subject.has_next?.must_equal true
|
31
|
-
end
|
32
|
-
|
33
|
-
it "does not have next not full page" do
|
34
|
-
subject.has_next?.must_equal false
|
35
|
-
end
|
36
|
-
|
37
|
-
it "has prev page when greater than 0" do
|
38
|
-
subject.has_prev?.must_equal true
|
39
|
-
end
|
40
|
-
|
41
|
-
it "does not have prev page when equal to 0" do
|
42
|
-
list = subject.class.new([], 1, 0)
|
43
|
-
list.has_prev?.must_equal false
|
44
|
-
end
|
45
|
-
|
46
|
-
it "does not have next not full page" do
|
47
|
-
subject.has_next?.must_equal false
|
48
|
-
end
|
49
29
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% if @list.page_count > 1 %>
|
2
|
+
<ul class="pagination">
|
3
|
+
<% if @list.prev_page %>
|
4
|
+
<li class="arrow"><a href="<%= request.path %>?page=<%= @list.prev_page %>">« Previous</a></li>
|
5
|
+
<% else %>
|
6
|
+
<li class="arrow unavailable"><a disabled>« Previous</a></li>
|
7
|
+
<% end %>
|
8
|
+
<li class="unavailable"><a disabled>Page <%= @list.current_page %> of <%= @list.page_count %></a></li>
|
9
|
+
<% if @list.next_page %>
|
10
|
+
<li class="arrow"><a href="<%= request.path %>?page=<%= @list.next_page %>">Next »</a></li>
|
11
|
+
<% else %>
|
12
|
+
<li class="arrow unavailable"><a disabled>Next »</a></li>
|
13
|
+
<% end %>
|
14
|
+
</ul>
|
15
|
+
<% end %>
|
data/web/views/failing.erb
CHANGED
@@ -14,28 +14,38 @@
|
|
14
14
|
<th>Queue</th>
|
15
15
|
<th>Args</th>
|
16
16
|
<th></th>
|
17
|
+
<th></th>
|
17
18
|
</tr>
|
18
19
|
</thead>
|
19
20
|
<tbody>
|
20
21
|
<% @list.page_jobs.each do |job| %>
|
21
22
|
<tr>
|
22
|
-
<td><%= job.run_at.utc %></td>
|
23
|
+
<td><a href="<%= to "jobs/#{job.job_id}" %>"><%= job.run_at.utc %></a></td>
|
23
24
|
<td><%= job.error_count %></td>
|
24
25
|
<td><%= job.job_class %></td>
|
25
26
|
<td><%= job.queue %></td>
|
26
27
|
<td><pre><%= job.args.map(&:inspect).join(', ') %></pre></td>
|
27
28
|
<td>
|
28
|
-
<form action="<%= to "
|
29
|
+
<form action="<%= to "jobs/#{job.job_id}" %>" method="post">
|
30
|
+
<input type="hidden" name="_method" value="put" />
|
31
|
+
<button class="plain" title="Retry Immediately"><i class="fa fa-refresh"></i></button>
|
32
|
+
</form>
|
33
|
+
</td>
|
34
|
+
<td>
|
35
|
+
<form action="<%= to "jobs/#{job.job_id}" %>" method="post">
|
29
36
|
<input type="hidden" name="_method" value="delete" />
|
30
|
-
<
|
31
|
-
<input type="hidden" name="run_at" value="<%= job.run_at %>" />
|
32
|
-
<input type="hidden" name="priority" value="<%= job.priority %>" />
|
33
|
-
<button class="plain"><i class="fa fa-trash"></i></button>
|
37
|
+
<button class="plain" title="Delete"><i class="fa fa-trash"></i></button>
|
34
38
|
</form>
|
35
39
|
</td>
|
36
40
|
</tr>
|
37
41
|
<% end %>
|
38
42
|
</tbody>
|
39
43
|
</table>
|
44
|
+
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
<div class="row">
|
48
|
+
<div class="small-12 columns">
|
49
|
+
<%= erb :_pager %>
|
40
50
|
</div>
|
41
51
|
</div>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="small-12 columns">
|
3
|
+
<h1><%= @list.total %> Running Job<%= @list.total == 1 ? "" : "s" %></h1>
|
4
|
+
</div>
|
5
|
+
</div>
|
6
|
+
<div class="row">
|
7
|
+
<div class="small-12 columns">
|
8
|
+
<table>
|
9
|
+
<thead>
|
10
|
+
<tr>
|
11
|
+
<th>Started</th>
|
12
|
+
<th>Job</th>
|
13
|
+
<th>Queue</th>
|
14
|
+
<th>Args</th>
|
15
|
+
</tr>
|
16
|
+
</thead>
|
17
|
+
<tbody>
|
18
|
+
<% @list.page_jobs.each do |job| %>
|
19
|
+
<tr>
|
20
|
+
<td><%= job.pg_state_changed_at.utc %></td>
|
21
|
+
<td><%= job.job_class %></td>
|
22
|
+
<td><%= job.queue %></td>
|
23
|
+
<td><pre><%= job.args.map(&:inspect).join(', ') %></pre></td>
|
24
|
+
</tr>
|
25
|
+
<% end %>
|
26
|
+
</tbody>
|
27
|
+
</table>
|
28
|
+
</div>
|
29
|
+
</div>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="small-12 columns">
|
3
|
+
<h1><%= @list.total %> Scheduled Job<%= @list.total == 1 ? "" : "s" %></h1>
|
4
|
+
</div>
|
5
|
+
</div>
|
6
|
+
<div class="row">
|
7
|
+
<div class="small-12 columns">
|
8
|
+
<table>
|
9
|
+
<thead>
|
10
|
+
<tr>
|
11
|
+
<th>Run At</th>
|
12
|
+
<th>Job</th>
|
13
|
+
<th>Queue</th>
|
14
|
+
<th>Args</th>
|
15
|
+
<th></th>
|
16
|
+
<th></th>
|
17
|
+
</tr>
|
18
|
+
</thead>
|
19
|
+
<tbody>
|
20
|
+
<% @list.page_jobs.each do |job| %>
|
21
|
+
<tr>
|
22
|
+
<td><a href="<%= to "jobs/#{job.job_id}" %>"><%= job.run_at.utc %></a></td>
|
23
|
+
<td><%= job.job_class %></td>
|
24
|
+
<td><%= job.queue %></td>
|
25
|
+
<td><pre><%= job.args.map(&:inspect).join(', ') %></pre></td>
|
26
|
+
<td>
|
27
|
+
<form action="<%= to "jobs/#{job.job_id}" %>" method="post">
|
28
|
+
<input type="hidden" name="_method" value="put" />
|
29
|
+
<button class="plain" title="Run Immediately"><i class="fa fa-play-circle"></i></button>
|
30
|
+
</form>
|
31
|
+
</td>
|
32
|
+
<td>
|
33
|
+
<form action="<%= to "jobs/#{job.job_id}" %>" method="post">
|
34
|
+
<input type="hidden" name="_method" value="delete" />
|
35
|
+
<button class="plain" title="Delete"><i class="fa fa-trash"></i></button>
|
36
|
+
</form>
|
37
|
+
</td>
|
38
|
+
</tr>
|
39
|
+
<% end %>
|
40
|
+
</tbody>
|
41
|
+
</table>
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
<div class="row">
|
45
|
+
<div class="small-12 columns">
|
46
|
+
<%= erb :_pager %>
|
47
|
+
</div>
|
48
|
+
</div>
|
data/web/views/show.erb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="small-12 columns">
|
3
|
+
<h1>Job <%= @job.job_id %></h1>
|
4
|
+
</div>
|
5
|
+
</div>
|
6
|
+
<div class="row">
|
7
|
+
<div class="small-12 columns">
|
8
|
+
<table>
|
9
|
+
<tbody>
|
10
|
+
<tr>
|
11
|
+
<th>Job</th>
|
12
|
+
<td><%= @job.job_class %></td>
|
13
|
+
</tr>
|
14
|
+
<tr>
|
15
|
+
<th>Queue</th>
|
16
|
+
<td><%= @job.queue %></td>
|
17
|
+
</tr>
|
18
|
+
<tr>
|
19
|
+
<th>Priority</th>
|
20
|
+
<td><%= @job.priority %></td>
|
21
|
+
</tr>
|
22
|
+
<tr>
|
23
|
+
<th>Run At</th>
|
24
|
+
<td><%= @job.run_at.utc %></td>
|
25
|
+
</tr>
|
26
|
+
<tr>
|
27
|
+
<th>Failures</th>
|
28
|
+
<td><pre><%= @job.error_count %></pre></td>
|
29
|
+
</tr>
|
30
|
+
<tr>
|
31
|
+
<th>Args</th>
|
32
|
+
<td><pre><%= @job.args.map(&:inspect).join(', ') %></pre></td>
|
33
|
+
</tr>
|
34
|
+
<tr>
|
35
|
+
<th>Last Error</th>
|
36
|
+
<td><pre><%= @job.last_error %></pre></td>
|
37
|
+
</tr>
|
38
|
+
</tbody>
|
39
|
+
</table>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
<div class="row">
|
43
|
+
<div class="small-12 columns">
|
44
|
+
<form class="form-inline" action="<%= to "/jobs/#{@job.job_id}" %>" method="post">
|
45
|
+
<input type="hidden" name="_method" value="put" />
|
46
|
+
<button><i class="fa fa-play-circle"></i> Run Immediately</button>
|
47
|
+
</form>
|
48
|
+
<form class="form-inline" maction="<%= to "/jobs/#{@job.job_id}" %>" method="post">
|
49
|
+
<input type="hidden" name="_method" value="Delete" />
|
50
|
+
<button class="button alert"><i class="fa fa-trash"></i> Delete</button>
|
51
|
+
</form>
|
52
|
+
</div>
|
53
|
+
</div>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: que-web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Staten
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.4'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.4'
|
69
83
|
description: A web interface for the que queue
|
70
84
|
email:
|
71
85
|
- jstaten07@gmail.com
|
@@ -74,6 +88,7 @@ extensions: []
|
|
74
88
|
extra_rdoc_files: []
|
75
89
|
files:
|
76
90
|
- ".gitignore"
|
91
|
+
- ".travis.yml"
|
77
92
|
- Gemfile
|
78
93
|
- LICENSE.txt
|
79
94
|
- README.md
|
@@ -84,12 +99,14 @@ files:
|
|
84
99
|
- examples/rack/boot.rb
|
85
100
|
- examples/rack/config.ru
|
86
101
|
- lib/que/web.rb
|
87
|
-
- lib/que/web/
|
102
|
+
- lib/que/web/pager.rb
|
103
|
+
- lib/que/web/sql.rb
|
88
104
|
- lib/que/web/viewmodels.rb
|
89
105
|
- lib/que/web/viewmodels/dashboard.rb
|
90
106
|
- lib/que/web/viewmodels/job.rb
|
91
107
|
- lib/que/web/viewmodels/job_list.rb
|
92
108
|
- que-web.gemspec
|
109
|
+
- spec/pager_spec.rb
|
93
110
|
- spec/spec_helper.rb
|
94
111
|
- spec/viewmodels/dashboard_spec.rb
|
95
112
|
- spec/viewmodels/job_list_spec.rb
|
@@ -111,9 +128,13 @@ files:
|
|
111
128
|
- web/public/styles/normalize.css
|
112
129
|
- web/views/_footer.erb
|
113
130
|
- web/views/_navbar.erb
|
131
|
+
- web/views/_pager.erb
|
114
132
|
- web/views/failing.erb
|
115
133
|
- web/views/index.erb
|
116
134
|
- web/views/layout.erb
|
135
|
+
- web/views/running.erb
|
136
|
+
- web/views/scheduled.erb
|
137
|
+
- web/views/show.erb
|
117
138
|
homepage: https://github.com/statianzo/que-web
|
118
139
|
licenses:
|
119
140
|
- BSD
|
@@ -139,6 +160,7 @@ signing_key:
|
|
139
160
|
specification_version: 4
|
140
161
|
summary: A web interface for the que queue
|
141
162
|
test_files:
|
163
|
+
- spec/pager_spec.rb
|
142
164
|
- spec/spec_helper.rb
|
143
165
|
- spec/viewmodels/dashboard_spec.rb
|
144
166
|
- spec/viewmodels/job_list_spec.rb
|
data/lib/que/web/version.rb
DELETED
File without changes
|