sidekiq-cron 0.6.3 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -6
- data/Changes.md +32 -0
- data/Dockerfile +1 -1
- data/Gemfile +1 -1
- data/README.md +25 -12
- data/VERSION +1 -1
- data/docker-compose.yml +3 -1
- data/lib/sidekiq/cron/job.rb +82 -32
- data/lib/sidekiq/cron/launcher.rb +34 -40
- data/lib/sidekiq/cron/locales/de.yml +2 -2
- data/lib/sidekiq/cron/locales/en.yml +4 -2
- data/lib/sidekiq/cron/locales/ja.yml +18 -0
- data/lib/sidekiq/cron/locales/ru.yml +2 -2
- data/lib/sidekiq/cron/locales/zh-CN.yml +19 -0
- data/lib/sidekiq/cron/poller.rb +6 -4
- data/lib/sidekiq/cron/views/cron.erb +23 -19
- data/lib/sidekiq/cron/views/cron.slim +17 -15
- data/lib/sidekiq/cron/views/cron_show.erb +88 -0
- data/lib/sidekiq/cron/views/cron_show.slim +61 -0
- data/lib/sidekiq/cron/web_extension.rb +20 -3
- data/sidekiq-cron.gemspec +74 -70
- data/test/integration/performance_test.rb +7 -9
- data/test/test_helper.rb +17 -6
- data/test/unit/job_test.rb +67 -14
- data/test/unit/poller_test.rb +22 -23
- data/test/unit/web_extension_test.rb +22 -3
- metadata +12 -8
@@ -1,6 +1,3 @@
|
|
1
|
-
# require Sidekiq original launcher
|
2
|
-
require 'sidekiq/launcher'
|
3
|
-
|
4
1
|
# require cron poller
|
5
2
|
require 'sidekiq/cron/poller'
|
6
3
|
|
@@ -10,44 +7,41 @@ require 'sidekiq/cron/poller'
|
|
10
7
|
# we are creating new cron poller instance and
|
11
8
|
# adding start and stop commands to launcher
|
12
9
|
module Sidekiq
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
old_quiet
|
10
|
+
module Cron
|
11
|
+
module Launcher
|
12
|
+
# Add cron poller to launcher
|
13
|
+
attr_reader :cron_poller
|
14
|
+
|
15
|
+
# add cron poller and execute normal initialize of Sidekiq launcher
|
16
|
+
def initialize(options)
|
17
|
+
@cron_poller = Sidekiq::Cron::Poller.new
|
18
|
+
super(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
# execute normal run of launcher and run cron poller
|
22
|
+
def run
|
23
|
+
super
|
24
|
+
cron_poller.start
|
25
|
+
end
|
26
|
+
|
27
|
+
# execute normal quiet of launcher and quiet cron poller
|
28
|
+
def quiet
|
29
|
+
cron_poller.terminate
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
# execute normal stop of launcher and stop cron poller
|
34
|
+
def stop
|
35
|
+
cron_poller.terminate
|
36
|
+
super
|
37
|
+
end
|
42
38
|
end
|
39
|
+
end
|
40
|
+
end
|
43
41
|
|
44
|
-
|
45
|
-
|
42
|
+
Sidekiq.configure_server do
|
43
|
+
# require Sidekiq original launcher
|
44
|
+
require 'sidekiq/launcher'
|
46
45
|
|
47
|
-
|
48
|
-
def stop
|
49
|
-
cron_poller.terminate
|
50
|
-
old_stop
|
51
|
-
end
|
52
|
-
end
|
46
|
+
::Sidekiq::Launcher.prepend(Sidekiq::Cron::Launcher)
|
53
47
|
end
|
@@ -5,9 +5,9 @@ de:
|
|
5
5
|
EnqueueNow: In Warteschlange
|
6
6
|
'Cron string': Cron
|
7
7
|
AreYouSureDeleteCronJob: Sind Sie sicher, dass sie den Cronjob %{job} löschen wollen?
|
8
|
-
|
8
|
+
NoCronJobsWereFound: Keine Cronjobs gefunden
|
9
9
|
Enable: Aktivieren
|
10
10
|
Disable: Deaktivieren
|
11
|
-
'Last
|
11
|
+
'Last enqueued': Eingereiht
|
12
12
|
disabled: deaktiviert
|
13
13
|
enabled: aktiviert
|
@@ -10,9 +10,11 @@ en:
|
|
10
10
|
'Cron string': Cron
|
11
11
|
AreYouSureDeleteCronJobs: Are you sure you want to delete ALL cron jobs?
|
12
12
|
AreYouSureDeleteCronJob: Are you sure you want to delete the %{job} cron job?
|
13
|
-
|
13
|
+
NoCronJobsWereFound: No cron jobs were found
|
14
14
|
Enable: Enable
|
15
15
|
Disable: Disable
|
16
|
-
'Last
|
16
|
+
'Last enqueued': Last enqueued
|
17
17
|
disabled: disabled
|
18
18
|
enabled: enabled
|
19
|
+
NoHistoryWereFound: No history were found
|
20
|
+
Description: Description
|
@@ -0,0 +1,18 @@
|
|
1
|
+
ja:
|
2
|
+
Job: ジョブ
|
3
|
+
Cron: Cron
|
4
|
+
CronJobs: Cronジョブ
|
5
|
+
EnqueueNow: すぐにキューに入れる
|
6
|
+
EnableAll: すべて有効にする
|
7
|
+
DisableAll: すべて無効にする
|
8
|
+
EnqueueAll: すべてキューに入れる
|
9
|
+
DeleteAll: すべて削除
|
10
|
+
'Cron string': Cron
|
11
|
+
AreYouSureDeleteCronJobs: 本当にすべてのcronジョブを削除しますか?
|
12
|
+
AreYouSureDeleteCronJob: 本当に%{job}のcronジョブを削除しますか?
|
13
|
+
NoCronJobsWereFound: Cronジョブが見つかりませんでした
|
14
|
+
Enable: 有効にする
|
15
|
+
Disable: 無効にする
|
16
|
+
'Last enqueued': 最後のキュー
|
17
|
+
disabled: 無効
|
18
|
+
enabled: 有効
|
@@ -6,9 +6,9 @@ ru:
|
|
6
6
|
'Cron string': Периодичность (синтаксис Cron)
|
7
7
|
EnqueueNow: Запустить
|
8
8
|
AreYouSureDeleteCronJob: Вы действительно хотите удалить задачу «%{job}»?
|
9
|
-
|
9
|
+
NoCronJobsWereFound: Не найдено периодических задач
|
10
10
|
Enable: Включить
|
11
11
|
Disable: Отключить
|
12
|
-
'Last
|
12
|
+
'Last enqueued': Последний запуск
|
13
13
|
disabled: отключено
|
14
14
|
enabled: включено
|
@@ -0,0 +1,19 @@
|
|
1
|
+
zh-CN:
|
2
|
+
Job: 任务
|
3
|
+
Cron: 定时任务
|
4
|
+
CronJobs: 定时任务列表
|
5
|
+
EnqueueNow: 立刻执行
|
6
|
+
EnableAll: 启用所有
|
7
|
+
DisableAll: 禁用所有
|
8
|
+
EnqueueAll: 执行所有
|
9
|
+
DeleteAll: 删除所有
|
10
|
+
'Cron string': 定时策略
|
11
|
+
AreYouSureDeleteCronJobs: 你确定删除所有的定时任务吗?
|
12
|
+
AreYouSureDeleteCronJob: 你确定删除定时任务(%{job})吗?
|
13
|
+
NoCronJobsWereFound: 没有定时任务
|
14
|
+
Enable: 启用
|
15
|
+
Disable: 禁用
|
16
|
+
'Last enqueued': 放入队列时间
|
17
|
+
disabled: 已禁用
|
18
|
+
enabled: 已启用
|
19
|
+
|
data/lib/sidekiq/cron/poller.rb
CHANGED
@@ -17,8 +17,9 @@ module Sidekiq
|
|
17
17
|
rescue => ex
|
18
18
|
# Most likely a problem with redis networking.
|
19
19
|
# Punt and try again at the next interval
|
20
|
-
logger.error ex.message
|
21
|
-
logger.error ex.backtrace.first
|
20
|
+
Sidekiq.logger.error ex.message
|
21
|
+
Sidekiq.logger.error ex.backtrace.first
|
22
|
+
handle_exception(ex) if respond_to?(:handle_exception)
|
22
23
|
end
|
23
24
|
|
24
25
|
private
|
@@ -27,8 +28,9 @@ module Sidekiq
|
|
27
28
|
job.test_and_enque_for_time! time if job && job.valid?
|
28
29
|
rescue => ex
|
29
30
|
# problem somewhere in one job
|
30
|
-
logger.error "CRON JOB: #{ex.message}"
|
31
|
-
logger.error "CRON JOB: #{ex.backtrace.first}"
|
31
|
+
Sidekiq.logger.error "CRON JOB: #{ex.message}"
|
32
|
+
Sidekiq.logger.error "CRON JOB: #{ex.backtrace.first}"
|
33
|
+
handle_exception(ex) if respond_to?(:handle_exception)
|
32
34
|
end
|
33
35
|
|
34
36
|
def poll_interval_average
|
@@ -3,22 +3,24 @@
|
|
3
3
|
<h3><%=t 'CronJobs' %></h3>
|
4
4
|
</div>
|
5
5
|
<div class='col-sm-7 pull-right' style="margin-top: 20px; margin-bottom: 10px;">
|
6
|
-
|
7
|
-
<%=
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
<%=
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
<%=
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
<%=
|
20
|
-
|
21
|
-
|
6
|
+
<% if @cron_jobs.size > 0 %>
|
7
|
+
<form action="<%= root_path %>cron/__all__/delete" method="post" class="pull-right">
|
8
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
9
|
+
<input class="btn btn-small btn-danger" type="submit" name="delete" value="<%= t('DeleteAll') %>" data-confirm="<%= t('AreYouSureDeleteCronJobs') %>">
|
10
|
+
</form>
|
11
|
+
<form action="<%= root_path %>cron/__all__/disable" method="post" class="pull-right">
|
12
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
13
|
+
<input class="btn btn-small" type="submit" name="enque" value="<%= t('DisableAll') %>" />
|
14
|
+
</form>
|
15
|
+
<form action="<%= root_path %>cron/__all__/enable" method="post" class="pull-right">
|
16
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
17
|
+
<input class="btn btn-small" type="submit" name="enque" value="<%= t('EnableAll') %>" />
|
18
|
+
</form>
|
19
|
+
<form action="<%= root_path %>cron/__all__/enque" method="post" class="pull-right">
|
20
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
21
|
+
<input class="btn btn-small" type="submit" name="enque" value="<%= t('EnqueueAll') %>" />
|
22
|
+
</form>
|
23
|
+
<% end %>
|
22
24
|
</div>
|
23
25
|
</header>
|
24
26
|
|
@@ -29,7 +31,7 @@
|
|
29
31
|
<th><%= t('Status') %></th>
|
30
32
|
<th><%= t('Name') %></th>
|
31
33
|
<th><%= t('Cron string') %></th>
|
32
|
-
<th><%= t('Last
|
34
|
+
<th><%= t('Last enqueued') %></th>
|
33
35
|
<th width="180"><%= t('Actions')%></th>
|
34
36
|
</thead>
|
35
37
|
|
@@ -39,7 +41,9 @@
|
|
39
41
|
<tr>
|
40
42
|
<td style="<%= style %>"><%= t job.status %></td>
|
41
43
|
<td style="<%= style %>">
|
42
|
-
<
|
44
|
+
<a href="<%= root_path %>cron/<%= CGI.escape(job.name).gsub('+', '%20') %>">
|
45
|
+
<b><%= job.name %></b>
|
46
|
+
</a>
|
43
47
|
<hr style="margin:3px;border:0;">
|
44
48
|
<small>
|
45
49
|
<% if job.message and job.message.to_s.size > 100 %>
|
@@ -83,6 +87,6 @@
|
|
83
87
|
</tbody>
|
84
88
|
</table>
|
85
89
|
<% else %>
|
86
|
-
<
|
90
|
+
<div class='alert alert-success'><%= t('NoCronJobsWereFound') %></div>
|
87
91
|
<% end %>
|
88
92
|
|
@@ -3,18 +3,19 @@ header.row
|
|
3
3
|
h3 = t('CronJobs')
|
4
4
|
|
5
5
|
.span.col-sm-7.pull-right style="margin-top: 20px; margin-bottom: 10px;"
|
6
|
-
|
7
|
-
=
|
8
|
-
|
9
|
-
|
10
|
-
=
|
11
|
-
|
12
|
-
|
13
|
-
=
|
14
|
-
|
15
|
-
|
16
|
-
=
|
17
|
-
|
6
|
+
- if @cron_jobs.size > 0
|
7
|
+
form.pull-right action="#{root_path}cron/__all__/delete" method="post"
|
8
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
9
|
+
input.btn.btn-small.pull-left.btn-danger type="submit" name="enque" value="#{t('DeleteAll')}" data-confirm="#{t('AreYouSureDeleteCronJobs')}"
|
10
|
+
form.pull-right action="#{root_path}cron/__all__/disable" method="post"
|
11
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
12
|
+
input.btn.btn-small.pull-left type="submit" name="enque" value="#{t('DisableAll')}"
|
13
|
+
form.pull-right action="#{root_path}cron/__all__/enable" method="post"
|
14
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
15
|
+
input.btn.btn-small.pull-left type="submit" name="enque" value="#{t('EnableAll')}"
|
16
|
+
form.pull-right action="#{root_path}cron/__all__/enque" method="post"
|
17
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
18
|
+
input.btn.btn-small.pull-left type="submit" name="enque" value="#{t('EnqueueAll')}"
|
18
19
|
|
19
20
|
- if @cron_jobs.size > 0
|
20
21
|
|
@@ -23,7 +24,7 @@ header.row
|
|
23
24
|
th = t('Status')
|
24
25
|
th = t('Name')
|
25
26
|
th = t('Cron')
|
26
|
-
th = t('Last
|
27
|
+
th = t('Last enqueued')
|
27
28
|
th width="180px"
|
28
29
|
= t('Actions')
|
29
30
|
|
@@ -33,7 +34,8 @@ header.row
|
|
33
34
|
tr
|
34
35
|
td[style="#{style}"]= job.status
|
35
36
|
td[style="#{style}"]
|
36
|
-
|
37
|
+
a href="#{root_path}cron/#{CGI.escape(job.name).gsub('+', '%20')}"
|
38
|
+
b = job.name
|
37
39
|
hr style="margin:3px;border:0;"
|
38
40
|
small
|
39
41
|
- if job.message and job.message.to_s.size > 100
|
@@ -66,4 +68,4 @@ header.row
|
|
66
68
|
input.btn.btn-danger.btn-small type="submit" name="delete" value="#{t('Delete')}" data-confirm="#{t('AreYouSureDeleteCronJob', :job => job.name)}"
|
67
69
|
|
68
70
|
- else
|
69
|
-
.alert.alert-success = t('
|
71
|
+
.alert.alert-success = t('NoCronJobsWereFound')
|
@@ -0,0 +1,88 @@
|
|
1
|
+
<header class="row">
|
2
|
+
<div class="span col-sm-5 pull-left">
|
3
|
+
<h3>
|
4
|
+
<%= "#{t('Cron')} #{t('Job')}" %>
|
5
|
+
<small><%= @job.name %></small>
|
6
|
+
</h3>
|
7
|
+
</div>
|
8
|
+
<div class="span col-sm-7 pull-right" style="margin-top: 20px; margin-bottom: 10px;">
|
9
|
+
<% cron_job_path = "#{root_path}cron/#{CGI.escape(@job.name).gsub('+', '%20')}" %>
|
10
|
+
<form action="<%= cron_job_path %>/enque?redirect=<%= cron_job_path %>" class="pull-right" method="post">
|
11
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
12
|
+
<input class="btn btn-small pull-left" name="enque" type="submit" value="<%= t('EnqueueNow') %>" />
|
13
|
+
</form>
|
14
|
+
<% if @job.status == 'enabled' %>
|
15
|
+
<form action="<%= cron_job_path %>/disable?redirect=<%= cron_job_path %>" class="pull-right" method="post">
|
16
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
17
|
+
<input class="btn btn-small pull-left" name="disable" type="submit" value="<%= t('Disable') %>" />
|
18
|
+
</form>
|
19
|
+
<% else %>
|
20
|
+
<form action="<%= cron_job_path %>/enable?redirect=<%= cron_job_path %>" class="pull-right" method="post">
|
21
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
22
|
+
<input class="btn btn-small pull-left" name="enable" type="submit" value="<%= t('Enable') %>" />
|
23
|
+
</form>
|
24
|
+
<form action="<%= cron_job_path %>/delete" class="pull-right" method="post">
|
25
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
26
|
+
<input class="btn btn-danger btn-small" data-confirm="<%= t('AreYouSureDeleteCronJob', :job => @job.name) %>" name="delete" type="submit" value="<%= t('Delete') %>" />
|
27
|
+
</form>
|
28
|
+
<% end %>
|
29
|
+
</div>
|
30
|
+
</header>
|
31
|
+
|
32
|
+
<table class="table table-bordered table-striped">
|
33
|
+
<tbody>
|
34
|
+
<tr>
|
35
|
+
<th><%= t 'Status' %></th>
|
36
|
+
<td><%= @job.status %></td>
|
37
|
+
</tr>
|
38
|
+
<tr>
|
39
|
+
<th><%= t 'Name' %></th>
|
40
|
+
<td><%= @job.name %></td>
|
41
|
+
</tr>
|
42
|
+
<tr>
|
43
|
+
<th><%= t 'Description' %></th>
|
44
|
+
<td><%= @job.description %></td>
|
45
|
+
</tr>
|
46
|
+
<tr>
|
47
|
+
<th><%= t 'Message' %></th>
|
48
|
+
<td><pre><%= @job.pretty_message %></pre></td>
|
49
|
+
</tr>
|
50
|
+
<tr>
|
51
|
+
<th><%= t 'Cron' %></th>
|
52
|
+
<td><%= @job.cron.gsub(" ", " ") %></td>
|
53
|
+
</tr>
|
54
|
+
<tr>
|
55
|
+
<th><%= t 'Last enqueued' %></th>
|
56
|
+
<td><%= @job.last_enqueue_time ? relative_time(@job.last_enqueue_time) : "-" %></td>
|
57
|
+
</tr>
|
58
|
+
</tbody>
|
59
|
+
</table>
|
60
|
+
|
61
|
+
<header class="row">
|
62
|
+
<div class="col-sm-12">
|
63
|
+
<h4>
|
64
|
+
<%= t 'History' %>
|
65
|
+
</h4>
|
66
|
+
</div>
|
67
|
+
</header>
|
68
|
+
|
69
|
+
<% if @job.jid_history_from_redis.size > 0 %>
|
70
|
+
<table class="table table-hover table-bordered table-striped">
|
71
|
+
<thead>
|
72
|
+
<tr>
|
73
|
+
<th><%= t 'Enqueued' %></th>
|
74
|
+
<th><%= t 'JID' %></th>
|
75
|
+
</tr>
|
76
|
+
</thead>
|
77
|
+
<tbody>
|
78
|
+
<% @job.jid_history_from_redis.each do |jid_history| %>
|
79
|
+
<tr>
|
80
|
+
<td><%= jid_history['enqueued'] %></td>
|
81
|
+
<td><%= jid_history['jid'] %></td>
|
82
|
+
</tr>
|
83
|
+
<% end %>
|
84
|
+
</tbody>
|
85
|
+
</table>
|
86
|
+
<% else %>
|
87
|
+
<div class='alert alert-success'><%= t 'NoHistoryWereFound' %></div>
|
88
|
+
<% end %>
|
@@ -0,0 +1,61 @@
|
|
1
|
+
header.row
|
2
|
+
.span.col-sm-5.pull-left
|
3
|
+
h3
|
4
|
+
= "#{t('Cron')} #{t('Job')}"
|
5
|
+
small= @job.name
|
6
|
+
.span.col-sm-7.pull-right style=("margin-top: 20px; margin-bottom: 10px;")
|
7
|
+
- cron_job_path = "#{root_path}cron/#{CGI.escape(@job.name).gsub('+', '%20')}"
|
8
|
+
form.pull-right action="#{cron_job_path}/enque?redirect=#{cron_job_path}" method="post"
|
9
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
10
|
+
input.btn.btn-small.pull-left name="enque" type="submit" value="#{t('EnqueueNow')}"
|
11
|
+
- if @job.status == 'enabled'
|
12
|
+
form.pull-right action="#{cron_job_path}/disable?redirect=#{cron_job_path}" method="post"
|
13
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
14
|
+
input.btn.btn-small.pull-left name="disable" type="submit" value="#{t('Disable')}"
|
15
|
+
- else
|
16
|
+
form.pull-right action="#{cron_job_path}/enable?redirect=#{cron_job_path}" method="post"
|
17
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
18
|
+
input.btn.btn-small.pull-left name="enable" type="submit" value="#{t('Enable')}"
|
19
|
+
form.pull-right action="#{cron_job_path}/delete" method="post"
|
20
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
21
|
+
input.btn.btn-danger.btn-small data-confirm="#{t('AreYouSureDeleteCronJob' job =@job.name)}" name="delete" type="submit" value="#{t('Delete')}" /
|
22
|
+
|
23
|
+
table.table.table-bordered.table-striped
|
24
|
+
tbody
|
25
|
+
tr
|
26
|
+
th= t 'Status'
|
27
|
+
td= @job.status
|
28
|
+
tr
|
29
|
+
th= t 'Name'
|
30
|
+
td= @job.name
|
31
|
+
tr
|
32
|
+
th= t 'Description'
|
33
|
+
td= @job.description
|
34
|
+
tr
|
35
|
+
th= t 'Message'
|
36
|
+
td
|
37
|
+
pre= @job.pretty_message
|
38
|
+
tr
|
39
|
+
th= t 'Cron'
|
40
|
+
td= @job.cron.gsub(" ", " ")
|
41
|
+
tr
|
42
|
+
th= t 'Last enqueued'
|
43
|
+
td= @job.last_enqueue_time ? relative_time(@job.last_enqueue_time) : "-"
|
44
|
+
|
45
|
+
header.row
|
46
|
+
.col-sm-12
|
47
|
+
h4= t 'History'
|
48
|
+
|
49
|
+
- if @job.jid_history_from_redis.size > 0
|
50
|
+
table.table.table-hover.table-bordered.table-striped
|
51
|
+
thead
|
52
|
+
tr
|
53
|
+
th= t 'Enqueued'
|
54
|
+
th= t 'JID'
|
55
|
+
tbody
|
56
|
+
- @job.jid_history_from_redis.each do |jid_history|
|
57
|
+
tr
|
58
|
+
td= jid_history['enqueued']
|
59
|
+
td= jid_history['jid']
|
60
|
+
- else
|
61
|
+
.alert.alert-success= t 'NoHistoryWereFound'
|