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.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +145 -0
  3. data/Gemfile +3 -29
  4. data/README.md +175 -121
  5. data/Rakefile +3 -42
  6. data/lib/sidekiq/cron/job.rb +273 -144
  7. data/lib/sidekiq/cron/launcher.rb +39 -43
  8. data/lib/sidekiq/cron/locales/de.yml +2 -2
  9. data/lib/sidekiq/cron/locales/en.yml +6 -2
  10. data/lib/sidekiq/cron/locales/it.yml +23 -0
  11. data/lib/sidekiq/cron/locales/ja.yml +18 -0
  12. data/lib/sidekiq/cron/locales/pt.yml +22 -0
  13. data/lib/sidekiq/cron/locales/ru.yml +2 -2
  14. data/lib/sidekiq/cron/locales/zh-CN.yml +19 -0
  15. data/lib/sidekiq/cron/poller.rb +22 -12
  16. data/lib/sidekiq/cron/schedule_loader.rb +22 -0
  17. data/lib/sidekiq/cron/support.rb +8 -1
  18. data/lib/sidekiq/cron/version.rb +7 -0
  19. data/lib/sidekiq/cron/views/cron.erb +38 -28
  20. data/lib/sidekiq/cron/views/cron_show.erb +88 -0
  21. data/lib/sidekiq/cron/web.rb +1 -7
  22. data/lib/sidekiq/cron/web_extension.rb +19 -15
  23. data/lib/sidekiq/cron.rb +1 -0
  24. data/lib/sidekiq/options.rb +25 -0
  25. data/sidekiq-cron.gemspec +23 -108
  26. data/test/integration/performance_test.rb +13 -19
  27. data/test/models/person.rb +21 -0
  28. data/test/test_helper.rb +37 -38
  29. data/test/unit/fixtures/schedule_array.yml +13 -0
  30. data/test/unit/fixtures/schedule_erb.yml +6 -0
  31. data/test/unit/fixtures/schedule_hash.yml +12 -0
  32. data/test/unit/fixtures/schedule_string.yml +1 -0
  33. data/test/unit/job_test.rb +450 -35
  34. data/test/unit/launcher_test.rb +33 -0
  35. data/test/unit/poller_test.rb +28 -37
  36. data/test/unit/schedule_loader_test.rb +58 -0
  37. data/test/unit/web_extension_test.rb +59 -41
  38. metadata +72 -191
  39. data/.document +0 -5
  40. data/.travis.yml +0 -19
  41. data/Changes.md +0 -50
  42. data/Dockerfile +0 -32
  43. data/VERSION +0 -1
  44. data/config.ru +0 -14
  45. data/docker-compose.yml +0 -21
  46. data/examples/web-cron-ui.png +0 -0
  47. 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
- # we are creating new cron poller instance and
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
- class Launcher
14
- # Add cron poller to launcher
15
- attr_reader :cron_poller
16
-
17
- # remember old initialize
18
- alias_method :old_initialize, :initialize
19
-
20
- # add cron poller and execute normal initialize of Sidekiq launcher
21
- def initialize(options)
22
- @cron_poller = Sidekiq::Cron::Poller.new
23
- old_initialize options
24
- end
25
-
26
- # remember old run
27
- alias_method :old_run, :run
28
-
29
- # execute normal run of launcher and run cron poller
30
- def run
31
- old_run
32
- cron_poller.start
33
- end
34
-
35
- # remember old quiet
36
- alias_method :old_quiet, :quiet
37
-
38
- # execute normal quiet of launcher and quiet cron poller
39
- def quiet
40
- cron_poller.terminate
41
- old_quiet
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
- # remember old stop
45
- alias_method :old_stop, :stop
45
+ Sidekiq.configure_server do
46
+ require 'sidekiq/launcher'
46
47
 
47
- # execute normal stop of launcher and stop cron poller
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
- NoCronJobsFound: "Keine Cronjobs gefunden"
8
+ NoCronJobsWereFound: Keine Cronjobs gefunden
9
9
  Enable: Aktivieren
10
10
  Disable: Deaktivieren
11
- 'Last enque': Eingereiht
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
- NoCronJobsFound: "No cron jobs found"
15
+ NoCronJobsWereFound: No cron jobs were found
14
16
  Enable: Enable
15
17
  Disable: Disable
16
- 'Last enque': Last enqueued
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
- NoCronJobsFound: "Не найдено периодических задач"
9
+ NoCronJobsWereFound: Не найдено периодических задач
10
10
  Enable: Включить
11
11
  Disable: Отключить
12
- 'Last enque': Последний запуск
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
+
@@ -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
- POLL_INTERVAL = 30
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
- # problem somewhere in one job
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
- Sidekiq.options[:poll_interval] || POLL_INTERVAL
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
@@ -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
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sidekiq
4
+ module Cron
5
+ VERSION = "1.10.0"
6
+ end
7
+ end
@@ -1,24 +1,26 @@
1
1
  <header class='row'>
2
2
  <div class='col-sm-5 pull-left'>
3
- <h3><%=t 'CronJobs' %></h3>
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
- <form action="<%= root_path %>cron/__all__/delete" method="post" class="pull-right">
7
- <%= csrf_tag if respond_to?(:csrf_tag) %>
8
- <input class="btn btn-small btn-danger" type="submit" name="delete" value="<%= t('DeleteAll') %>" data-confirm="<%= t('AreYouSureDeleteCronJobs') %>">
9
- </form>
10
- <form action="<%= root_path %>cron/__all__/disable" method="post" class="pull-right">
11
- <%= csrf_tag if respond_to?(:csrf_tag) %>
12
- <input class="btn btn-small" type="submit" name="enque" value="<%= t('DisableAll') %>" />
13
- </form>
14
- <form action="<%= root_path %>cron/__all__/enable" method="post" class="pull-right">
15
- <%= csrf_tag if respond_to?(:csrf_tag) %>
16
- <input class="btn btn-small" type="submit" name="enque" value="<%= t('EnableAll') %>" />
17
- </form>
18
- <form action="<%= root_path %>cron/__all__/enque" method="post" class="pull-right">
19
- <%= csrf_tag if respond_to?(:csrf_tag) %>
20
- <input class="btn btn-small" type="submit" name="enque" value="<%= t('EnqueueAll') %>" />
21
- </form>
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 enque') %></th>
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
- <b><%= job.name %></b>
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
- <button data-toggle="collapse" data-target=".worker_<%= index %>" class="btn btn-xs"><%= t('ShowAll')%></button>
47
- <div class="toggle worker_<%= index %>" style="display: inline;"><%= job.message[0..100] + "... " %></div>
48
- <div class="toggle worker_<%= index %>" style="display: none;"><%= job.message %></div>
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
- <span class='alert alert-success'><%= t('NoCronJobsFound') %></span>
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(" ", "&nbsp;") %></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 %>
@@ -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
- #index page of cron jobs
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
- #if Slim renderer exists and sidekiq has layout.slim in views
16
- if defined?(Slim) && File.exists?(File.join(settings.views,"layout.slim"))
17
- render(:slim, File.read(File.join(view_path, "cron.slim")))
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
- render(:erb, File.read(File.join(view_path, "cron.erb")))
24
+ redirect "#{root_path}cron"
20
25
  end
21
26
  end
22
27
 
23
- #enque cron job
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
- #delete schedule
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
- #enable job
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
- #disable job
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
data/lib/sidekiq/cron.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "sidekiq/cron/job"
2
2
  require "sidekiq/cron/poller"
3
3
  require "sidekiq/cron/launcher"
4
+ require "sidekiq/cron/schedule_loader"
4
5
 
5
6
  module Sidekiq
6
7
  module Cron