sidekiq-cron 0.6.3 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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