que-web 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e462dea7156e236045867d2dc8738e060f62517d
4
- data.tar.gz: 8d01b77c484316f7b34a4dff2f0c61d432fbe92e
3
+ metadata.gz: 7a2be8dc64c1ad88ec87d8850ca883595b6ddd37
4
+ data.tar.gz: 2d0157762713b670c0d06be83ff0b48976164254
5
5
  SHA512:
6
- metadata.gz: dcb503d51659fcded547811282f5bee869312fc17a2006bcb36da240fcea46fb1c6de959832620c4d17b2154d8f427cb9c5d4ae1e1ea2263561551a938fbd2ed
7
- data.tar.gz: b8a3383ffec238ec16c63a07d7a78f02b306ed12482c45eba53c8a3bd564efb95a6db50c143c496b4f22a115edda3d729fbc982a3ec7db094d4558bc0d706655
6
+ metadata.gz: 14476a70a236bc448525729dda19d0c13432daa7e81568b5dcd9a640885370c3f3943277fbeb9facd224d867edf7ecb424687aebf11ed4a7cfab945ff1e8d904
7
+ data.tar.gz: e8d894075794550693695fcbb288f1ce16669e79b815c38e6b30378b773bb17629e169fc50625dbdea609d38e07d818d495ddcfca4fd902023b0e2b20ef5f517
data/README.md CHANGED
@@ -22,7 +22,9 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- In your `config.ru` add
25
+ #### With `config.ru`
26
+
27
+ Add in `config.ru`:
26
28
 
27
29
  ```ruby
28
30
  require "que/web"
@@ -32,14 +34,50 @@ map "/que" do
32
34
  end
33
35
  ```
34
36
 
35
- Or in Rails `config/routes.rb`
37
+ ### Rails
38
+
39
+ In `config/routes.rb`:
36
40
 
37
41
  ```ruby
38
42
  require "que/web"
39
43
  mount Que::Web => "/que"
40
44
  ```
41
45
 
42
- If you want to use Docker, run:
46
+ #### Rails 5.0
47
+
48
+ You must use the master branch of Sinatra for `que-web`.
49
+ In your gemfile:
50
+
51
+ ```
52
+ gem 'que-web'
53
+ gem 'sinatra', git: 'https://github.com/sinatra/sinatra'
54
+ ```
55
+
56
+ See https://github.com/sinatra/sinatra/issues/1071
57
+
58
+ ### Authentication
59
+
60
+ #### Devise
61
+ ```ruby
62
+ # config/routes.rb
63
+ authenticate :user do
64
+ mount Que::Web, at: 'que'
65
+ end
66
+ ```
67
+
68
+ #### Basic HTTP auth
69
+
70
+ In `config/initializers/queweb.rb`:
71
+ ```ruby
72
+ Que::Web.use(Rack::Auth::Basic) do |user, password|
73
+ [user, password] == [ENV["QUEWEB_USERNAME"], ENV["QUEWEB_PASSWORD"]]
74
+ end
75
+ ```
76
+ Then add the two environment variables to your production environment.
77
+
78
+ ### Docker
79
+
80
+ Run:
43
81
  ```
44
82
  docker run -e DATABASE_URL=postgres://username:password@hostname/db_name -p 3002:8080 joevandyk/que-web
45
83
  ```
data/lib/que/web.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "sinatra"
1
+ require "sinatra/base"
2
2
  require "erubis"
3
3
 
4
4
  module Que
@@ -14,30 +14,30 @@ module Que
14
14
  set :erb, :escape_html => true
15
15
 
16
16
  get "/" do
17
- stats = Que.execute SQL[:dashboard_stats]
17
+ stats = Que.execute SQL[:dashboard_stats], [search]
18
18
  @dashboard = Viewmodels::Dashboard.new(stats[0])
19
19
  erb :index
20
20
  end
21
21
 
22
22
  get "/running" do
23
- worker_states = Que.worker_states
23
+ worker_states = search_running Que.worker_states
24
24
  pager = get_pager worker_states.count
25
25
  @list = Viewmodels::JobList.new(worker_states, pager)
26
26
  erb :running
27
27
  end
28
28
 
29
29
  get "/failing" do
30
- stats = Que.execute SQL[:dashboard_stats]
30
+ stats = Que.execute SQL[:dashboard_stats], [search]
31
31
  pager = get_pager stats[0]["failing"]
32
- failing_jobs = Que.execute SQL[:failing_jobs], [pager.page_size, pager.offset]
32
+ failing_jobs = Que.execute SQL[:failing_jobs], [pager.page_size, pager.offset, search]
33
33
  @list = Viewmodels::JobList.new(failing_jobs, pager)
34
34
  erb :failing
35
35
  end
36
36
 
37
37
  get "/scheduled" do
38
- stats = Que.execute SQL[:dashboard_stats]
38
+ stats = Que.execute SQL[:dashboard_stats], [search]
39
39
  pager = get_pager stats[0]["scheduled"]
40
- scheduled_jobs = Que.execute SQL[:scheduled_jobs], [pager.page_size, pager.offset]
40
+ scheduled_jobs = Que.execute SQL[:scheduled_jobs], [pager.page_size, pager.offset, search]
41
41
 
42
42
  @list = Viewmodels::JobList.new(scheduled_jobs, pager)
43
43
  erb :scheduled
@@ -85,6 +85,21 @@ module Que
85
85
  Pager.new(page, PAGE_SIZE, record_count)
86
86
  end
87
87
 
88
+ def search
89
+ return '%' unless search_param.present?
90
+ "%#{search_param}%"
91
+ end
92
+
93
+ def search_running(jobs)
94
+ return jobs unless search_param.present?
95
+ jobs.select { |job| job.job_class.include? search_param }
96
+ end
97
+
98
+ def search_param
99
+ return unless params['search'].present?
100
+ params['search'].gsub(/[^0-9A-Za-z:]/, '')
101
+ end
102
+
88
103
  after { session[FLASH_KEY] = {} if @sweep_flash }
89
104
 
90
105
  helpers do
@@ -92,6 +107,15 @@ module Que
92
107
  "#{env['SCRIPT_NAME']}/"
93
108
  end
94
109
 
110
+ def link_to(path)
111
+ to path_with_search(path)
112
+ end
113
+
114
+ def path_with_search(path)
115
+ path += "?search=#{search_param}" if search_param.present?
116
+ path
117
+ end
118
+
95
119
  def active_class(pattern)
96
120
  if request.path.match pattern
97
121
  "active"
@@ -109,9 +133,6 @@ module Que
109
133
  end
110
134
 
111
135
  def relative_time(time)
112
- if time.is_a?(String)
113
- time = Time.parse(time)
114
- end
115
136
  %{<time class="timeago" datetime="#{time.utc.iso8601}">#{time.utc}</time>}
116
137
  end
117
138
 
data/lib/que/web/sql.rb CHANGED
@@ -1,56 +1,58 @@
1
1
  Que::Web::SQL = {
2
- :dashboard_stats => %{
3
- SELECT count(*) AS total,
4
- count(locks.job_id) AS running,
5
- coalesce(sum((error_count > 0 AND locks.job_id IS NULL)::int), 0) AS failing,
6
- coalesce(sum((error_count = 0 AND locks.job_id IS NULL)::int), 0) 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,
2
+ dashboard_stats: <<-SQL.freeze,
3
+ SELECT count(*) AS total,
4
+ count(locks.job_id) AS running,
5
+ coalesce(sum((error_count > 0 AND locks.job_id IS NULL)::int), 0) AS failing,
6
+ coalesce(sum((error_count = 0 AND locks.job_id IS NULL)::int), 0) 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
+ WHERE
14
+ job_class LIKE ($1)
15
+ SQL
16
+ failing_jobs: <<-SQL.freeze,
17
+ SELECT que_jobs.*
18
+ FROM que_jobs
19
+ LEFT JOIN (
20
+ SELECT (classid::bigint << 32) + objid::bigint AS job_id
21
+ FROM pg_locks
22
+ WHERE locktype = 'advisory'
23
+ ) locks USING (job_id)
24
+ WHERE locks.job_id IS NULL AND error_count > 0 AND job_class LIKE ($3)
25
+ ORDER BY run_at
26
+ LIMIT $1::int
27
+ OFFSET $2::int
28
+ SQL
29
+ scheduled_jobs: <<-SQL.freeze,
30
+ SELECT que_jobs.*
31
+ FROM que_jobs
32
+ LEFT JOIN (
33
+ SELECT (classid::bigint << 32) + objid::bigint AS job_id
34
+ FROM pg_locks
35
+ WHERE locktype = 'advisory'
36
+ ) locks USING (job_id)
37
+ WHERE locks.job_id IS NULL AND error_count = 0 AND job_class LIKE ($3)
38
+ ORDER BY run_at
39
+ LIMIT $1::int
40
+ OFFSET $2::int
41
+ SQL
42
+ delete_job: <<-SQL.freeze,
43
+ DELETE
44
+ FROM que_jobs
45
+ WHERE job_id = $1::bigint
46
+ SQL
47
+ reschedule_job: <<-SQL.freeze,
48
+ UPDATE que_jobs
49
+ SET run_at = $2::timestamptz
50
+ WHERE job_id = $1::bigint
51
+ SQL
52
+ fetch_job: <<-SQL.freeze,
53
+ SELECT *
54
+ FROM que_jobs
55
+ WHERE job_id = $1::bigint
56
+ LIMIT 1
57
+ SQL
56
58
  }.freeze
data/que-web.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "que-web"
7
- spec.version = "0.4.0"
7
+ spec.version = "0.5.0"
8
8
  spec.authors = ["Jason Staten"]
9
9
  spec.email = ["jstaten07@gmail.com"]
10
10
  spec.summary = %q{A web interface for the que queue}
@@ -71,3 +71,7 @@ pre {
71
71
  i.subtle {
72
72
  color: #999999;
73
73
  }
74
+
75
+ .search {
76
+ margin-top: 15px;
77
+ }
@@ -1,14 +1,14 @@
1
1
  <nav class="top-bar" data-topbar role="navigation">
2
2
  <ul class="title-area">
3
3
  <li class="name">
4
- <h1><a href="<%= root_path %>">Que</a></h1>
4
+ <h1><a href="<%= path_with_search root_path %>">Que</a></h1>
5
5
  </li>
6
6
  </ul>
7
7
  <section class="top-bar-section">
8
8
  <ul class="left">
9
- <li class="<%= active_class('running') %>"><a href="<%= to 'running' %>"><span>Running</span></a></li>
10
- <li class="<%= active_class('scheduled') %>"><a href="<%= to 'scheduled' %>"><span>Scheduled</span></a></li>
11
- <li class="<%= active_class('failing') %>"><a href="<%= to 'failing' %>"><span>Failing</span></a></li>
9
+ <li class="<%= active_class('running') %>"><a href="<%= link_to 'running' %>"><span>Running</span></a></li>
10
+ <li class="<%= active_class('scheduled') %>"><a href="<%= link_to 'scheduled' %>"><span>Scheduled</span></a></li>
11
+ <li class="<%= active_class('failing') %>"><a href="<%= link_to 'failing' %>"><span>Failing</span></a></li>
12
12
  </ul>
13
13
  <ul class="right version">
14
14
  <li>Que <%= Que::Version %></li>
@@ -0,0 +1,10 @@
1
+ <form class="search" action="<%= request.path %>" method="get">
2
+ <div class="row collapse">
3
+ <div class="small-8 columns">
4
+ <input type="text" name="search" value="<%= search_param %>" />
5
+ </div>
6
+ <div class="small-4 columns">
7
+ <button class="button postfix">Search</button>
8
+ </div>
9
+ </div>
10
+ </form>
@@ -1,7 +1,10 @@
1
1
  <div class="row">
2
- <div class="small-12 columns">
2
+ <div class="small-12 medium-8 columns">
3
3
  <h1><%= @list.total %> Failing Job<%= @list.total == 1 ? "" : "s" %></h1>
4
4
  </div>
5
+ <div class="small-12 medium-4 columns">
6
+ <%== erb :_search %>
7
+ </div>
5
8
  </div>
6
9
  <div class="row">
7
10
  <div class="small-12 columns">
@@ -21,7 +24,7 @@
21
24
  <tbody>
22
25
  <% @list.page_jobs.each do |job| %>
23
26
  <tr>
24
- <td><a href="<%= to "jobs/#{job.job_id}" %>">
27
+ <td><a href="<%= link_to "jobs/#{job.job_id}" %>">
25
28
  <%== relative_time job.run_at %></a>
26
29
  <%== erb :_past_due, locals: {job: job} %>
27
30
  </td>
@@ -31,13 +34,13 @@
31
34
  <td><pre><%= format_args job %></pre></td>
32
35
  <td><%= format_error job %></pre></td>
33
36
  <td>
34
- <form action="<%= to "jobs/#{job.job_id}" %>" method="post">
37
+ <form action="<%= link_to "jobs/#{job.job_id}" %>" method="post">
35
38
  <input type="hidden" name="_method" value="put" />
36
39
  <button class="plain" title="Retry Immediately"><i class="fa fa-refresh"></i></button>
37
40
  </form>
38
41
  </td>
39
42
  <td>
40
- <form action="<%= to "jobs/#{job.job_id}" %>" method="post">
43
+ <form action="<%= link_to "jobs/#{job.job_id}" %>" method="post">
41
44
  <input type="hidden" name="_method" value="delete" />
42
45
  <button class="plain" title="Delete"><i class="fa fa-trash"></i></button>
43
46
  </form>
data/web/views/index.erb CHANGED
@@ -1,10 +1,13 @@
1
1
  <div class="row">
2
- <div class="small-12 columns">
2
+ <div class="small-12 medium-8 columns">
3
3
  <h1>Jobs</h1>
4
4
  </div>
5
+ <div class="small-12 medium-4 columns">
6
+ <%== erb :_search %>
7
+ </div>
5
8
  </div>
6
9
  <div class="row">
7
- <a class="small-12 large-4 columns" href="<%= to 'running' %>">
10
+ <a class="small-12 large-4 columns" href="<%= link_to 'running' %>">
8
11
  <div class="dashboard-stat running">
9
12
  <div class="cell">
10
13
  <h2>Running<h2>
@@ -14,7 +17,7 @@
14
17
  </div>
15
18
  </div>
16
19
  </a>
17
- <a class="small-12 large-4 columns" href="<%= to 'scheduled' %>">
20
+ <a class="small-12 large-4 columns" href="<%= link_to 'scheduled' %>">
18
21
  <div class="dashboard-stat scheduled">
19
22
  <div class="cell">
20
23
  <h2>Scheduled<h2>
@@ -24,7 +27,7 @@
24
27
  </div>
25
28
  </div>
26
29
  </a>
27
- <a class="small-12 large-4 columns" href="<%= to 'failing' %>">
30
+ <a class="small-12 large-4 columns" href="<%= link_to 'failing' %>">
28
31
  <div class="dashboard-stat failing">
29
32
  <div class="cell">
30
33
  <h2>Failing<h2>
@@ -1,7 +1,10 @@
1
1
  <div class="row">
2
- <div class="small-12 columns">
2
+ <div class="small-12 medium-8 columns">
3
3
  <h1><%= @list.total %> Running Job<%= @list.total == 1 ? "" : "s" %></h1>
4
4
  </div>
5
+ <div class="small-12 medium-4 columns">
6
+ <%== erb :_search %>
7
+ </div>
5
8
  </div>
6
9
  <div class="row">
7
10
  <div class="small-12 columns">
@@ -1,7 +1,10 @@
1
1
  <div class="row">
2
- <div class="small-12 columns">
2
+ <div class="small-12 medium-8 columns">
3
3
  <h1><%= @list.total %> Scheduled Job<%= @list.total == 1 ? "" : "s" %></h1>
4
4
  </div>
5
+ <div class="small-12 medium-4 columns">
6
+ <%== erb :_search %>
7
+ </div>
5
8
  </div>
6
9
  <div class="row">
7
10
  <div class="small-12 columns">
@@ -20,20 +23,20 @@
20
23
  <% @list.page_jobs.each do |job| %>
21
24
  <tr>
22
25
  <td>
23
- <a href="<%= to "jobs/#{job.job_id}" %>"><%== relative_time job.run_at %></a>
26
+ <a href="<%= link_to "jobs/#{job.job_id}" %>"><%== relative_time job.run_at %></a>
24
27
  <%== erb :_past_due, locals: {job: job}%>
25
28
  </td>
26
29
  <td><%= job.job_class %></td>
27
30
  <td><%= job.queue %></td>
28
31
  <td><pre><%= format_args job %></pre></td>
29
32
  <td>
30
- <form action="<%= to "jobs/#{job.job_id}" %>" method="post">
33
+ <form action="<%= link_to "jobs/#{job.job_id}" %>" method="post">
31
34
  <input type="hidden" name="_method" value="put" />
32
35
  <button class="plain" title="Run Immediately"><i class="fa fa-play-circle"></i></button>
33
36
  </form>
34
37
  </td>
35
38
  <td>
36
- <form action="<%= to "jobs/#{job.job_id}" %>" method="post">
39
+ <form action="<%= link_to "jobs/#{job.job_id}" %>" method="post">
37
40
  <input type="hidden" name="_method" value="delete" />
38
41
  <button class="plain" title="Delete"><i class="fa fa-trash"></i></button>
39
42
  </form>
data/web/views/show.erb CHANGED
@@ -44,11 +44,11 @@
44
44
  </div>
45
45
  <div class="row">
46
46
  <div class="small-12 columns">
47
- <form class="form-inline" action="<%= to "/jobs/#{@job.job_id}" %>" method="post">
47
+ <form class="form-inline" action="<%= link_to "/jobs/#{@job.job_id}" %>" method="post">
48
48
  <input type="hidden" name="_method" value="put" />
49
49
  <button><i class="fa fa-play-circle"></i> Run Immediately</button>
50
50
  </form>
51
- <form class="form-inline" maction="<%= to "/jobs/#{@job.job_id}" %>" method="post">
51
+ <form class="form-inline" maction="<%= link_to "/jobs/#{@job.job_id}" %>" method="post">
52
52
  <input type="hidden" name="_method" value="Delete" />
53
53
  <button class="button alert"><i class="fa fa-trash"></i> Delete</button>
54
54
  </form>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: que-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Staten
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-09 00:00:00.000000000 Z
11
+ date: 2017-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: que
@@ -150,6 +150,7 @@ files:
150
150
  - web/views/_navbar.erb
151
151
  - web/views/_pager.erb
152
152
  - web/views/_past_due.erb
153
+ - web/views/_search.erb
153
154
  - web/views/failing.erb
154
155
  - web/views/index.erb
155
156
  - web/views/layout.erb
@@ -176,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
176
177
  version: '0'
177
178
  requirements: []
178
179
  rubyforge_project:
179
- rubygems_version: 2.2.2
180
+ rubygems_version: 2.6.11
180
181
  signing_key:
181
182
  specification_version: 4
182
183
  summary: A web interface for the que queue