sidekiq-cron 1.12.0 → 2.0.0.rc2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -2
- data/README.md +196 -35
- data/lib/sidekiq/cron/job.rb +236 -154
- data/lib/sidekiq/cron/launcher.rb +2 -5
- data/lib/sidekiq/cron/locales/id.yml +22 -0
- data/lib/sidekiq/cron/namespace.rb +43 -0
- data/lib/sidekiq/cron/poller.rb +12 -13
- data/lib/sidekiq/cron/schedule_loader.rb +1 -5
- data/lib/sidekiq/cron/support.rb +1 -2
- data/lib/sidekiq/cron/version.rb +1 -1
- data/lib/sidekiq/cron/views/cron.erb +53 -38
- data/lib/sidekiq/cron/views/cron_show.erb +11 -7
- data/lib/sidekiq/cron/web.rb +12 -2
- data/lib/sidekiq/cron/web_extension.rb +71 -25
- data/lib/sidekiq/cron.rb +61 -5
- data/lib/sidekiq/options.rb +3 -5
- data/lib/sidekiq-cron.rb +6 -0
- data/sidekiq-cron.gemspec +3 -2
- metadata +31 -9
@@ -0,0 +1,43 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Cron
|
3
|
+
class Namespace
|
4
|
+
def self.all
|
5
|
+
namespaces = nil
|
6
|
+
|
7
|
+
Sidekiq.redis do |conn|
|
8
|
+
namespaces = conn.keys('cron_jobs:*').collect do |key|
|
9
|
+
key.split(':').last
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Adds the default namespace if not present
|
14
|
+
has_default = namespaces.detect do |name|
|
15
|
+
name == Sidekiq::Cron.configuration.default_namespace
|
16
|
+
end
|
17
|
+
|
18
|
+
unless has_default
|
19
|
+
namespaces << Sidekiq::Cron.configuration.default_namespace
|
20
|
+
end
|
21
|
+
|
22
|
+
namespaces
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.all_with_count
|
26
|
+
all.map do |namespace_name|
|
27
|
+
{
|
28
|
+
count: count(namespace_name),
|
29
|
+
name: namespace_name
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.count(name = Sidekiq::Cron.configuration.default_namespace)
|
35
|
+
out = 0
|
36
|
+
Sidekiq.redis do |conn|
|
37
|
+
out = conn.scard("cron_jobs:#{name}")
|
38
|
+
end
|
39
|
+
out
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/sidekiq/cron/poller.rb
CHANGED
@@ -1,25 +1,24 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
require 'sidekiq/scheduled'
|
4
|
-
require 'sidekiq/options'
|
5
4
|
|
6
5
|
module Sidekiq
|
7
6
|
module Cron
|
8
|
-
# The Poller checks Redis every N seconds for
|
7
|
+
# The Poller checks Redis every N seconds for scheduled cron jobs.
|
9
8
|
class Poller < Sidekiq::Scheduled::Poller
|
10
9
|
def initialize(config = nil)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def start
|
14
|
+
Sidekiq::Cron::Job.migrate_old_jobs_if_needed!
|
15
|
+
|
16
|
+
super
|
18
17
|
end
|
19
18
|
|
20
19
|
def enqueue
|
21
20
|
time = Time.now.utc
|
22
|
-
Sidekiq::Cron::Job.all.each do |job|
|
21
|
+
Sidekiq::Cron::Job.all('*').each do |job|
|
23
22
|
enqueue_job(job, time)
|
24
23
|
end
|
25
24
|
rescue => ex
|
@@ -33,7 +32,7 @@ module Sidekiq
|
|
33
32
|
private
|
34
33
|
|
35
34
|
def enqueue_job(job, time = Time.now.utc)
|
36
|
-
job.
|
35
|
+
job.test_and_enqueue_for_time! time if job && job.valid?
|
37
36
|
rescue => ex
|
38
37
|
# Problem somewhere in one job.
|
39
38
|
Sidekiq.logger.error "CRON JOB: #{ex.message}"
|
@@ -1,9 +1,5 @@
|
|
1
|
-
require 'sidekiq'
|
2
|
-
require 'sidekiq/cron/job'
|
3
|
-
require 'sidekiq/options'
|
4
|
-
|
5
1
|
Sidekiq.configure_server do |config|
|
6
|
-
schedule_file = Sidekiq::
|
2
|
+
schedule_file = Sidekiq::Cron.configuration.cron_schedule_file
|
7
3
|
|
8
4
|
if File.exist?(schedule_file)
|
9
5
|
config.on(:startup) do
|
data/lib/sidekiq/cron/support.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
# https://github.com/rails/rails/blob/352865d0f835c24daa9a2e9863dcc9dde9e5371a/activesupport/lib/active_support/inflector/methods.rb#L270
|
2
|
-
|
3
1
|
module Sidekiq
|
4
2
|
module Cron
|
5
3
|
module Support
|
4
|
+
# Inspired by Active Support Inflector
|
6
5
|
def self.constantize(camel_cased_word)
|
7
6
|
names = camel_cased_word.split("::".freeze)
|
8
7
|
|
data/lib/sidekiq/cron/version.rb
CHANGED
@@ -1,22 +1,25 @@
|
|
1
1
|
<header class='row'>
|
2
2
|
<div class='col-sm-5 pull-left'>
|
3
|
-
<h3
|
3
|
+
<h3>
|
4
|
+
<%= t('CronJobs') %>
|
5
|
+
<small><%= @current_namespace %></small>
|
6
|
+
</h3>
|
4
7
|
</div>
|
5
|
-
<div class='col-sm-7 pull-right'
|
8
|
+
<div class='col-sm-7 pull-right h2'>
|
6
9
|
<% if @cron_jobs.size > 0 %>
|
7
|
-
<form action="<%= root_path %>cron/
|
10
|
+
<form action="<%= root_path %>cron/namespaces/<%= @current_namespace %>/all/delete" method="post" class="pull-right">
|
8
11
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
9
12
|
<input class="btn btn-danger" type="submit" name="delete" value="<%= t('DeleteAll') %>" data-confirm="<%= t('AreYouSureDeleteCronJobs') %>" />
|
10
13
|
</form>
|
11
|
-
<form action="<%= root_path %>cron/
|
14
|
+
<form action="<%= root_path %>cron/namespaces/<%= @current_namespace %>/all/disable" method="post" class="pull-right">
|
12
15
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
13
16
|
<input class="btn btn-warn" type="submit" name="enque" value="<%= t('DisableAll') %>" />
|
14
17
|
</form>
|
15
|
-
<form action="<%= root_path %>cron/
|
18
|
+
<form action="<%= root_path %>cron/namespaces/<%= @current_namespace %>/all/enable" method="post" class="pull-right">
|
16
19
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
17
20
|
<input class="btn btn-warn" type="submit" name="enque" value="<%= t('EnableAll') %>" />
|
18
21
|
</form>
|
19
|
-
<form action="<%= root_path %>cron/
|
22
|
+
<form action="<%= root_path %>cron/namespaces/<%= @current_namespace %>/all/enque" method="post" class="pull-right">
|
20
23
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
21
24
|
<input class="btn btn-warn" type="submit" name="enque" value="<%= t('EnqueueAll') %>" data-confirm="<%= t('AreYouSureEnqueueCronJobs') %>" />
|
22
25
|
</form>
|
@@ -24,67 +27,79 @@
|
|
24
27
|
</div>
|
25
28
|
</header>
|
26
29
|
|
27
|
-
|
30
|
+
<!-- Namespaces -->
|
31
|
+
<div class='row'>
|
32
|
+
<div class="col-sm-12 summary_bar">
|
33
|
+
<ul class="list-unstyled summary row">
|
34
|
+
<% @namespaces.sort_by { |namespace| namespace[:name] }.each do |namespace| %>
|
35
|
+
<li class="col-sm-1">
|
36
|
+
<a href="<%= root_path %>cron/namespaces/<%= namespace[:name] %>">
|
37
|
+
<span class="count"><%= namespace[:count] %></span>
|
38
|
+
<span class="desc"><%= namespace[:name] %></span>
|
39
|
+
</a>
|
40
|
+
</li>
|
41
|
+
<% end %>
|
42
|
+
</ul>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
<!-- Namespaces -->
|
28
46
|
|
47
|
+
<% if @cron_jobs.size > 0 %>
|
29
48
|
<table class="table table-hover table-bordered table-striped table-white">
|
30
49
|
<thead>
|
50
|
+
<tr>
|
31
51
|
<th><%= t('Status') %></th>
|
32
|
-
<th><%= t('Name') %></th>
|
52
|
+
<th width="50%"><%= t('Name') %></th>
|
33
53
|
<th><%= t('Cron string') %></th>
|
34
54
|
<th><%= t('Last enqueued') %></th>
|
35
|
-
<th width="180"><%= t('Actions')%></th>
|
55
|
+
<th width="180"><%= t('Actions') %></th>
|
56
|
+
</tr>
|
36
57
|
</thead>
|
37
58
|
|
38
59
|
<tbody>
|
39
|
-
<% @cron_jobs.sort{|a,b| a.sort_name <=> b.sort_name }.
|
40
|
-
<%
|
60
|
+
<% @cron_jobs.sort{ |a,b| a.sort_name <=> b.sort_name }.each do |job| %>
|
61
|
+
<% klass = (job.status == 'disabled') ? 'bg-danger text-muted' : '' %>
|
62
|
+
<% escaped_job_name = CGI.escape(job.name).gsub('+', '%20') %>
|
41
63
|
<tr>
|
42
|
-
<td
|
43
|
-
<td
|
44
|
-
<a href="<%= root_path %>cron/<%=
|
45
|
-
<b
|
64
|
+
<td class="<%= klass %>"><%= t job.status %></td>
|
65
|
+
<td class="<%= klass %>">
|
66
|
+
<a href="<%= root_path %>cron/namespaces/<%= job.namespace %>/jobs/<%= escaped_job_name %>" title="<%= job.description %>">
|
67
|
+
<b class="<%= klass %>"><%= job.name %></b>
|
46
68
|
</a>
|
47
|
-
<
|
48
|
-
<small>
|
69
|
+
<br/>
|
49
70
|
<% if job.message and job.message.to_s.size > 100 %>
|
50
|
-
|
51
|
-
<
|
52
|
-
<
|
53
|
-
|
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 %>
|
71
|
+
<details>
|
72
|
+
<summary class="btn btn-warn btn-xs">Show message</summary>
|
73
|
+
<p><small><%= job.message %></small></p>
|
74
|
+
</details>
|
59
75
|
<% else %>
|
60
|
-
|
76
|
+
<small><%= job.message %></small>
|
61
77
|
<% end %>
|
62
|
-
</small>
|
63
78
|
</td>
|
64
|
-
<td
|
65
|
-
<td
|
66
|
-
<td
|
79
|
+
<td class="<%= klass %>"><b><%= job.human_cron %><br/><small><%= job.cron.gsub(" ", " ") %></small></b></td>
|
80
|
+
<td class="<%= klass %>"><%= job.last_enqueue_time ? relative_time(job.last_enqueue_time) : "-" %></td>
|
81
|
+
<td class="<%= klass %>">
|
67
82
|
<% if job.status == 'enabled' %>
|
68
|
-
<form action="<%= root_path %>cron/<%=
|
83
|
+
<form action="<%= root_path %>cron/namespaces/<%= job.namespace %>/jobs/<%= escaped_job_name %>/enque" method="post">
|
69
84
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
70
85
|
<input class='btn btn-warn btn-xs pull-left' type="submit" name="enque" value="<%= t('EnqueueNow') %>" data-confirm="<%= t('AreYouSureEnqueueCronJob', :job => job.name) %>"/>
|
71
86
|
</form>
|
72
|
-
<form action="<%= root_path %>cron/<%=
|
87
|
+
<form action="<%= root_path %>cron/namespaces/<%= job.namespace %>/jobs/<%= escaped_job_name %>/disable" method="post">
|
73
88
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
74
89
|
<input class='btn btn-warn btn-xs pull-left' type="submit" name="disable" value="<%= t('Disable') %>"/>
|
75
90
|
</form>
|
76
91
|
<% else %>
|
77
|
-
<form action="<%= root_path %>cron/<%=
|
92
|
+
<form action="<%= root_path %>cron/namespaces/<%= job.namespace %>/jobs/<%= escaped_job_name %>/enque" method="post">
|
78
93
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
79
|
-
<input class='btn btn-warn btn-xs pull-left' type="submit" name="enque" value="<%= t('EnqueueNow') %>"/>
|
94
|
+
<input class='btn btn-warn btn-xs pull-left' type="submit" name="enque" value="<%= t('EnqueueNow') %>" data-confirm="<%= t('AreYouSureEnqueueCronJob', :job => job.name) %>"/>
|
80
95
|
</form>
|
81
|
-
<form action="<%= root_path %>cron/<%=
|
96
|
+
<form action="<%= root_path %>cron/namespaces/<%= job.namespace %>/jobs/<%= escaped_job_name %>/enable" method="post">
|
82
97
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
83
98
|
<input class='btn btn-warn btn-xs pull-left' type="submit" name="enable" value="<%= t('Enable') %>"/>
|
84
99
|
</form>
|
85
|
-
<form action="<%= root_path %>cron/<%=
|
100
|
+
<form action="<%= root_path %>cron/namespaces/<%= job.namespace %>/jobs/<%= escaped_job_name %>/delete" method="post">
|
86
101
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
87
|
-
<input class='btn btn-xs btn-danger pull-left' type="submit" name="delete" value="<%= t('Delete') %>" data-confirm="<%= t('AreYouSureDeleteCronJob', :job => job.name) %>"/>
|
102
|
+
<input class='btn btn-xs btn-danger pull-left help-block' type="submit" name="delete" value="<%= t('Delete') %>" data-confirm="<%= t('AreYouSureDeleteCronJob', :job => job.name) %>"/>
|
88
103
|
</form>
|
89
104
|
<% end %>
|
90
105
|
</td>
|
@@ -5,25 +5,25 @@
|
|
5
5
|
<small><%= @job.name %></small>
|
6
6
|
</h3>
|
7
7
|
</div>
|
8
|
-
<div class="span col-sm-7 pull-right
|
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">
|
8
|
+
<div class="span col-sm-7 pull-right h2">
|
9
|
+
<% cron_job_path = "#{root_path}cron/namespaces/#{@current_namespace}/jobs/#{CGI.escape(@job.name).gsub('+', '%20')}" %>
|
10
|
+
<form action="<%= cron_job_path %>/enque?redirect=<%= cron_job_path %>" class="pull-right" method="post">
|
11
11
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
12
12
|
<input class="btn btn-warn pull-left" name="enque" type="submit" value="<%= t('EnqueueNow') %>" data-confirm="<%= t('AreYouSureEnqueueCronJob', :job => @job.name) %>" />
|
13
13
|
</form>
|
14
14
|
<% if @job.status == 'enabled' %>
|
15
|
-
<form action="<%= cron_job_path %>/disable?redirect=<%= cron_job_path %>" method="post">
|
15
|
+
<form action="<%= cron_job_path %>/disable?redirect=<%= cron_job_path %>" class="pull-right" method="post">
|
16
16
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
17
17
|
<input class="btn btn-warn pull-left" name="disable" type="submit" value="<%= t('Disable') %>" />
|
18
18
|
</form>
|
19
19
|
<% else %>
|
20
|
-
<form action="<%= cron_job_path %>/enable?redirect=<%= cron_job_path %>" method="post">
|
20
|
+
<form action="<%= cron_job_path %>/enable?redirect=<%= cron_job_path %>" class="pull-right" method="post">
|
21
21
|
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
22
22
|
<input class="btn btn-warn pull-left" name="enable" type="submit" value="<%= t('Enable') %>" />
|
23
23
|
</form>
|
24
|
-
<form action="<%= cron_job_path %>/delete" method="post">
|
24
|
+
<form action="<%= cron_job_path %>/delete" class="pull-right" method="post">
|
25
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') %>" />
|
26
|
+
<input class="btn btn-danger pull-left" data-confirm="<%= t('AreYouSureDeleteCronJob', :job => @job.name) %>" name="delete" type="submit" value="<%= t('Delete') %>" />
|
27
27
|
</form>
|
28
28
|
<% end %>
|
29
29
|
</div>
|
@@ -39,6 +39,10 @@
|
|
39
39
|
<th><%= t 'Name' %></th>
|
40
40
|
<td><%= @job.name %></td>
|
41
41
|
</tr>
|
42
|
+
<tr>
|
43
|
+
<th><%= t 'Namespace' %></th>
|
44
|
+
<td><%= @job.namespace %></td>
|
45
|
+
</tr>
|
42
46
|
<tr>
|
43
47
|
<th><%= t 'Description' %></th>
|
44
48
|
<td><%= @job.description %></td>
|
data/lib/sidekiq/cron/web.rb
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
require "sidekiq/cron/web_extension"
|
2
2
|
require "sidekiq/cron/job"
|
3
|
+
require "sidekiq/cron/namespace"
|
3
4
|
|
4
5
|
if defined?(Sidekiq::Web)
|
5
|
-
|
6
|
-
|
6
|
+
if Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('7.3.0')
|
7
|
+
Sidekiq::Web.register(
|
8
|
+
Sidekiq::Cron::WebExtension, # Class which contains the HTTP actions, required
|
9
|
+
name: "cron", # the name of the extension, used to namespace assets
|
10
|
+
tab: "Cron", # labels(s) of the UI tabs
|
11
|
+
index: "cron", # index route(s) for each tab
|
12
|
+
)
|
13
|
+
else
|
14
|
+
Sidekiq::Web.register Sidekiq::Cron::WebExtension
|
15
|
+
Sidekiq::Web.tabs["Cron"] = "cron"
|
16
|
+
end
|
7
17
|
end
|
@@ -4,65 +4,111 @@ module Sidekiq
|
|
4
4
|
def self.registered(app)
|
5
5
|
app.settings.locales << File.join(File.expand_path("..", __FILE__), "locales")
|
6
6
|
|
7
|
+
app.helpers do
|
8
|
+
# This method constructs the URL for the cron jobs page within the specified namespace.
|
9
|
+
def namespace_redirect_path
|
10
|
+
"#{root_path}cron/namespaces/#{route_params[:namespace]}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
7
14
|
# Index page of cron jobs.
|
8
15
|
app.get '/cron' do
|
9
|
-
view_path
|
16
|
+
view_path = File.join(File.expand_path("..", __FILE__), "views")
|
10
17
|
|
18
|
+
@current_namespace = 'default'
|
19
|
+
|
20
|
+
@namespaces = Sidekiq::Cron::Namespace.all_with_count
|
21
|
+
|
22
|
+
# Not passing namespace takes all the jobs from the default one.
|
11
23
|
@cron_jobs = Sidekiq::Cron::Job.all
|
12
24
|
|
13
25
|
render(:erb, File.read(File.join(view_path, "cron.erb")))
|
14
26
|
end
|
15
27
|
|
28
|
+
app.get '/cron/namespaces/:name' do
|
29
|
+
view_path = File.join(File.expand_path("..", __FILE__), "views")
|
30
|
+
|
31
|
+
@current_namespace = route_params[:name]
|
32
|
+
|
33
|
+
@namespaces = Sidekiq::Cron::Namespace.all_with_count
|
34
|
+
|
35
|
+
@cron_jobs = Sidekiq::Cron::Job.all(@current_namespace)
|
36
|
+
|
37
|
+
render(:erb, File.read(File.join(view_path, "cron.erb")))
|
38
|
+
end
|
39
|
+
|
16
40
|
# Display job detail + jid history.
|
17
|
-
app.get '/cron/:name' do
|
41
|
+
app.get '/cron/namespaces/:namespace/jobs/:name' do
|
18
42
|
view_path = File.join(File.expand_path("..", __FILE__), "views")
|
19
43
|
|
20
|
-
@
|
44
|
+
@current_namespace = route_params[:namespace]
|
45
|
+
@job_name = route_params[:name]
|
46
|
+
|
47
|
+
@namespaces = Sidekiq::Cron::Namespace.all_with_count
|
48
|
+
|
49
|
+
@job = Sidekiq::Cron::Job.find(@job_name, @current_namespace)
|
50
|
+
|
21
51
|
if @job
|
22
52
|
render(:erb, File.read(File.join(view_path, "cron_show.erb")))
|
23
53
|
else
|
24
|
-
redirect
|
54
|
+
redirect namespace_redirect_path
|
25
55
|
end
|
26
56
|
end
|
27
57
|
|
58
|
+
# Enqueue all cron jobs.
|
59
|
+
app.post '/cron/namespaces/:namespace/all/enque' do
|
60
|
+
Sidekiq::Cron::Job.all(route_params[:namespace]).each(&:enqueue!)
|
61
|
+
redirect params['redirect'] || namespace_redirect_path
|
62
|
+
end
|
63
|
+
|
28
64
|
# Enqueue cron job.
|
29
|
-
app.post '/cron/:name/enque' do
|
30
|
-
if route_params[:name]
|
31
|
-
|
32
|
-
elsif job = Sidekiq::Cron::Job.find(route_params[:name])
|
33
|
-
job.enque!
|
65
|
+
app.post '/cron/namespaces/:namespace/jobs/:name/enque' do
|
66
|
+
if job = Sidekiq::Cron::Job.find(route_params[:name], route_params[:namespace])
|
67
|
+
job.enqueue!
|
34
68
|
end
|
35
|
-
redirect params['redirect'] ||
|
69
|
+
redirect params['redirect'] || namespace_redirect_path
|
70
|
+
end
|
71
|
+
|
72
|
+
# Delete all schedules.
|
73
|
+
app.post '/cron/namespaces/:namespace/all/delete' do
|
74
|
+
Sidekiq::Cron::Job.all(route_params[:namespace]).each(&:destroy)
|
75
|
+
redirect params['redirect'] || namespace_redirect_path
|
36
76
|
end
|
37
77
|
|
38
78
|
# Delete schedule.
|
39
|
-
app.post '/cron/:name/delete' do
|
40
|
-
if route_params[:name]
|
41
|
-
Sidekiq::Cron::Job.all.each(&:destroy)
|
42
|
-
elsif job = Sidekiq::Cron::Job.find(route_params[:name])
|
79
|
+
app.post '/cron/namespaces/:namespace/jobs/:name/delete' do
|
80
|
+
if job = Sidekiq::Cron::Job.find(route_params[:name], route_params[:namespace])
|
43
81
|
job.destroy
|
44
82
|
end
|
45
|
-
redirect
|
83
|
+
redirect params['redirect'] || namespace_redirect_path
|
84
|
+
end
|
85
|
+
|
86
|
+
# Enable all jobs.
|
87
|
+
app.post '/cron/namespaces/:namespace/all/enable' do
|
88
|
+
Sidekiq::Cron::Job.all(route_params[:namespace]).each(&:enable!)
|
89
|
+
redirect params['redirect'] || namespace_redirect_path
|
46
90
|
end
|
47
91
|
|
48
92
|
# Enable job.
|
49
|
-
app.post '/cron/:name/enable' do
|
50
|
-
if route_params[:name]
|
51
|
-
Sidekiq::Cron::Job.all.each(&:enable!)
|
52
|
-
elsif job = Sidekiq::Cron::Job.find(route_params[:name])
|
93
|
+
app.post '/cron/namespaces/:namespace/jobs/:name/enable' do
|
94
|
+
if job = Sidekiq::Cron::Job.find(route_params[:name], route_params[:namespace])
|
53
95
|
job.enable!
|
54
96
|
end
|
55
|
-
redirect params['redirect'] ||
|
97
|
+
redirect params['redirect'] || namespace_redirect_path
|
98
|
+
end
|
99
|
+
|
100
|
+
# Disable all jobs.
|
101
|
+
app.post '/cron/namespaces/:namespace/all/disable' do
|
102
|
+
Sidekiq::Cron::Job.all(route_params[:namespace]).each(&:disable!)
|
103
|
+
redirect params['redirect'] || namespace_redirect_path
|
56
104
|
end
|
57
105
|
|
58
106
|
# Disable job.
|
59
|
-
app.post '/cron/:name/disable' do
|
60
|
-
if route_params[:name]
|
61
|
-
Sidekiq::Cron::Job.all.each(&:disable!)
|
62
|
-
elsif job = Sidekiq::Cron::Job.find(route_params[:name])
|
107
|
+
app.post '/cron/namespaces/:namespace/jobs/:name/disable' do
|
108
|
+
if job = Sidekiq::Cron::Job.find(route_params[:name], route_params[:namespace])
|
63
109
|
job.disable!
|
64
110
|
end
|
65
|
-
redirect params['redirect'] ||
|
111
|
+
redirect params['redirect'] || namespace_redirect_path
|
66
112
|
end
|
67
113
|
end
|
68
114
|
end
|
data/lib/sidekiq/cron.rb
CHANGED
@@ -1,9 +1,65 @@
|
|
1
|
-
require "sidekiq/cron/job"
|
2
|
-
require "sidekiq/cron/poller"
|
3
|
-
require "sidekiq/cron/launcher"
|
4
|
-
require "sidekiq/cron/schedule_loader"
|
5
|
-
|
6
1
|
module Sidekiq
|
7
2
|
module Cron
|
3
|
+
class << self
|
4
|
+
attr_accessor :configuration
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.configure
|
8
|
+
self.configuration ||= Configuration.new
|
9
|
+
yield(configuration) if block_given?
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.reset!
|
13
|
+
self.configuration = Configuration.new
|
14
|
+
end
|
15
|
+
|
16
|
+
class Configuration
|
17
|
+
# The default namespace is used when no namespace is specified.
|
18
|
+
attr_accessor :default_namespace
|
19
|
+
|
20
|
+
# The parsing mode when using the natural language cron syntax from the `fugit` gem.
|
21
|
+
#
|
22
|
+
# :single -- use the first parsed cron line and ignore the rest (default)
|
23
|
+
# :strict -- raise an error if multiple cron lines are parsed from one string
|
24
|
+
attr_reader :natural_cron_parsing_mode
|
25
|
+
|
26
|
+
# The poller will not enqueue jobs that are late by more than this amount of seconds.
|
27
|
+
# Defaults to 60 seconds.
|
28
|
+
#
|
29
|
+
# This is useful when sidekiq (and sidekiq-cron) is not used in zero downtime deployments and
|
30
|
+
# when the deployment is done and sidekiq-cron starts to catch up, it will consider older
|
31
|
+
# jobs that missed their schedules during the deployment. E.g., jobs that run once a day.
|
32
|
+
attr_accessor :reschedule_grace_period
|
33
|
+
|
34
|
+
# The maximum number of recent cron job execution histories to retain.
|
35
|
+
# This value controls how many past job executions are stored.
|
36
|
+
attr_accessor :cron_history_size
|
37
|
+
|
38
|
+
# The interval, in seconds, at which to poll for scheduled cron jobs.
|
39
|
+
# This determines how frequently the scheduler checks for jobs to enqueue.
|
40
|
+
attr_accessor :cron_poll_interval
|
41
|
+
|
42
|
+
# The path to a YAML file containing multiple cron job schedules.
|
43
|
+
attr_accessor :cron_schedule_file
|
44
|
+
|
45
|
+
def initialize
|
46
|
+
@default_namespace = 'default'
|
47
|
+
@natural_cron_parsing_mode = :single
|
48
|
+
@reschedule_grace_period = 60
|
49
|
+
@cron_history_size = 10
|
50
|
+
@cron_poll_interval = 30
|
51
|
+
@cron_schedule_file = 'config/schedule.yml'
|
52
|
+
end
|
53
|
+
|
54
|
+
def natural_cron_parsing_mode=(mode)
|
55
|
+
unless %i[single strict].include?(mode)
|
56
|
+
raise ArgumentError, "Unknown natural cron parsing mode: #{mode.inspect}"
|
57
|
+
end
|
58
|
+
|
59
|
+
@natural_cron_parsing_mode = mode
|
60
|
+
end
|
61
|
+
end
|
8
62
|
end
|
9
63
|
end
|
64
|
+
|
65
|
+
Sidekiq::Cron.configure
|
data/lib/sidekiq/options.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# Module to access Sidekiq config
|
3
2
|
module Sidekiq
|
4
3
|
module Options
|
5
4
|
def self.[](key)
|
@@ -16,13 +15,12 @@ module Sidekiq
|
|
16
15
|
|
17
16
|
def self.options_field
|
18
17
|
return @options_field unless @options_field.nil?
|
18
|
+
|
19
19
|
sidekiq_version = Gem::Version.new(Sidekiq::VERSION)
|
20
20
|
@options_field = if sidekiq_version >= Gem::Version.new('7.0')
|
21
21
|
:default_configuration
|
22
|
-
elsif sidekiq_version >= Gem::Version.new('6.5')
|
23
|
-
false
|
24
22
|
else
|
25
|
-
|
23
|
+
false
|
26
24
|
end
|
27
25
|
end
|
28
26
|
end
|
data/lib/sidekiq-cron.rb
CHANGED
data/sidekiq-cron.gemspec
CHANGED
@@ -26,9 +26,10 @@ Gem::Specification.new do |s|
|
|
26
26
|
|
27
27
|
s.required_ruby_version = ">= 2.7"
|
28
28
|
|
29
|
-
s.add_dependency("
|
30
|
-
s.add_dependency("
|
29
|
+
s.add_dependency("cronex", ">= 0.13.0")
|
30
|
+
s.add_dependency("fugit", "~> 1.8", ">= 1.11.1")
|
31
31
|
s.add_dependency("globalid", ">= 1.0.1")
|
32
|
+
s.add_dependency("sidekiq", ">= 6.5.0")
|
32
33
|
|
33
34
|
s.add_development_dependency("minitest", "~> 5.15")
|
34
35
|
s.add_development_dependency("mocha", "~> 2.1")
|