sidekiq-cron 0.6.3 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +145 -0
- data/Gemfile +3 -29
- data/README.md +175 -121
- data/Rakefile +3 -42
- data/lib/sidekiq/cron/job.rb +273 -144
- data/lib/sidekiq/cron/launcher.rb +39 -43
- data/lib/sidekiq/cron/locales/de.yml +2 -2
- data/lib/sidekiq/cron/locales/en.yml +6 -2
- data/lib/sidekiq/cron/locales/it.yml +23 -0
- data/lib/sidekiq/cron/locales/ja.yml +18 -0
- data/lib/sidekiq/cron/locales/pt.yml +22 -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 +22 -12
- data/lib/sidekiq/cron/schedule_loader.rb +22 -0
- data/lib/sidekiq/cron/support.rb +8 -1
- data/lib/sidekiq/cron/version.rb +7 -0
- data/lib/sidekiq/cron/views/cron.erb +38 -28
- data/lib/sidekiq/cron/views/cron_show.erb +88 -0
- data/lib/sidekiq/cron/web.rb +1 -7
- data/lib/sidekiq/cron/web_extension.rb +19 -15
- data/lib/sidekiq/cron.rb +1 -0
- data/lib/sidekiq/options.rb +25 -0
- data/sidekiq-cron.gemspec +23 -108
- data/test/integration/performance_test.rb +13 -19
- data/test/models/person.rb +21 -0
- data/test/test_helper.rb +37 -38
- data/test/unit/fixtures/schedule_array.yml +13 -0
- data/test/unit/fixtures/schedule_erb.yml +6 -0
- data/test/unit/fixtures/schedule_hash.yml +12 -0
- data/test/unit/fixtures/schedule_string.yml +1 -0
- data/test/unit/job_test.rb +450 -35
- data/test/unit/launcher_test.rb +33 -0
- data/test/unit/poller_test.rb +28 -37
- data/test/unit/schedule_loader_test.rb +58 -0
- data/test/unit/web_extension_test.rb +59 -41
- metadata +72 -191
- data/.document +0 -5
- data/.travis.yml +0 -19
- data/Changes.md +0 -50
- data/Dockerfile +0 -32
- data/VERSION +0 -1
- data/config.ru +0 -14
- data/docker-compose.yml +0 -21
- data/examples/web-cron-ui.png +0 -0
- data/lib/sidekiq/cron/views/cron.slim +0 -69
@@ -1,53 +1,49 @@
|
|
1
|
-
# require Sidekiq original launcher
|
2
|
-
require 'sidekiq/launcher'
|
3
|
-
|
4
|
-
# require cron poller
|
5
1
|
require 'sidekiq/cron/poller'
|
6
2
|
|
7
3
|
# For Cron we need to add some methods to Launcher
|
8
4
|
# so look at the code bellow.
|
9
5
|
#
|
10
|
-
#
|
11
|
-
# adding start and stop commands to launcher
|
6
|
+
# We are creating new cron poller instance and
|
7
|
+
# adding start and stop commands to launcher.
|
12
8
|
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
|
-
|
9
|
+
module Cron
|
10
|
+
module Launcher
|
11
|
+
DEFAULT_POLL_INTERVAL = 30
|
12
|
+
|
13
|
+
# Add cron poller to launcher.
|
14
|
+
attr_reader :cron_poller
|
15
|
+
|
16
|
+
# Add cron poller and execute normal initialize of Sidekiq launcher.
|
17
|
+
def initialize(config, **kwargs)
|
18
|
+
config[:cron_poll_interval] = DEFAULT_POLL_INTERVAL if config[:cron_poll_interval].nil?
|
19
|
+
|
20
|
+
@cron_poller = Sidekiq::Cron::Poller.new(config) if config[:cron_poll_interval] > 0
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
# Execute normal run of launcher and run cron poller.
|
25
|
+
def run
|
26
|
+
super
|
27
|
+
cron_poller.start if @cron_poller
|
28
|
+
end
|
29
|
+
|
30
|
+
# Execute normal quiet of launcher and quiet cron poller.
|
31
|
+
def quiet
|
32
|
+
cron_poller.terminate if @cron_poller
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
# Execute normal stop of launcher and stop cron poller.
|
37
|
+
def stop
|
38
|
+
cron_poller.terminate if @cron_poller
|
39
|
+
super
|
40
|
+
end
|
42
41
|
end
|
42
|
+
end
|
43
|
+
end
|
43
44
|
|
44
|
-
|
45
|
-
|
45
|
+
Sidekiq.configure_server do
|
46
|
+
require 'sidekiq/launcher'
|
46
47
|
|
47
|
-
|
48
|
-
def stop
|
49
|
-
cron_poller.terminate
|
50
|
-
old_stop
|
51
|
-
end
|
52
|
-
end
|
48
|
+
::Sidekiq::Launcher.prepend(Sidekiq::Cron::Launcher)
|
53
49
|
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
|
@@ -8,11 +8,15 @@ en:
|
|
8
8
|
EnqueueAll: Enqueue All
|
9
9
|
DeleteAll: Delete All
|
10
10
|
'Cron string': Cron
|
11
|
+
AreYouSureEnqueueCronJobs: Are you sure you want to enqueue ALL cron jobs?
|
12
|
+
AreYouSureEnqueueCronJob: Are you sure you want to enqueue the %{job} cron job?
|
11
13
|
AreYouSureDeleteCronJobs: Are you sure you want to delete ALL cron jobs?
|
12
14
|
AreYouSureDeleteCronJob: Are you sure you want to delete the %{job} cron job?
|
13
|
-
|
15
|
+
NoCronJobsWereFound: No cron jobs were found
|
14
16
|
Enable: Enable
|
15
17
|
Disable: Disable
|
16
|
-
'Last
|
18
|
+
'Last enqueued': Last enqueued
|
17
19
|
disabled: disabled
|
18
20
|
enabled: enabled
|
21
|
+
NoHistoryWereFound: No history were found
|
22
|
+
Description: Description
|
@@ -0,0 +1,23 @@
|
|
1
|
+
it:
|
2
|
+
Job: Job
|
3
|
+
Cron: Cron
|
4
|
+
CronJobs: Cron job
|
5
|
+
EnqueueNow: Accoda
|
6
|
+
EnableAll: Attiva tutto
|
7
|
+
DisableAll: Disattiva tutto
|
8
|
+
EnqueueAll: Accoda tutto
|
9
|
+
DeleteAll: Cancella tutto
|
10
|
+
"Cron string": Cron
|
11
|
+
AreYouSureEnqueueCronJobs: Vuoi accodare TUTTI i cron job?
|
12
|
+
AreYouSureEnqueueCronJob: "Vuoi accodare il cron job '%{job}'?"
|
13
|
+
AreYouSureDeleteCronJobs: Vuoi cancellare TUTTI i cron job?
|
14
|
+
AreYouSureDeleteCronJob: "Vuoi cancellare il cron job '%{job}'?"
|
15
|
+
NoCronJobsWereFound: Nessun cron job trovato
|
16
|
+
Enable: Attiva
|
17
|
+
Disable: Disattiva
|
18
|
+
"Last enqueued": Ultimo accodamento
|
19
|
+
disabled: disattivato
|
20
|
+
enabled: attivato
|
21
|
+
NoHistoryWereFound: Nessun evento in cronologia
|
22
|
+
Description: Descrizione
|
23
|
+
Message: Payload
|
@@ -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: 有効
|
@@ -0,0 +1,22 @@
|
|
1
|
+
pt:
|
2
|
+
Job: Tarefa
|
3
|
+
Cron: Cron
|
4
|
+
CronJobs: Tarefas do Cron
|
5
|
+
EnqueueNow: Enfileirar agora
|
6
|
+
EnableAll: Habilitar todos
|
7
|
+
DisableAll: Desabilitar todos
|
8
|
+
EnqueueAll: Enfileirar todos
|
9
|
+
DeleteAll: Excluir todos
|
10
|
+
'Cron string': Cron
|
11
|
+
AreYouSureEnqueueCronJobs: Tem certeza de que deseja enfileirar TODOS as tarefas?
|
12
|
+
AreYouSureEnqueueCronJob: Tem certeza de que deseja enfileirar a tarefa %{job}?
|
13
|
+
AreYouSureDeleteCronJobs: Tem certeza de que deseja excluir TODOS as tarefas?
|
14
|
+
AreYouSureDeleteCronJob: Tem certeza de que deseja excluir a tarefa %{job}?
|
15
|
+
NoCronJobsWereFound: Nenhuma tarefa foi encontrada
|
16
|
+
Enable: Habilitar
|
17
|
+
Disable: Desabilitar
|
18
|
+
'Last enqueued': Último enfileirado
|
19
|
+
disabled: desabilitado
|
20
|
+
enabled: habilitado
|
21
|
+
NoHistoryWereFound: Nenhum histórico foi encontrado
|
22
|
+
Description: Descrição
|
@@ -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
@@ -1,14 +1,22 @@
|
|
1
1
|
require 'sidekiq'
|
2
|
-
require 'sidekiq/util'
|
3
2
|
require 'sidekiq/cron'
|
4
3
|
require 'sidekiq/scheduled'
|
4
|
+
require 'sidekiq/options'
|
5
5
|
|
6
6
|
module Sidekiq
|
7
7
|
module Cron
|
8
|
-
|
9
|
-
|
10
|
-
# The Poller checks Redis every N seconds for sheduled cron jobs
|
8
|
+
# The Poller checks Redis every N seconds for sheduled cron jobs.
|
11
9
|
class Poller < Sidekiq::Scheduled::Poller
|
10
|
+
def initialize(config = nil)
|
11
|
+
if Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('6.5.0')
|
12
|
+
super
|
13
|
+
else
|
14
|
+
# Old version of Sidekiq does not accept a config argument.
|
15
|
+
@config = config
|
16
|
+
super()
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
12
20
|
def enqueue
|
13
21
|
time = Time.now.utc
|
14
22
|
Sidekiq::Cron::Job.all.each do |job|
|
@@ -16,9 +24,10 @@ module Sidekiq
|
|
16
24
|
end
|
17
25
|
rescue => ex
|
18
26
|
# Most likely a problem with redis networking.
|
19
|
-
# Punt and try again at the next interval
|
20
|
-
logger.error ex.message
|
21
|
-
logger.error ex.backtrace.first
|
27
|
+
# Punt and try again at the next interval.
|
28
|
+
Sidekiq.logger.error ex.message
|
29
|
+
Sidekiq.logger.error ex.backtrace.first
|
30
|
+
handle_exception(ex) if respond_to?(:handle_exception)
|
22
31
|
end
|
23
32
|
|
24
33
|
private
|
@@ -26,13 +35,14 @@ module Sidekiq
|
|
26
35
|
def enqueue_job(job, time = Time.now.utc)
|
27
36
|
job.test_and_enque_for_time! time if job && job.valid?
|
28
37
|
rescue => ex
|
29
|
-
#
|
30
|
-
logger.error "CRON JOB: #{ex.message}"
|
31
|
-
logger.error "CRON JOB: #{ex.backtrace.first}"
|
38
|
+
# Problem somewhere in one job.
|
39
|
+
Sidekiq.logger.error "CRON JOB: #{ex.message}"
|
40
|
+
Sidekiq.logger.error "CRON JOB: #{ex.backtrace.first}"
|
41
|
+
handle_exception(ex) if respond_to?(:handle_exception)
|
32
42
|
end
|
33
43
|
|
34
|
-
def poll_interval_average
|
35
|
-
|
44
|
+
def poll_interval_average(process_count = 1)
|
45
|
+
@config[:cron_poll_interval]
|
36
46
|
end
|
37
47
|
end
|
38
48
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'sidekiq'
|
2
|
+
require 'sidekiq/cron/job'
|
3
|
+
require 'sidekiq/options'
|
4
|
+
|
5
|
+
if Sidekiq.server?
|
6
|
+
Sidekiq.configure_server do |config|
|
7
|
+
schedule_file = Sidekiq::Options[:cron_schedule_file] || 'config/schedule.yml'
|
8
|
+
|
9
|
+
if File.exist?(schedule_file)
|
10
|
+
config.on(:startup) do
|
11
|
+
schedule = Sidekiq::Cron::Support.load_yaml(ERB.new(IO.read(schedule_file)).result)
|
12
|
+
if schedule.kind_of?(Hash)
|
13
|
+
Sidekiq::Cron::Job.load_from_hash! schedule
|
14
|
+
elsif schedule.kind_of?(Array)
|
15
|
+
Sidekiq::Cron::Job.load_from_array! schedule
|
16
|
+
else
|
17
|
+
raise "Not supported schedule format. Confirm your #{schedule_file}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/sidekiq/cron/support.rb
CHANGED
@@ -28,11 +28,18 @@ module Sidekiq
|
|
28
28
|
const
|
29
29
|
end
|
30
30
|
|
31
|
-
# owner is in Object, so raise
|
32
31
|
constant.const_get(name, false)
|
33
32
|
end
|
34
33
|
end
|
35
34
|
end
|
35
|
+
|
36
|
+
def self.load_yaml(src)
|
37
|
+
if Psych::VERSION > "4.0"
|
38
|
+
YAML.safe_load(src, permitted_classes: [Symbol], aliases: true)
|
39
|
+
else
|
40
|
+
YAML.load(src)
|
41
|
+
end
|
42
|
+
end
|
36
43
|
end
|
37
44
|
end
|
38
45
|
end
|
@@ -1,24 +1,26 @@
|
|
1
1
|
<header class='row'>
|
2
2
|
<div class='col-sm-5 pull-left'>
|
3
|
-
<h3><%=t
|
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-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-warn" 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-warn" 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-warn" type="submit" name="enque" value="<%= t('EnqueueAll') %>" data-confirm="<%= t('AreYouSureEnqueueCronJobs') %>" />
|
22
|
+
</form>
|
23
|
+
<% end %>
|
22
24
|
</div>
|
23
25
|
</header>
|
24
26
|
|
@@ -29,23 +31,31 @@
|
|
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
|
|
36
38
|
<tbody>
|
37
39
|
<% @cron_jobs.sort{|a,b| a.sort_name <=> b.sort_name }.each_with_index do |job, index| %>
|
38
|
-
<% style = "#{job.status == 'disabled' ? "background: #ecc": ""}" %>
|
40
|
+
<% style = "#{job.status == 'disabled' ? "background: #ecc; color: #585454;": ""}" %>
|
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 style="<%= style %>"><%= 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 %>
|
46
|
-
|
47
|
-
|
48
|
-
|
50
|
+
<% if Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new("6.3.0") %>
|
51
|
+
<button data-toggle="job_<%= index %>" class="btn btn-warn btn-xs"><%= t('ShowAll')%></button>
|
52
|
+
<div class="toggle" id="job_<%= index %>" style="display: inline;"><%= job.message[0..100] + "... " %></div>
|
53
|
+
<div class="toggle" id="job_<%= index %>_full" style="display: none;"><%= job.message %></div>
|
54
|
+
<% else %>
|
55
|
+
<button data-toggle="collapse" data-target=".worker_<%= index %>" class="btn btn-warn btn-xs"><%= t('ShowAll')%></button>
|
56
|
+
<div class="toggle worker_<%= index %>" style="display: inline;"><%= job.message[0..100] + "... " %></div>
|
57
|
+
<div class="toggle worker_<%= index %>" style="display: none;"><%= job.message %></div>
|
58
|
+
<% end %>
|
49
59
|
<% else %>
|
50
60
|
<%= job.message %>
|
51
61
|
<% end %>
|
@@ -57,20 +67,20 @@
|
|
57
67
|
<% if job.status == 'enabled' %>
|
58
68
|
<form action="<%= root_path %>cron/<%= CGI.escape(job.name).gsub('+', '%20') %>/enque" method="post">
|
59
69
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
60
|
-
<input class='btn btn-xs pull-left' type="submit" name="enque" value="<%= t('EnqueueNow') %>"/>
|
70
|
+
<input class='btn btn-warn btn-xs pull-left' type="submit" name="enque" value="<%= t('EnqueueNow') %>" data-confirm="<%= t('AreYouSureEnqueueCronJob', :job => job.name) %>"/>
|
61
71
|
</form>
|
62
72
|
<form action="<%= root_path %>cron/<%= CGI.escape(job.name).gsub('+', '%20') %>/disable" method="post">
|
63
73
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
64
|
-
<input class='btn btn-xs pull-left' type="submit" name="disable" value="<%= t('Disable') %>"/>
|
74
|
+
<input class='btn btn-warn btn-xs pull-left' type="submit" name="disable" value="<%= t('Disable') %>"/>
|
65
75
|
</form>
|
66
76
|
<% else %>
|
67
77
|
<form action="<%= root_path %>cron/<%= CGI.escape(job.name).gsub('+', '%20') %>/enque" method="post">
|
68
78
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
69
|
-
<input class='btn btn-xs pull-left' type="submit" name="enque" value="<%= t('EnqueueNow') %>"/>
|
79
|
+
<input class='btn btn-warn btn-xs pull-left' type="submit" name="enque" value="<%= t('EnqueueNow') %>"/>
|
70
80
|
</form>
|
71
81
|
<form action="<%= root_path %>cron/<%= CGI.escape(job.name).gsub('+', '%20') %>/enable" method="post">
|
72
82
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
73
|
-
<input class='btn btn-xs pull-left' type="submit" name="enable" value="<%= t('Enable') %>"/>
|
83
|
+
<input class='btn btn-warn btn-xs pull-left' type="submit" name="enable" value="<%= t('Enable') %>"/>
|
74
84
|
</form>
|
75
85
|
<form action="<%= root_path %>cron/<%= CGI.escape(job.name).gsub('+', '%20') %>/delete" method="post">
|
76
86
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
@@ -83,6 +93,6 @@
|
|
83
93
|
</tbody>
|
84
94
|
</table>
|
85
95
|
<% else %>
|
86
|
-
<
|
96
|
+
<div class='alert alert-success'><%= t('NoCronJobsWereFound') %></div>
|
87
97
|
<% end %>
|
88
98
|
|
@@ -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 %>" method="post">
|
11
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
12
|
+
<input class="btn btn-warn pull-left" name="enque" type="submit" value="<%= t('EnqueueNow') %>" data-confirm="<%= t('AreYouSureEnqueueCronJob', :job => @job.name) %>" />
|
13
|
+
</form>
|
14
|
+
<% if @job.status == 'enabled' %>
|
15
|
+
<form action="<%= cron_job_path %>/disable?redirect=<%= cron_job_path %>" method="post">
|
16
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
17
|
+
<input class="btn btn-warn pull-left" name="disable" type="submit" value="<%= t('Disable') %>" />
|
18
|
+
</form>
|
19
|
+
<% else %>
|
20
|
+
<form action="<%= cron_job_path %>/enable?redirect=<%= cron_job_path %>" method="post">
|
21
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
22
|
+
<input class="btn btn-warn pull-left" name="enable" type="submit" value="<%= t('Enable') %>" />
|
23
|
+
</form>
|
24
|
+
<form action="<%= cron_job_path %>/delete" method="post">
|
25
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
26
|
+
<input class="btn btn-danger" 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 %>
|
data/lib/sidekiq/cron/web.rb
CHANGED
@@ -3,11 +3,5 @@ require "sidekiq/cron/job"
|
|
3
3
|
|
4
4
|
if defined?(Sidekiq::Web)
|
5
5
|
Sidekiq::Web.register Sidekiq::Cron::WebExtension
|
6
|
-
|
7
|
-
if Sidekiq::Web.tabs.is_a?(Array)
|
8
|
-
# For sidekiq < 2.5
|
9
|
-
Sidekiq::Web.tabs << "cron"
|
10
|
-
else
|
11
|
-
Sidekiq::Web.tabs["Cron"] = "cron"
|
12
|
-
end
|
6
|
+
Sidekiq::Web.tabs["Cron"] = "cron"
|
13
7
|
end
|
@@ -1,36 +1,41 @@
|
|
1
1
|
module Sidekiq
|
2
2
|
module Cron
|
3
3
|
module WebExtension
|
4
|
-
|
5
4
|
def self.registered(app)
|
6
|
-
|
7
5
|
app.settings.locales << File.join(File.expand_path("..", __FILE__), "locales")
|
8
6
|
|
9
|
-
#
|
7
|
+
# Index page of cron jobs.
|
10
8
|
app.get '/cron' do
|
11
9
|
view_path = File.join(File.expand_path("..", __FILE__), "views")
|
12
10
|
|
13
11
|
@cron_jobs = Sidekiq::Cron::Job.all
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
render(:erb, File.read(File.join(view_path, "cron.erb")))
|
14
|
+
end
|
15
|
+
|
16
|
+
# Display job detail + jid history.
|
17
|
+
app.get '/cron/:name' do
|
18
|
+
view_path = File.join(File.expand_path("..", __FILE__), "views")
|
19
|
+
|
20
|
+
@job = Sidekiq::Cron::Job.find(route_params[:name])
|
21
|
+
if @job
|
22
|
+
render(:erb, File.read(File.join(view_path, "cron_show.erb")))
|
18
23
|
else
|
19
|
-
|
24
|
+
redirect "#{root_path}cron"
|
20
25
|
end
|
21
26
|
end
|
22
27
|
|
23
|
-
#
|
28
|
+
# Enqueue cron job.
|
24
29
|
app.post '/cron/:name/enque' do
|
25
30
|
if route_params[:name] === '__all__'
|
26
31
|
Sidekiq::Cron::Job.all.each(&:enque!)
|
27
32
|
elsif job = Sidekiq::Cron::Job.find(route_params[:name])
|
28
33
|
job.enque!
|
29
34
|
end
|
30
|
-
redirect "#{root_path}cron"
|
35
|
+
redirect params['redirect'] || "#{root_path}cron"
|
31
36
|
end
|
32
37
|
|
33
|
-
#
|
38
|
+
# Delete schedule.
|
34
39
|
app.post '/cron/:name/delete' do
|
35
40
|
if route_params[:name] === '__all__'
|
36
41
|
Sidekiq::Cron::Job.all.each(&:destroy)
|
@@ -40,26 +45,25 @@ module Sidekiq
|
|
40
45
|
redirect "#{root_path}cron"
|
41
46
|
end
|
42
47
|
|
43
|
-
#
|
48
|
+
# Enable job.
|
44
49
|
app.post '/cron/:name/enable' do
|
45
50
|
if route_params[:name] === '__all__'
|
46
51
|
Sidekiq::Cron::Job.all.each(&:enable!)
|
47
52
|
elsif job = Sidekiq::Cron::Job.find(route_params[:name])
|
48
53
|
job.enable!
|
49
54
|
end
|
50
|
-
redirect "#{root_path}cron"
|
55
|
+
redirect params['redirect'] || "#{root_path}cron"
|
51
56
|
end
|
52
57
|
|
53
|
-
#
|
58
|
+
# Disable job.
|
54
59
|
app.post '/cron/:name/disable' do
|
55
60
|
if route_params[:name] === '__all__'
|
56
61
|
Sidekiq::Cron::Job.all.each(&:disable!)
|
57
62
|
elsif job = Sidekiq::Cron::Job.find(route_params[:name])
|
58
63
|
job.disable!
|
59
64
|
end
|
60
|
-
redirect "#{root_path}cron"
|
65
|
+
redirect params['redirect'] || "#{root_path}cron"
|
61
66
|
end
|
62
|
-
|
63
67
|
end
|
64
68
|
end
|
65
69
|
end
|