que-web 0.7.2 → 0.9.3

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
- SHA1:
3
- metadata.gz: 70f3a29ddd4f76bdfb0a2aa84d663874366639a4
4
- data.tar.gz: e6887380327c8e50a8a4e3aeb682d4d7408c81f9
2
+ SHA256:
3
+ metadata.gz: ebaed73a196599d197e408d743f11878983bd41946128b414a761f41212f798b
4
+ data.tar.gz: cbf8d59327853afaea14ffc79d6b6633bd56c046b64b8b2200ca29251bc4b2ae
5
5
  SHA512:
6
- metadata.gz: 90343c4a7898f6085ae331a3062006032ff299704431f6e255818b9325423c54902df5f52191574bd840617953e1b6a21477083ca7c47f8922c6cd82403e6025
7
- data.tar.gz: e2b62a44728afe7c43c3d5f14fc873e3c090c792de35a589d7c1dc57df98b2bee8808bd61b88b6d4ed26cf9f4cf8a7ff25597e420fb10a0a3a78e9040a4698e1
6
+ metadata.gz: 6674c985452e1bf8c7aaf159b6efd1d0ef3008bb0020abe7625799a422e76246443c953ff5d4eb7676f8bf0cf4a39e1bee71fcdf3ac97bafafd8f9aa292f6c96
7
+ data.tar.gz: 39c94ab7f64cb5bf20c2e978aa369fd675dde28b058f52ffb4e2af4fec7c91f8d4d14b904b86d0e2f5c35ef02053be68e3b3d1a8edc02aa4d8a1e8941733436f
@@ -1,8 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
- - 2.0.0
5
- - 2.1
3
+ - 2.4
4
+ - 2.5
5
+ - 2.6
6
6
  - jruby
7
7
  notifications:
8
8
  email: false
@@ -1,4 +1,32 @@
1
- ### Unreleased
1
+ ### 0.9.3 - 2020-06-17
2
+ #### Added:
3
+ - Set expired_at=NULL when rescheduling job
4
+ - Make job search case-insensitive
5
+ - Allow to search by ActiveJob class name
6
+
7
+ ### 0.9.2 - 2020-04-24
8
+ #### Fixed:
9
+ - Fixed rendering "running" page
10
+ - Fixed displaying relative time on "failing" page
11
+
12
+ ### 0.9.1 - 2020-04-01
13
+ #### Fixed:
14
+ - Fixed rendering HTML
15
+
16
+ ### 0.9.0 - 2020-03-31
17
+ #### Added:
18
+ - Display real job class when wrapped by ActiveJob
19
+ - Updated foundation CSS to latest 5.x version
20
+ - Removed erubis gem dependency
21
+
22
+ #### Fixed:
23
+ - Fixed minitest deprecation warnings
24
+
25
+ ### 0.8 - 2018-09-21
26
+
27
+ #### Compatibility with 1.0.0.beta3 Que:
28
+ - Changed job_id to id
29
+ - Removed pg_* attributes
2
30
 
3
31
  ### 0.7.1 - 2018-03-02
4
32
 
data/README.md CHANGED
@@ -43,18 +43,6 @@ require "que/web"
43
43
  mount Que::Web => "/que"
44
44
  ```
45
45
 
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
46
  ### Authentication
59
47
 
60
48
  #### Devise
@@ -2,24 +2,24 @@ GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
4
  erubis (2.7.0)
5
- mustermann (1.0.1)
5
+ mustermann (1.0.3)
6
6
  pg (1.0.0)
7
- puma (3.11.2)
7
+ puma (3.12.3)
8
8
  que (0.14.2)
9
9
  que-web (0.7.0)
10
10
  erubis
11
11
  que (~> 0.8)
12
12
  sinatra
13
- rack (2.0.4)
14
- rack-protection (2.0.0)
13
+ rack (2.0.8)
14
+ rack-protection (2.0.7)
15
15
  rack
16
16
  sequel (5.5.0)
17
- sinatra (2.0.0)
17
+ sinatra (2.0.7)
18
18
  mustermann (~> 1.0)
19
19
  rack (~> 2.0)
20
- rack-protection (= 2.0.0)
20
+ rack-protection (= 2.0.7)
21
21
  tilt (~> 2.0)
22
- tilt (2.0.8)
22
+ tilt (2.0.10)
23
23
 
24
24
  PLATFORMS
25
25
  ruby
@@ -1,28 +1,28 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- que-web (0.7.0)
5
- erubis
6
- que (~> 0.8)
4
+ que-web (0.9.2)
5
+ que (~> 1.0.0.beta3)
7
6
  sinatra
8
7
 
9
8
  GEM
10
9
  remote: https://rubygems.org/
11
10
  specs:
12
- erubis (2.7.0)
13
- mustermann (1.0.1)
14
- pg (1.0.0)
15
- que (0.14.2)
16
- rack (2.0.4)
17
- rack-protection (2.0.0)
11
+ mustermann (1.1.1)
12
+ ruby2_keywords (~> 0.0.1)
13
+ pg (1.2.3)
14
+ que (1.0.0.beta4)
15
+ rack (2.2.2)
16
+ rack-protection (2.0.8.1)
18
17
  rack
19
- sequel (5.5.0)
20
- sinatra (2.0.0)
18
+ ruby2_keywords (0.0.2)
19
+ sequel (5.31.0)
20
+ sinatra (2.0.8.1)
21
21
  mustermann (~> 1.0)
22
22
  rack (~> 2.0)
23
- rack-protection (= 2.0.0)
23
+ rack-protection (= 2.0.8.1)
24
24
  tilt (~> 2.0)
25
- tilt (2.0.8)
25
+ tilt (2.0.10)
26
26
 
27
27
  PLATFORMS
28
28
  ruby
@@ -33,4 +33,4 @@ DEPENDENCIES
33
33
  sequel
34
34
 
35
35
  BUNDLED WITH
36
- 1.15.3
36
+ 2.1.4
@@ -7,9 +7,8 @@ require 'securerandom'
7
7
 
8
8
  Que.logger = Logger.new(STDOUT)
9
9
  Que.logger.level = Logger::INFO
10
- Que.connection = Sequel.connect "postgres://localhost/quewebtest", max_connections: Que.worker_count + 1
11
- Que.migrate!
12
- Que.mode = :async
10
+ Que.connection = Sequel.connect("postgres://localhost/quewebtest", max_connections: 1)
11
+ Que.migrate!(version: 4)
13
12
  $stdout.sync = true
14
13
 
15
14
  class FailJob < Que::Job
@@ -31,4 +30,3 @@ class SlowJob < Que::Job
31
30
  sleep 15
32
31
  end
33
32
  end
34
-
@@ -22,7 +22,7 @@ end
22
22
 
23
23
  map '/xss' do
24
24
  run lambda { |env|
25
- FailJob.enqueue '<script>alert("xss")</script>', {name: '<script>alert("xss")', age: 20, numbers: [10]*50}
25
+ FailJob.enqueue "<script>alert('xss')</script>", {name: "<script>alert('xss')", age: 20, numbers: [10]*50}
26
26
  [200, {}, ['Failing job queued']]
27
27
  }
28
28
  end
@@ -41,7 +41,6 @@ map '/slow' do
41
41
  }
42
42
  end
43
43
 
44
-
45
44
  map '/delayslow' do
46
45
  run lambda { |env|
47
46
  SlowJob.enqueue 'arg1', {name: 'delayslow', age: 20}, run_at: Time.now + 10
@@ -52,4 +51,3 @@ end
52
51
  run lambda { |env|
53
52
  [200, {}, ['Hello']]
54
53
  }
55
-
@@ -1,5 +1,5 @@
1
1
  require "sinatra/base"
2
- require "erubis"
2
+ require "cgi"
3
3
 
4
4
  module Que
5
5
  class Web < Sinatra::Base
@@ -11,7 +11,6 @@ module Que
11
11
  set :root, File.expand_path("../../../web", __FILE__)
12
12
  set :public_folder, proc { "#{root}/public" }
13
13
  set :views, proc { File.expand_path("views", root) }
14
- set :erb, :escape_html => true
15
14
 
16
15
  get "/" do
17
16
  stats = Que.execute SQL[:dashboard_stats], [search]
@@ -20,7 +19,7 @@ module Que
20
19
  end
21
20
 
22
21
  get "/running" do
23
- worker_states = search_running Que.worker_states
22
+ worker_states = search_running Que.job_states
24
23
  pager = get_pager worker_states.count
25
24
  @list = Viewmodels::JobList.new(worker_states, pager)
26
25
  erb :running
@@ -28,7 +27,7 @@ module Que
28
27
 
29
28
  get "/failing" do
30
29
  stats = Que.execute SQL[:dashboard_stats], [search]
31
- pager = get_pager stats[0]["failing"]
30
+ pager = get_pager stats[0][:failing]
32
31
  failing_jobs = Que.execute SQL[:failing_jobs], [pager.page_size, pager.offset, search]
33
32
  @list = Viewmodels::JobList.new(failing_jobs, pager)
34
33
  erb :failing
@@ -36,9 +35,8 @@ module Que
36
35
 
37
36
  get "/scheduled" do
38
37
  stats = Que.execute SQL[:dashboard_stats], [search]
39
- pager = get_pager stats[0]["scheduled"]
38
+ pager = get_pager stats[0][:scheduled]
40
39
  scheduled_jobs = Que.execute SQL[:scheduled_jobs], [pager.page_size, pager.offset, search]
41
-
42
40
  @list = Viewmodels::JobList.new(scheduled_jobs, pager)
43
41
  erb :scheduled
44
42
  end
@@ -62,12 +60,10 @@ module Que
62
60
  job_id = id.to_i
63
61
  if job_id > 0
64
62
  run_at = Time.now
65
-
66
63
  updated_rows = Que.execute SQL[:reschedule_job], [job_id, run_at]
67
-
68
64
  if updated_rows.empty?
69
65
  # Didn't get the advisory lock
70
- set_flash "warning", "Job #{job_id} not rescheduled as it was already runnning"
66
+ set_flash "warning", "Job #{job_id} not rescheduled as it was already running"
71
67
  else
72
68
  set_flash "info", "Job #{job_id} rescheduled for #{run_at}"
73
69
  end
@@ -105,7 +101,7 @@ module Que
105
101
 
106
102
  if updated_rows.empty?
107
103
  # Didn't get the advisory lock
108
- set_flash "warning", "Job #{job_id} not deleted as it was already runnning"
104
+ set_flash "warning", "Job #{job_id} not deleted as it was already running"
109
105
  else
110
106
  set_flash "info", "Job #{job_id} deleted"
111
107
  end
@@ -163,11 +159,11 @@ module Que
163
159
 
164
160
  def search_running(jobs)
165
161
  return jobs unless search_param
166
- jobs.select { |job| job.fetch('job_class').include? search_param }
162
+ jobs.select { |job| job.fetch(:job_class).include? search_param }
167
163
  end
168
164
 
169
165
  def search_param
170
- sanitised = (params['search'] || '').gsub(/[^0-9a-z:]i/, '')
166
+ sanitised = (params['search'] || '').gsub(/[^0-9a-z:]/i, '')
171
167
  return if sanitised.empty?
172
168
  sanitised
173
169
  end
@@ -183,8 +179,8 @@ module Que
183
179
  end
184
180
 
185
181
  def format_error(job)
186
- return unless job.last_error
187
- line = job.last_error.lines.first || ''
182
+ return unless job.last_error_message
183
+ line = job.last_error_message.lines.first || ''
188
184
  truncate line, 30
189
185
  end
190
186
 
@@ -209,6 +205,13 @@ module Que
209
205
  hash = session[FLASH_KEY] ||= {}
210
206
  hash[level] = val
211
207
  end
208
+
209
+ def html_escape(text)
210
+ return if text.nil?
211
+
212
+ CGI.escape_html(text)
213
+ end
214
+ alias h html_escape
212
215
  end
213
216
  helpers Helpers
214
217
  end
@@ -1,17 +1,17 @@
1
1
  lock_job_sql = <<-SQL.freeze
2
- SELECT job_id, pg_try_advisory_lock(job_id) AS locked
2
+ SELECT id, pg_try_advisory_lock(id) AS locked
3
3
  FROM que_jobs
4
- WHERE job_id = $1::bigint
4
+ WHERE id = $1::bigint
5
5
  SQL
6
6
 
7
7
  lock_all_failing_jobs_sql = <<-SQL.freeze
8
- SELECT job_id, pg_try_advisory_lock(job_id) AS locked
8
+ SELECT id, pg_try_advisory_lock(id) AS locked
9
9
  FROM que_jobs
10
10
  WHERE error_count > 0
11
11
  SQL
12
12
 
13
13
  lock_all_scheduled_jobs_sql = <<-SQL.freeze
14
- SELECT job_id, pg_try_advisory_lock(job_id) AS locked
14
+ SELECT id, pg_try_advisory_lock(id) AS locked
15
15
  FROM que_jobs
16
16
  WHERE error_count = 0
17
17
  SQL
@@ -20,11 +20,12 @@ def reschedule_all_jobs_query(scope)
20
20
  <<-SQL.freeze
21
21
  WITH target AS (#{scope})
22
22
  UPDATE que_jobs
23
- SET run_at = $1::timestamptz
23
+ SET run_at = $1::timestamptz,
24
+ expired_at = NULL
24
25
  FROM target
25
26
  WHERE target.locked
26
- AND target.job_id = que_jobs.job_id
27
- RETURNING pg_advisory_unlock(target.job_id)
27
+ AND target.id = que_jobs.id
28
+ RETURNING pg_advisory_unlock(target.id)
28
29
  SQL
29
30
  end
30
31
 
@@ -34,8 +35,8 @@ def delete_jobs_query(scope)
34
35
  DELETE FROM que_jobs
35
36
  USING target
36
37
  WHERE target.locked
37
- AND target.job_id = que_jobs.job_id
38
- RETURNING pg_advisory_unlock(target.job_id)
38
+ AND target.id = que_jobs.id
39
+ RETURNING pg_advisory_unlock(target.id)
39
40
  SQL
40
41
  end
41
42
 
@@ -50,9 +51,10 @@ Que::Web::SQL = {
50
51
  SELECT (classid::bigint << 32) + objid::bigint AS job_id
51
52
  FROM pg_locks
52
53
  WHERE locktype = 'advisory'
53
- ) locks USING (job_id)
54
+ ) locks ON (que_jobs.id=locks.job_id)
54
55
  WHERE
55
- job_class LIKE ($1)
56
+ job_class ILIKE ($1)
57
+ OR que_jobs.args #>> '{0, job_class}' ILIKE ($1)
56
58
  SQL
57
59
  failing_jobs: <<-SQL.freeze,
58
60
  SELECT que_jobs.*
@@ -61,8 +63,13 @@ Que::Web::SQL = {
61
63
  SELECT (classid::bigint << 32) + objid::bigint AS job_id
62
64
  FROM pg_locks
63
65
  WHERE locktype = 'advisory'
64
- ) locks USING (job_id)
65
- WHERE locks.job_id IS NULL AND error_count > 0 AND job_class LIKE ($3)
66
+ ) locks ON (que_jobs.id=locks.job_id)
67
+ WHERE locks.job_id IS NULL
68
+ AND error_count > 0
69
+ AND (
70
+ job_class ILIKE ($3)
71
+ OR que_jobs.args #>> '{0, job_class}' ILIKE ($3)
72
+ )
66
73
  ORDER BY run_at
67
74
  LIMIT $1::int
68
75
  OFFSET $2::int
@@ -74,8 +81,13 @@ Que::Web::SQL = {
74
81
  SELECT (classid::bigint << 32) + objid::bigint AS job_id
75
82
  FROM pg_locks
76
83
  WHERE locktype = 'advisory'
77
- ) locks USING (job_id)
78
- WHERE locks.job_id IS NULL AND error_count = 0 AND job_class LIKE ($3)
84
+ ) locks ON (que_jobs.id=locks.job_id)
85
+ WHERE locks.job_id IS NULL
86
+ AND error_count = 0
87
+ AND (
88
+ job_class ILIKE ($3)
89
+ OR que_jobs.args #>> '{0, job_class}' ILIKE ($3)
90
+ )
79
91
  ORDER BY run_at
80
92
  LIMIT $1::int
81
93
  OFFSET $2::int
@@ -86,18 +98,19 @@ Que::Web::SQL = {
86
98
  reschedule_job: <<-SQL.freeze,
87
99
  WITH target AS (#{lock_job_sql})
88
100
  UPDATE que_jobs
89
- SET run_at = $2::timestamptz
101
+ SET run_at = $2::timestamptz,
102
+ expired_at = NULL
90
103
  FROM target
91
104
  WHERE target.locked
92
- AND target.job_id = que_jobs.job_id
93
- RETURNING pg_advisory_unlock(target.job_id)
105
+ AND target.id = que_jobs.id
106
+ RETURNING pg_advisory_unlock(target.id)
94
107
  SQL
95
108
  reschedule_all_scheduled_jobs: reschedule_all_jobs_query(lock_all_scheduled_jobs_sql),
96
109
  reschedule_all_failing_jobs: reschedule_all_jobs_query(lock_all_failing_jobs_sql),
97
110
  fetch_job: <<-SQL.freeze,
98
111
  SELECT *
99
112
  FROM que_jobs
100
- WHERE job_id = $1::bigint
113
+ WHERE id = $1::bigint
101
114
  LIMIT 1
102
115
  SQL
103
116
  }.freeze
@@ -1,3 +1,5 @@
1
+ require "json"
2
+
1
3
  Dir[File.expand_path('../viewmodels/*.rb', __FILE__)].each {|f| require f}
2
4
  module Que::Web::Viewmodels
3
5
  end
@@ -2,7 +2,7 @@ module Que::Web::Viewmodels
2
2
  class Dashboard < Struct.new(:running, :scheduled, :failing)
3
3
  def initialize(stats)
4
4
  members.each do |m|
5
- self[m] = stats[m.to_s]
5
+ self[m] = stats[m]
6
6
  end
7
7
  end
8
8
  end
@@ -1,18 +1,26 @@
1
1
  module Que::Web::Viewmodels
2
2
  class Job < Struct.new(
3
- :args, :error_count, :job_class, :job_id, :last_error,
4
- :pg_backend_pid, :pg_last_query, :pg_last_query_started_at, :pg_state,
5
- :pg_state_changed_at, :pg_transaction_started_at, :pg_waiting_on_lock,
6
- :priority, :queue, :run_at)
3
+ :priority, :run_at, :id, :job_class, :error_count, :last_error_message,
4
+ :queue, :last_error_backtrace, :finished_at, :expired_at, :args, :data,
5
+ :backend_pid)
7
6
 
8
7
  def initialize(job)
9
8
  members.each do |m|
10
- self[m] = job[m.to_s]
9
+ self[m] = job[m]
11
10
  end
12
11
  end
13
12
 
14
13
  def past_due?(relative_to = Time.now)
15
14
  run_at < relative_to
16
15
  end
16
+
17
+ def humanized_job_class
18
+ case job_class
19
+ when "ActiveJob::QueueAdapters::QueAdapter::JobWrapper"
20
+ args.first[:job_class]
21
+ else
22
+ job_class
23
+ end
24
+ end
17
25
  end
18
26
  end