delayed_job_ui 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +17 -0
- data/app/assets/javascripts/delayed_job_ui.js +52 -0
- data/app/assets/javascripts/jquery.dataTables.js +14622 -0
- data/app/assets/stylesheets/delayed_job_ui.scss +146 -0
- data/app/controllers/delayed_job_ui/main_controller.rb +34 -0
- data/app/helpers/delayed_job_ui/main_helper.rb +7 -0
- data/app/views/delayed_job_ui/_job.html.haml +37 -0
- data/app/views/delayed_job_ui/_job_table.html.haml +17 -0
- data/app/views/delayed_job_ui/_ui_layout.html.haml +42 -0
- data/delayed_job_ui.gemspec +23 -0
- data/lib/delayed_job_ui/engine.rb +12 -0
- data/lib/delayed_job_ui/jobs.rb +27 -0
- data/lib/delayed_job_ui.rb +6 -0
- metadata +102 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
#delayed-job-ui {
|
2
|
+
* {
|
3
|
+
box-sizing: border-box;
|
4
|
+
&:before, &:after {
|
5
|
+
box-sizing: inherit;
|
6
|
+
}
|
7
|
+
}
|
8
|
+
|
9
|
+
.panel {
|
10
|
+
border-radius: 0;
|
11
|
+
background: white;
|
12
|
+
box-shadow: 0px 0px 1px rgba(0,0,0,0.2);
|
13
|
+
|
14
|
+
.content {
|
15
|
+
margin-top: 20px;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
dl {
|
20
|
+
dt {
|
21
|
+
font-size: 80%;
|
22
|
+
color: #999;
|
23
|
+
width: 60px;
|
24
|
+
float: left;
|
25
|
+
padding-top: 1px;
|
26
|
+
text-align: right;
|
27
|
+
}
|
28
|
+
dd {
|
29
|
+
margin-bottom: 10px;
|
30
|
+
margin-left: 70px;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
.tabs {
|
35
|
+
background: #eee;
|
36
|
+
li {
|
37
|
+
float: left;
|
38
|
+
list-style: none;
|
39
|
+
margin-bottom: 0;
|
40
|
+
|
41
|
+
a.tab-title {
|
42
|
+
position: relative;
|
43
|
+
color: #A1A1A1;
|
44
|
+
background: #F4F4F4;
|
45
|
+
border-top: 4px solid #ddd;
|
46
|
+
box-shadow: 1px 0px 1px rgba(0,0,0,0.2);
|
47
|
+
margin-right: 5px;
|
48
|
+
padding: 10px 40px;
|
49
|
+
display: block;
|
50
|
+
z-index: 10;
|
51
|
+
top: 1px;
|
52
|
+
|
53
|
+
&.active {
|
54
|
+
top: 1px;
|
55
|
+
color: black;
|
56
|
+
border-top: 5px solid #D65F75;
|
57
|
+
background: white;
|
58
|
+
border-bottom: none;
|
59
|
+
border-right: none;
|
60
|
+
box-shadow: 1px -2px 1px rgba(0,0,0,0.2);
|
61
|
+
z-index: 999;
|
62
|
+
}
|
63
|
+
|
64
|
+
&:hover {
|
65
|
+
background: white;
|
66
|
+
text-decoration: none;
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
.delayed_job_ui_button {
|
73
|
+
padding: 10px 16px;
|
74
|
+
margin: 0;
|
75
|
+
line-height: 11px;
|
76
|
+
background: #1ABC9C;
|
77
|
+
border: none;
|
78
|
+
border-bottom: 2px solid rgba(0,0,0,0.1);
|
79
|
+
color: white;
|
80
|
+
border-radius: 3px;
|
81
|
+
font-size: 12px;
|
82
|
+
cursor: pointer;
|
83
|
+
|
84
|
+
&:hover {
|
85
|
+
background: #17A88C;
|
86
|
+
}
|
87
|
+
|
88
|
+
&.delete {
|
89
|
+
background: #D65F75;
|
90
|
+
&:hover {
|
91
|
+
background: #C05569
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
.delayed_job {
|
97
|
+
margin-bottom: 20px;
|
98
|
+
}
|
99
|
+
|
100
|
+
.cf {
|
101
|
+
&:before, &:after {
|
102
|
+
display: table;
|
103
|
+
content: '';
|
104
|
+
clear: both;
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
.inline-block {
|
109
|
+
display: inline-block;
|
110
|
+
}
|
111
|
+
|
112
|
+
table.dataTable {
|
113
|
+
.ui-state-default {
|
114
|
+
background-color: #F2F2F2;
|
115
|
+
border-bottom: 1px solid #E0E0E0;
|
116
|
+
}
|
117
|
+
td {
|
118
|
+
background-color: white;
|
119
|
+
border-bottom: 1px solid lightgray;
|
120
|
+
vertical-align: top;
|
121
|
+
&.sorting_1 {
|
122
|
+
background-color: #F2F2F2;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
th {
|
126
|
+
border-left: none;
|
127
|
+
border-right: none;
|
128
|
+
border-top: 1px solid #E0E0E0;
|
129
|
+
border-bottom: 1px solid #E0E0E0;
|
130
|
+
color: #999999;
|
131
|
+
font-weight: bold;
|
132
|
+
font-size:10px;
|
133
|
+
line-height:10px;
|
134
|
+
text-transform:uppercase;
|
135
|
+
}
|
136
|
+
tr {
|
137
|
+
background-color: white;
|
138
|
+
&.even > td, &.odd > td {
|
139
|
+
&.highlight {
|
140
|
+
background-color: #F2F2F2;
|
141
|
+
}
|
142
|
+
background-color: white;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module DelayedJobUi
|
2
|
+
class MainController < ::ApplicationController
|
3
|
+
def invoke
|
4
|
+
begin
|
5
|
+
@job = Delayed::Job.find(params[:id])
|
6
|
+
@job.invoke_job
|
7
|
+
rescue => e
|
8
|
+
failed_job(e)
|
9
|
+
else
|
10
|
+
@job.delete # if successful, destroy the job.
|
11
|
+
end
|
12
|
+
redirect_to params[:return_url]
|
13
|
+
end
|
14
|
+
|
15
|
+
def destroy
|
16
|
+
@job = Delayed::Job.find(params[:id])
|
17
|
+
@job.destroy!
|
18
|
+
redirect_to params[:return_url]
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def failed_job(e)
|
24
|
+
puts "[DelayedJobUi] This job failed"
|
25
|
+
puts e.message
|
26
|
+
ap e.backtrace
|
27
|
+
@job.failed_at = Time.zone.now
|
28
|
+
@job.last_error = e.message
|
29
|
+
@job.attempts += 1
|
30
|
+
@job.save
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
- handler = YAML.load(job.handler)
|
2
|
+
- object = handler.instance_variable_get(:@object)
|
3
|
+
- args = handler.instance_variable_get(:@args)
|
4
|
+
- method_name = handler.instance_variable_get(:@method_name)
|
5
|
+
|
6
|
+
%tr.delayed_job
|
7
|
+
%td= job.id
|
8
|
+
%td= object.class if object
|
9
|
+
%td= object.id if object
|
10
|
+
%td= method_name if method_name
|
11
|
+
%td= job.priority
|
12
|
+
%td= job.attempts
|
13
|
+
%td
|
14
|
+
- if job.run_at
|
15
|
+
= job.run_at.strftime("%D %T %Z")
|
16
|
+
%td
|
17
|
+
- if job.last_error
|
18
|
+
= h job.last_error
|
19
|
+
%td
|
20
|
+
- if job.locked_at
|
21
|
+
= h job.locked_at
|
22
|
+
%td
|
23
|
+
- if job.locked_by
|
24
|
+
= h job.locked_by
|
25
|
+
%td
|
26
|
+
- if job.failed_at
|
27
|
+
= h job.failed_at
|
28
|
+
%td
|
29
|
+
= form_tag delayed_job_ui.invoke_path, :method => :post, :class => 'inline-block' do
|
30
|
+
= hidden_field_tag :id, job.id
|
31
|
+
= hidden_field_tag :return_url, request.original_url
|
32
|
+
= submit_tag 'Run Job', :class => 'delayed_job_ui_button'
|
33
|
+
|
34
|
+
= form_tag delayed_job_ui.destroy_path, :method => :delete, :class => 'inline-block' do
|
35
|
+
= hidden_field_tag :id, job.id
|
36
|
+
= hidden_field_tag :return_url, request.original_url
|
37
|
+
= submit_tag 'Delete Job', :class => 'delayed_job_ui_button delete'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
%table.job_table
|
2
|
+
%thead
|
3
|
+
%th Job ID
|
4
|
+
%th Object Class
|
5
|
+
%th Object ID
|
6
|
+
%th Method
|
7
|
+
%th Priority
|
8
|
+
%th Attempts
|
9
|
+
%th Run At
|
10
|
+
%th Last Error
|
11
|
+
%th Locked At
|
12
|
+
%th Locked By
|
13
|
+
%th Failed At
|
14
|
+
%th Actions
|
15
|
+
%tbody
|
16
|
+
- DelayedJobUi::Jobs.jobs(type).each do |job|
|
17
|
+
= render :partial => 'delayed_job_ui/job', :locals => {:job => job}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
= stylesheet_link_tag "delayed_job_ui"
|
2
|
+
= javascript_include_tag 'delayed_job_ui'
|
3
|
+
|
4
|
+
#delayed-job-ui
|
5
|
+
%ul.tabs.cf
|
6
|
+
%li
|
7
|
+
= link_to 'Overview', '#overview', :class => 'tab-title link_to_tab active'
|
8
|
+
%li
|
9
|
+
= link_to 'Enqueued', '#enqueued', :class => 'tab-title link_to_tab'
|
10
|
+
%li
|
11
|
+
= link_to 'Working', '#working', :class => 'tab-title link_to_tab'
|
12
|
+
%li
|
13
|
+
= link_to 'Pending', '#pending', :class => 'tab-title link_to_tab'
|
14
|
+
%li
|
15
|
+
= link_to 'Failed', '#failed', :class => 'tab-title link_to_tab'
|
16
|
+
.panel
|
17
|
+
.content
|
18
|
+
#overview.tab-content
|
19
|
+
%h2 Overview
|
20
|
+
%table
|
21
|
+
%thead
|
22
|
+
%tr
|
23
|
+
%th Type
|
24
|
+
%th Count
|
25
|
+
%tbody
|
26
|
+
- DelayedJobUi::Jobs.job_count.each do |type, count|
|
27
|
+
%tr
|
28
|
+
%td= link_to type.to_s.capitalize, "##{type}", :class => 'link_to_tab'
|
29
|
+
%td= count
|
30
|
+
|
31
|
+
#enqueued.tab-content
|
32
|
+
%h2 Enqueued
|
33
|
+
= render 'delayed_job_ui/job_table', :type => :enqueued
|
34
|
+
#working.tab-content
|
35
|
+
%h2 Working
|
36
|
+
= render 'delayed_job_ui/job_table', :type => :working
|
37
|
+
#pending.tab-content
|
38
|
+
%h2 Pending
|
39
|
+
= render 'delayed_job_ui/job_table', :type => :pending
|
40
|
+
#failed.tab-content
|
41
|
+
%h2 Failed
|
42
|
+
= render 'delayed_job_ui/job_table', :type => :failed
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'delayed_job_ui'
|
3
|
+
s.version = '0.0.0'
|
4
|
+
s.date = '2014-09-18'
|
5
|
+
s.summary = 'A UI wrapper for DelayedJob'
|
6
|
+
s.description = s.summary
|
7
|
+
s.author = 'Sean Woojin Kim'
|
8
|
+
s.email = 'seanwoojinkim@gmail.com'
|
9
|
+
s.files = [
|
10
|
+
"Gemfile",
|
11
|
+
"delayed_job_ui.gemspec",
|
12
|
+
] + %x{ git ls-files }.split("\n").select { |d| d =~ %r{^(lib|test|app)} }
|
13
|
+
s.extra_rdoc_files = [
|
14
|
+
"LICENSE.txt",
|
15
|
+
"README.md"
|
16
|
+
]
|
17
|
+
s.homepage = ''
|
18
|
+
s.license = 'MIT'
|
19
|
+
|
20
|
+
s.add_dependency 'delayed_job_active_record'
|
21
|
+
s.add_dependency 'jquery-rails'
|
22
|
+
s.add_dependency 'awesome_print'
|
23
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'delayed_job_active_record'
|
3
|
+
|
4
|
+
module DelayedJobUi
|
5
|
+
class Engine < Rails::Engine
|
6
|
+
isolate_namespace DelayedJobUi
|
7
|
+
config.to_prepare do
|
8
|
+
ActionView::Base.send :include, MainHelper
|
9
|
+
Rails.application.config.assets.precompile += %w{delayed_job_ui.css delayed_job_ui.js jquery.dataTables.js}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module DelayedJobUi
|
2
|
+
class Jobs
|
3
|
+
def self.jobs(type)
|
4
|
+
case type
|
5
|
+
when :working
|
6
|
+
query = "locked_at IS NOT NULL"
|
7
|
+
when :failed
|
8
|
+
query = "last_error IS NOT NULL"
|
9
|
+
when :pending
|
10
|
+
query = "attempts = 0 AND locked_at IS NULL"
|
11
|
+
end
|
12
|
+
if defined? query
|
13
|
+
Delayed::Job.where(query)
|
14
|
+
else
|
15
|
+
Delayed::Job.all
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.job_count
|
20
|
+
count_hash = {:enqueued => 0, :working => 0, :pending => 0, :failed => 0}
|
21
|
+
count_hash.each do |type, number|
|
22
|
+
count_hash[type] = self.jobs(type).count
|
23
|
+
end
|
24
|
+
count_hash
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: delayed_job_ui
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sean Woojin Kim
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: delayed_job_active_record
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: jquery-rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: awesome_print
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A UI wrapper for DelayedJob
|
56
|
+
email: seanwoojinkim@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files:
|
60
|
+
- LICENSE.txt
|
61
|
+
- README.md
|
62
|
+
files:
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- app/assets/javascripts/delayed_job_ui.js
|
67
|
+
- app/assets/javascripts/jquery.dataTables.js
|
68
|
+
- app/assets/stylesheets/delayed_job_ui.scss
|
69
|
+
- app/controllers/delayed_job_ui/main_controller.rb
|
70
|
+
- app/helpers/delayed_job_ui/main_helper.rb
|
71
|
+
- app/views/delayed_job_ui/_job.html.haml
|
72
|
+
- app/views/delayed_job_ui/_job_table.html.haml
|
73
|
+
- app/views/delayed_job_ui/_ui_layout.html.haml
|
74
|
+
- delayed_job_ui.gemspec
|
75
|
+
- lib/delayed_job_ui.rb
|
76
|
+
- lib/delayed_job_ui/engine.rb
|
77
|
+
- lib/delayed_job_ui/jobs.rb
|
78
|
+
homepage: ''
|
79
|
+
licenses:
|
80
|
+
- MIT
|
81
|
+
metadata: {}
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 2.2.2
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: A UI wrapper for DelayedJob
|
102
|
+
test_files: []
|