sidekiq-cron 1.0.4 → 1.2.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.
- checksums.yaml +4 -4
- data/.travis.yml +5 -8
- data/Changes.md +18 -0
- data/Dockerfile +1 -1
- data/README.md +9 -2
- data/VERSION +1 -1
- data/docker-compose.yml +3 -1
- data/lib/sidekiq/cron/job.rb +58 -17
- data/lib/sidekiq/cron/launcher.rb +34 -40
- data/lib/sidekiq/cron/locales/de.yml +1 -1
- data/lib/sidekiq/cron/locales/en.yml +3 -1
- data/lib/sidekiq/cron/locales/ja.yml +1 -1
- data/lib/sidekiq/cron/locales/ru.yml +1 -1
- data/lib/sidekiq/cron/locales/zh-CN.yml +1 -1
- data/lib/sidekiq/cron/poller.rb +4 -4
- data/lib/sidekiq/cron/views/cron.erb +4 -2
- data/lib/sidekiq/cron/views/cron.slim +3 -2
- data/lib/sidekiq/cron/views/cron_show.erb +88 -0
- data/lib/sidekiq/cron/views/cron_show.slim +61 -0
- data/lib/sidekiq/cron/web_extension.rb +20 -3
- data/sidekiq-cron.gemspec +6 -4
- data/test/integration/performance_test.rb +3 -5
- data/test/test_helper.rb +17 -6
- data/test/unit/job_test.rb +32 -3
- data/test/unit/poller_test.rb +1 -3
- data/test/unit/web_extension_test.rb +20 -1
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cb2f152cb3faf85dbc089e10820fd48d7c23f6ad
|
|
4
|
+
data.tar.gz: 4ced419b5c9ddaeb43a6ebd62221cdbd95eb2c91
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d882bd7a34f478fc9ea3eb591c6ffe01df2b360ba501ef2df13aa3d7631f77a97a393bc5a391ec682810766dbfe8790bb8a42ed29fc69a666623753103c4c994
|
|
7
|
+
data.tar.gz: 4bbdf927f3830a9a62e2bf622bf34492555e0a8051f303a0a712eda46a818a5dfd78b5de913e137e39b91f046a05247ae2a133cabe1573fa1b4f21307f721b24
|
data/.travis.yml
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
language: ruby
|
|
2
2
|
rvm:
|
|
3
|
-
- 2.
|
|
4
|
-
- 2.
|
|
5
|
-
- 2.
|
|
6
|
-
- 2.
|
|
3
|
+
- 2.6
|
|
4
|
+
- 2.5
|
|
5
|
+
- 2.4
|
|
6
|
+
- 2.3
|
|
7
|
+
- 2.2
|
|
7
8
|
services:
|
|
8
9
|
- redis-server
|
|
9
10
|
branches:
|
|
@@ -15,7 +16,3 @@ notifications:
|
|
|
15
16
|
- ondrej@bartas.cz
|
|
16
17
|
env:
|
|
17
18
|
travis: 'yes'
|
|
18
|
-
matrix:
|
|
19
|
-
allow_failures:
|
|
20
|
-
- rvm: jruby-19mode
|
|
21
|
-
- rvm: rbx-19mode
|
data/Changes.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
v 1.2.0
|
|
2
|
+
-------
|
|
3
|
+
|
|
4
|
+
- updated readme
|
|
5
|
+
- fix problem with Sidekiq::Launcher and requiring it when not needed
|
|
6
|
+
- better patching of Sidekiq::Launcher
|
|
7
|
+
- fixed Dockerfile
|
|
8
|
+
|
|
9
|
+
v 1.1.0
|
|
10
|
+
-------
|
|
11
|
+
|
|
12
|
+
- updated readme
|
|
13
|
+
- fix unit tests - changed argument error when getting invalid cron format
|
|
14
|
+
- when fallbacking old job enqueued time use `Time.parse` šwithout format (so ruby can decide best method to parse it)
|
|
15
|
+
- add option `date_as_argument` which will add to your job arguments on last place `Time.now.to_f` when it was eneuqued
|
|
16
|
+
- add option `description` which will allow you to add notes to your jobs so in web view you can see it
|
|
17
|
+
- fixed translations
|
|
18
|
+
|
|
1
19
|
v 1.0.4
|
|
2
20
|
-------
|
|
3
21
|
|
data/Dockerfile
CHANGED
data/README.md
CHANGED
|
@@ -19,6 +19,11 @@ Works with ActiveJob (Rails 4.2+)
|
|
|
19
19
|
|
|
20
20
|
You don't need Sidekiq PRO, you can use this gem with plain __Sidekiq__.
|
|
21
21
|
|
|
22
|
+
Upgrade from <0.6x to 1.0.x
|
|
23
|
+
---------------------------
|
|
24
|
+
|
|
25
|
+
Please be aware that sidekiq-cron < 1.0 was relying on rufus-scheduler < 3.5. Using those older sidekiq-cron with rufus-scheduler >= 3.5 ends up with jobs failing on creation. Sidekiq-cron 1.0 includes a patch that switches from rufus-scheduler to rufus-scheduler's core dependency, fugit.
|
|
26
|
+
|
|
22
27
|
Requirements
|
|
23
28
|
-----------------
|
|
24
29
|
|
|
@@ -37,7 +42,7 @@ Installation
|
|
|
37
42
|
|
|
38
43
|
or add to your `Gemfile`
|
|
39
44
|
|
|
40
|
-
gem "sidekiq-cron", "~>
|
|
45
|
+
gem "sidekiq-cron", "~> 1.1"
|
|
41
46
|
|
|
42
47
|
|
|
43
48
|
Getting Started
|
|
@@ -56,9 +61,11 @@ _Job properties_:
|
|
|
56
61
|
#OPTIONAL
|
|
57
62
|
'queue' => 'name of queue',
|
|
58
63
|
'args' => '[Array or Hash] of arguments which will be passed to perform method',
|
|
64
|
+
'date_as_argument' => true, # add the time of execution as last argument of the perform method
|
|
59
65
|
'active_job' => true, # enqueue job through rails 4.2+ active job interface
|
|
60
66
|
'queue_name_prefix' => 'prefix', # rails 4.2+ active job queue with prefix
|
|
61
|
-
'queue_name_delimiter' => '.' # rails 4.2+ active job queue with custom delimiter
|
|
67
|
+
'queue_name_delimiter' => '.', # rails 4.2+ active job queue with custom delimiter
|
|
68
|
+
'description' => 'A sentence describing what work this job performs.' # Optional
|
|
62
69
|
}
|
|
63
70
|
```
|
|
64
71
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0
|
|
1
|
+
1.2.0
|
data/docker-compose.yml
CHANGED
data/lib/sidekiq/cron/job.rb
CHANGED
|
@@ -13,7 +13,6 @@ module Sidekiq
|
|
|
13
13
|
#how long we would like to store informations about previous enqueues
|
|
14
14
|
REMEMBER_THRESHOLD = 24 * 60 * 60
|
|
15
15
|
LAST_ENQUEUE_TIME_FORMAT = '%Y-%m-%d %H:%M:%S %z'
|
|
16
|
-
LAST_ENQUEUE_TIME_FORMAT_OLD = '%Y-%m-%d %H:%M:%S'
|
|
17
16
|
|
|
18
17
|
#crucial part of whole enquing job
|
|
19
18
|
def should_enque? time
|
|
@@ -57,21 +56,23 @@ module Sidekiq
|
|
|
57
56
|
nil
|
|
58
57
|
end
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
if
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if @active_job
|
|
68
|
-
Sidekiq::Client.push(active_job_message)
|
|
59
|
+
jid =
|
|
60
|
+
if klass_const
|
|
61
|
+
if defined?(ActiveJob::Base) && klass_const < ActiveJob::Base
|
|
62
|
+
enqueue_active_job(klass_const).try :provider_job_id
|
|
63
|
+
else
|
|
64
|
+
enqueue_sidekiq_worker(klass_const)
|
|
65
|
+
end
|
|
69
66
|
else
|
|
70
|
-
|
|
67
|
+
if @active_job
|
|
68
|
+
Sidekiq::Client.push(active_job_message)
|
|
69
|
+
else
|
|
70
|
+
Sidekiq::Client.push(sidekiq_worker_message)
|
|
71
|
+
end
|
|
71
72
|
end
|
|
72
|
-
end
|
|
73
73
|
|
|
74
74
|
save_last_enqueue_time
|
|
75
|
+
add_jid_history jid
|
|
75
76
|
logger.debug { "enqueued #{@name}: #{@message}" }
|
|
76
77
|
end
|
|
77
78
|
|
|
@@ -83,14 +84,10 @@ module Sidekiq
|
|
|
83
84
|
|
|
84
85
|
def enqueue_active_job(klass_const)
|
|
85
86
|
klass_const.set(queue: @queue).perform_later(*@args)
|
|
86
|
-
|
|
87
|
-
true
|
|
88
87
|
end
|
|
89
88
|
|
|
90
89
|
def enqueue_sidekiq_worker(klass_const)
|
|
91
90
|
klass_const.set(queue: queue_name_with_prefix).perform_async(*@args)
|
|
92
|
-
|
|
93
|
-
true
|
|
94
91
|
end
|
|
95
92
|
|
|
96
93
|
# siodekiq worker message
|
|
@@ -283,6 +280,7 @@ module Sidekiq
|
|
|
283
280
|
|
|
284
281
|
#get right arguments for job
|
|
285
282
|
@args = args["args"].nil? ? [] : parse_args( args["args"] )
|
|
283
|
+
@args += [Time.now.to_f] if args["date_as_argument"]
|
|
286
284
|
|
|
287
285
|
@active_job = args["active_job"] == true || ("#{args["active_job"]}" =~ (/^(true|t|yes|y|1)$/i)) == 0 || false
|
|
288
286
|
@active_job_queue_name_prefix = args["queue_name_prefix"]
|
|
@@ -350,6 +348,12 @@ module Sidekiq
|
|
|
350
348
|
!enabled?
|
|
351
349
|
end
|
|
352
350
|
|
|
351
|
+
def pretty_message
|
|
352
|
+
JSON.pretty_generate Sidekiq.load_json(message)
|
|
353
|
+
rescue JSON::ParserError
|
|
354
|
+
message
|
|
355
|
+
end
|
|
356
|
+
|
|
353
357
|
def status_from_redis
|
|
354
358
|
out = "enabled"
|
|
355
359
|
if fetch_missing_args
|
|
@@ -371,6 +375,18 @@ module Sidekiq
|
|
|
371
375
|
out
|
|
372
376
|
end
|
|
373
377
|
|
|
378
|
+
def jid_history_from_redis
|
|
379
|
+
out =
|
|
380
|
+
Sidekiq.redis do |conn|
|
|
381
|
+
conn.lrange(jid_history_key, 0, -1) rescue nil
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# returns nil if out nil
|
|
385
|
+
out && out.map do |jid_history_raw|
|
|
386
|
+
Sidekiq.load_json jid_history_raw
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
374
390
|
#export job data to hash
|
|
375
391
|
def to_hash
|
|
376
392
|
{
|
|
@@ -457,6 +473,20 @@ module Sidekiq
|
|
|
457
473
|
end
|
|
458
474
|
end
|
|
459
475
|
|
|
476
|
+
def add_jid_history(jid)
|
|
477
|
+
jid_history = {
|
|
478
|
+
jid: jid,
|
|
479
|
+
enqueued: @last_enqueue_time
|
|
480
|
+
}
|
|
481
|
+
@history_size ||= (Sidekiq.options[:cron_history_size] || 10).to_i - 1
|
|
482
|
+
Sidekiq.redis do |conn|
|
|
483
|
+
conn.lpush jid_history_key,
|
|
484
|
+
Sidekiq.dump_json(jid_history)
|
|
485
|
+
# keep only last 10 entries in a fifo manner
|
|
486
|
+
conn.ltrim jid_history_key, 0, @history_size
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
460
490
|
# remove job from cron jobs by name
|
|
461
491
|
# input:
|
|
462
492
|
# first arg: name (string) - name of job (must be same - case sensitive)
|
|
@@ -468,6 +498,9 @@ module Sidekiq
|
|
|
468
498
|
#delete runned timestamps
|
|
469
499
|
conn.del job_enqueued_key
|
|
470
500
|
|
|
501
|
+
# delete jid_history
|
|
502
|
+
conn.del jid_history_key
|
|
503
|
+
|
|
471
504
|
#delete main job
|
|
472
505
|
conn.del redis_key
|
|
473
506
|
end
|
|
@@ -554,7 +587,7 @@ module Sidekiq
|
|
|
554
587
|
def parse_enqueue_time(timestamp)
|
|
555
588
|
DateTime.strptime(timestamp, LAST_ENQUEUE_TIME_FORMAT).to_time.utc
|
|
556
589
|
rescue ArgumentError
|
|
557
|
-
DateTime.
|
|
590
|
+
DateTime.parse(timestamp).to_time.utc
|
|
558
591
|
end
|
|
559
592
|
|
|
560
593
|
def not_past_scheduled_time?(current_time)
|
|
@@ -586,12 +619,20 @@ module Sidekiq
|
|
|
586
619
|
"cron_job:#{name}:enqueued"
|
|
587
620
|
end
|
|
588
621
|
|
|
622
|
+
def self.jid_history_key name
|
|
623
|
+
"cron_job:#{name}:jid_history"
|
|
624
|
+
end
|
|
625
|
+
|
|
589
626
|
# Redis key for storing one cron job run times
|
|
590
627
|
# (when poller added job to queue)
|
|
591
628
|
def job_enqueued_key
|
|
592
629
|
self.class.job_enqueued_key @name
|
|
593
630
|
end
|
|
594
631
|
|
|
632
|
+
def jid_history_key
|
|
633
|
+
self.class.jid_history_key @name
|
|
634
|
+
end
|
|
635
|
+
|
|
595
636
|
# Give Hash
|
|
596
637
|
# returns array for using it for redis.hmset
|
|
597
638
|
def hash_to_redis hash
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
# require Sidekiq original launcher
|
|
2
|
-
require 'sidekiq/launcher'
|
|
3
|
-
|
|
4
1
|
# require cron poller
|
|
5
2
|
require 'sidekiq/cron/poller'
|
|
6
3
|
|
|
@@ -10,44 +7,41 @@ require 'sidekiq/cron/poller'
|
|
|
10
7
|
# we are creating new cron poller instance and
|
|
11
8
|
# adding start and stop commands to launcher
|
|
12
9
|
module Sidekiq
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
old_quiet
|
|
10
|
+
module Cron
|
|
11
|
+
module Launcher
|
|
12
|
+
# Add cron poller to launcher
|
|
13
|
+
attr_reader :cron_poller
|
|
14
|
+
|
|
15
|
+
# add cron poller and execute normal initialize of Sidekiq launcher
|
|
16
|
+
def initialize(options)
|
|
17
|
+
@cron_poller = Sidekiq::Cron::Poller.new
|
|
18
|
+
super(options)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# execute normal run of launcher and run cron poller
|
|
22
|
+
def run
|
|
23
|
+
super
|
|
24
|
+
cron_poller.start
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# execute normal quiet of launcher and quiet cron poller
|
|
28
|
+
def quiet
|
|
29
|
+
cron_poller.terminate
|
|
30
|
+
super
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# execute normal stop of launcher and stop cron poller
|
|
34
|
+
def stop
|
|
35
|
+
cron_poller.terminate
|
|
36
|
+
super
|
|
37
|
+
end
|
|
42
38
|
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
Sidekiq.configure_server do
|
|
43
|
+
# require Sidekiq original launcher
|
|
44
|
+
require 'sidekiq/launcher'
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
def stop
|
|
49
|
-
cron_poller.terminate
|
|
50
|
-
old_stop
|
|
51
|
-
end
|
|
52
|
-
end
|
|
46
|
+
::Sidekiq::Launcher.prepend(Sidekiq::Cron::Launcher)
|
|
53
47
|
end
|
|
@@ -13,6 +13,8 @@ en:
|
|
|
13
13
|
NoCronJobsWereFound: No cron jobs were found
|
|
14
14
|
Enable: Enable
|
|
15
15
|
Disable: Disable
|
|
16
|
-
'Last
|
|
16
|
+
'Last enqueued': Last enqueued
|
|
17
17
|
disabled: disabled
|
|
18
18
|
enabled: enabled
|
|
19
|
+
NoHistoryWereFound: No history were found
|
|
20
|
+
Description: Description
|
data/lib/sidekiq/cron/poller.rb
CHANGED
|
@@ -17,8 +17,8 @@ module Sidekiq
|
|
|
17
17
|
rescue => ex
|
|
18
18
|
# Most likely a problem with redis networking.
|
|
19
19
|
# Punt and try again at the next interval
|
|
20
|
-
logger.error ex.message
|
|
21
|
-
logger.error ex.backtrace.first
|
|
20
|
+
Sidekiq.logger.error ex.message
|
|
21
|
+
Sidekiq.logger.error ex.backtrace.first
|
|
22
22
|
handle_exception(ex) if respond_to?(:handle_exception)
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -28,8 +28,8 @@ module Sidekiq
|
|
|
28
28
|
job.test_and_enque_for_time! time if job && job.valid?
|
|
29
29
|
rescue => ex
|
|
30
30
|
# problem somewhere in one job
|
|
31
|
-
logger.error "CRON JOB: #{ex.message}"
|
|
32
|
-
logger.error "CRON JOB: #{ex.backtrace.first}"
|
|
31
|
+
Sidekiq.logger.error "CRON JOB: #{ex.message}"
|
|
32
|
+
Sidekiq.logger.error "CRON JOB: #{ex.backtrace.first}"
|
|
33
33
|
handle_exception(ex) if respond_to?(:handle_exception)
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
<th><%= t('Status') %></th>
|
|
32
32
|
<th><%= t('Name') %></th>
|
|
33
33
|
<th><%= t('Cron string') %></th>
|
|
34
|
-
<th><%= t('Last
|
|
34
|
+
<th><%= t('Last enqueued') %></th>
|
|
35
35
|
<th width="180"><%= t('Actions')%></th>
|
|
36
36
|
</thead>
|
|
37
37
|
|
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
<tr>
|
|
42
42
|
<td style="<%= style %>"><%= t job.status %></td>
|
|
43
43
|
<td style="<%= style %>">
|
|
44
|
-
<
|
|
44
|
+
<a href="<%= root_path %>cron/<%= CGI.escape(job.name).gsub('+', '%20') %>">
|
|
45
|
+
<b><%= job.name %></b>
|
|
46
|
+
</a>
|
|
45
47
|
<hr style="margin:3px;border:0;">
|
|
46
48
|
<small>
|
|
47
49
|
<% if job.message and job.message.to_s.size > 100 %>
|
|
@@ -24,7 +24,7 @@ header.row
|
|
|
24
24
|
th = t('Status')
|
|
25
25
|
th = t('Name')
|
|
26
26
|
th = t('Cron')
|
|
27
|
-
th = t('Last
|
|
27
|
+
th = t('Last enqueued')
|
|
28
28
|
th width="180px"
|
|
29
29
|
= t('Actions')
|
|
30
30
|
|
|
@@ -34,7 +34,8 @@ header.row
|
|
|
34
34
|
tr
|
|
35
35
|
td[style="#{style}"]= job.status
|
|
36
36
|
td[style="#{style}"]
|
|
37
|
-
|
|
37
|
+
a href="#{root_path}cron/#{CGI.escape(job.name).gsub('+', '%20')}"
|
|
38
|
+
b = job.name
|
|
38
39
|
hr style="margin:3px;border:0;"
|
|
39
40
|
small
|
|
40
41
|
- if job.message and job.message.to_s.size > 100
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<header class="row">
|
|
2
|
+
<div class="span col-sm-5 pull-left">
|
|
3
|
+
<h3>
|
|
4
|
+
<%= "#{t('Cron')} #{t('Job')}" %>
|
|
5
|
+
<small><%= @job.name %></small>
|
|
6
|
+
</h3>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="span col-sm-7 pull-right" style="margin-top: 20px; margin-bottom: 10px;">
|
|
9
|
+
<% cron_job_path = "#{root_path}cron/#{CGI.escape(@job.name).gsub('+', '%20')}" %>
|
|
10
|
+
<form action="<%= cron_job_path %>/enque?redirect=<%= cron_job_path %>" class="pull-right" method="post">
|
|
11
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
|
12
|
+
<input class="btn btn-small pull-left" name="enque" type="submit" value="<%= t('EnqueueNow') %>" />
|
|
13
|
+
</form>
|
|
14
|
+
<% if @job.status == 'enabled' %>
|
|
15
|
+
<form action="<%= cron_job_path %>/disable?redirect=<%= cron_job_path %>" class="pull-right" method="post">
|
|
16
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
|
17
|
+
<input class="btn btn-small pull-left" name="disable" type="submit" value="<%= t('Disable') %>" />
|
|
18
|
+
</form>
|
|
19
|
+
<% else %>
|
|
20
|
+
<form action="<%= cron_job_path %>/enable?redirect=<%= cron_job_path %>" class="pull-right" method="post">
|
|
21
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
|
22
|
+
<input class="btn btn-small pull-left" name="enable" type="submit" value="<%= t('Enable') %>" />
|
|
23
|
+
</form>
|
|
24
|
+
<form action="<%= cron_job_path %>/delete" class="pull-right" method="post">
|
|
25
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
|
26
|
+
<input class="btn btn-danger btn-small" data-confirm="<%= t('AreYouSureDeleteCronJob', :job => @job.name) %>" name="delete" type="submit" value="<%= t('Delete') %>" />
|
|
27
|
+
</form>
|
|
28
|
+
<% end %>
|
|
29
|
+
</div>
|
|
30
|
+
</header>
|
|
31
|
+
|
|
32
|
+
<table class="table table-bordered table-striped">
|
|
33
|
+
<tbody>
|
|
34
|
+
<tr>
|
|
35
|
+
<th><%= t 'Status' %></th>
|
|
36
|
+
<td><%= @job.status %></td>
|
|
37
|
+
</tr>
|
|
38
|
+
<tr>
|
|
39
|
+
<th><%= t 'Name' %></th>
|
|
40
|
+
<td><%= @job.name %></td>
|
|
41
|
+
</tr>
|
|
42
|
+
<tr>
|
|
43
|
+
<th><%= t 'Description' %></th>
|
|
44
|
+
<td><%= @job.description %></td>
|
|
45
|
+
</tr>
|
|
46
|
+
<tr>
|
|
47
|
+
<th><%= t 'Message' %></th>
|
|
48
|
+
<td><pre><%= @job.pretty_message %></pre></td>
|
|
49
|
+
</tr>
|
|
50
|
+
<tr>
|
|
51
|
+
<th><%= t 'Cron' %></th>
|
|
52
|
+
<td><%= @job.cron.gsub(" ", " ") %></td>
|
|
53
|
+
</tr>
|
|
54
|
+
<tr>
|
|
55
|
+
<th><%= t 'Last enqueued' %></th>
|
|
56
|
+
<td><%= @job.last_enqueue_time ? relative_time(@job.last_enqueue_time) : "-" %></td>
|
|
57
|
+
</tr>
|
|
58
|
+
</tbody>
|
|
59
|
+
</table>
|
|
60
|
+
|
|
61
|
+
<header class="row">
|
|
62
|
+
<div class="col-sm-12">
|
|
63
|
+
<h4>
|
|
64
|
+
<%= t 'History' %>
|
|
65
|
+
</h4>
|
|
66
|
+
</div>
|
|
67
|
+
</header>
|
|
68
|
+
|
|
69
|
+
<% if @job.jid_history_from_redis.size > 0 %>
|
|
70
|
+
<table class="table table-hover table-bordered table-striped">
|
|
71
|
+
<thead>
|
|
72
|
+
<tr>
|
|
73
|
+
<th><%= t 'Enqueued' %></th>
|
|
74
|
+
<th><%= t 'JID' %></th>
|
|
75
|
+
</tr>
|
|
76
|
+
</thead>
|
|
77
|
+
<tbody>
|
|
78
|
+
<% @job.jid_history_from_redis.each do |jid_history| %>
|
|
79
|
+
<tr>
|
|
80
|
+
<td><%= jid_history['enqueued'] %></td>
|
|
81
|
+
<td><%= jid_history['jid'] %></td>
|
|
82
|
+
</tr>
|
|
83
|
+
<% end %>
|
|
84
|
+
</tbody>
|
|
85
|
+
</table>
|
|
86
|
+
<% else %>
|
|
87
|
+
<div class='alert alert-success'><%= t 'NoHistoryWereFound' %></div>
|
|
88
|
+
<% end %>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
header.row
|
|
2
|
+
.span.col-sm-5.pull-left
|
|
3
|
+
h3
|
|
4
|
+
= "#{t('Cron')} #{t('Job')}"
|
|
5
|
+
small= @job.name
|
|
6
|
+
.span.col-sm-7.pull-right style=("margin-top: 20px; margin-bottom: 10px;")
|
|
7
|
+
- cron_job_path = "#{root_path}cron/#{CGI.escape(@job.name).gsub('+', '%20')}"
|
|
8
|
+
form.pull-right action="#{cron_job_path}/enque?redirect=#{cron_job_path}" method="post"
|
|
9
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
|
10
|
+
input.btn.btn-small.pull-left name="enque" type="submit" value="#{t('EnqueueNow')}"
|
|
11
|
+
- if @job.status == 'enabled'
|
|
12
|
+
form.pull-right action="#{cron_job_path}/disable?redirect=#{cron_job_path}" method="post"
|
|
13
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
|
14
|
+
input.btn.btn-small.pull-left name="disable" type="submit" value="#{t('Disable')}"
|
|
15
|
+
- else
|
|
16
|
+
form.pull-right action="#{cron_job_path}/enable?redirect=#{cron_job_path}" method="post"
|
|
17
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
|
18
|
+
input.btn.btn-small.pull-left name="enable" type="submit" value="#{t('Enable')}"
|
|
19
|
+
form.pull-right action="#{cron_job_path}/delete" method="post"
|
|
20
|
+
= csrf_tag if respond_to?(:csrf_tag)
|
|
21
|
+
input.btn.btn-danger.btn-small data-confirm="#{t('AreYouSureDeleteCronJob' job =@job.name)}" name="delete" type="submit" value="#{t('Delete')}" /
|
|
22
|
+
|
|
23
|
+
table.table.table-bordered.table-striped
|
|
24
|
+
tbody
|
|
25
|
+
tr
|
|
26
|
+
th= t 'Status'
|
|
27
|
+
td= @job.status
|
|
28
|
+
tr
|
|
29
|
+
th= t 'Name'
|
|
30
|
+
td= @job.name
|
|
31
|
+
tr
|
|
32
|
+
th= t 'Description'
|
|
33
|
+
td= @job.description
|
|
34
|
+
tr
|
|
35
|
+
th= t 'Message'
|
|
36
|
+
td
|
|
37
|
+
pre= @job.pretty_message
|
|
38
|
+
tr
|
|
39
|
+
th= t 'Cron'
|
|
40
|
+
td= @job.cron.gsub(" ", " ")
|
|
41
|
+
tr
|
|
42
|
+
th= t 'Last enqueued'
|
|
43
|
+
td= @job.last_enqueue_time ? relative_time(@job.last_enqueue_time) : "-"
|
|
44
|
+
|
|
45
|
+
header.row
|
|
46
|
+
.col-sm-12
|
|
47
|
+
h4= t 'History'
|
|
48
|
+
|
|
49
|
+
- if @job.jid_history_from_redis.size > 0
|
|
50
|
+
table.table.table-hover.table-bordered.table-striped
|
|
51
|
+
thead
|
|
52
|
+
tr
|
|
53
|
+
th= t 'Enqueued'
|
|
54
|
+
th= t 'JID'
|
|
55
|
+
tbody
|
|
56
|
+
- @job.jid_history_from_redis.each do |jid_history|
|
|
57
|
+
tr
|
|
58
|
+
td= jid_history['enqueued']
|
|
59
|
+
td= jid_history['jid']
|
|
60
|
+
- else
|
|
61
|
+
.alert.alert-success= t 'NoHistoryWereFound'
|
|
@@ -20,6 +20,23 @@ module Sidekiq
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
# display job detail + jid history
|
|
24
|
+
app.get '/cron/:name' do
|
|
25
|
+
view_path = File.join(File.expand_path("..", __FILE__), "views")
|
|
26
|
+
|
|
27
|
+
@job = Sidekiq::Cron::Job.find(route_params[:name])
|
|
28
|
+
if @job
|
|
29
|
+
#if Slim renderer exists and sidekiq has layout.slim in views
|
|
30
|
+
if defined?(Slim) && File.exists?(File.join(settings.views,"layout.slim"))
|
|
31
|
+
render(:slim, File.read(File.join(view_path, "cron_show.slim")))
|
|
32
|
+
else
|
|
33
|
+
render(:erb, File.read(File.join(view_path, "cron_show.erb")))
|
|
34
|
+
end
|
|
35
|
+
else
|
|
36
|
+
redirect "#{root_path}cron"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
23
40
|
#enque cron job
|
|
24
41
|
app.post '/cron/:name/enque' do
|
|
25
42
|
if route_params[:name] === '__all__'
|
|
@@ -27,7 +44,7 @@ module Sidekiq
|
|
|
27
44
|
elsif job = Sidekiq::Cron::Job.find(route_params[:name])
|
|
28
45
|
job.enque!
|
|
29
46
|
end
|
|
30
|
-
redirect "#{root_path}cron"
|
|
47
|
+
redirect params['redirect'] || "#{root_path}cron"
|
|
31
48
|
end
|
|
32
49
|
|
|
33
50
|
#delete schedule
|
|
@@ -47,7 +64,7 @@ module Sidekiq
|
|
|
47
64
|
elsif job = Sidekiq::Cron::Job.find(route_params[:name])
|
|
48
65
|
job.enable!
|
|
49
66
|
end
|
|
50
|
-
redirect "#{root_path}cron"
|
|
67
|
+
redirect params['redirect'] || "#{root_path}cron"
|
|
51
68
|
end
|
|
52
69
|
|
|
53
70
|
#disable job
|
|
@@ -57,7 +74,7 @@ module Sidekiq
|
|
|
57
74
|
elsif job = Sidekiq::Cron::Job.find(route_params[:name])
|
|
58
75
|
job.disable!
|
|
59
76
|
end
|
|
60
|
-
redirect "#{root_path}cron"
|
|
77
|
+
redirect params['redirect'] || "#{root_path}cron"
|
|
61
78
|
end
|
|
62
79
|
|
|
63
80
|
end
|
data/sidekiq-cron.gemspec
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: sidekiq-cron 1.0
|
|
5
|
+
# stub: sidekiq-cron 1.2.0 ruby lib
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "sidekiq-cron".freeze
|
|
9
|
-
s.version = "1.0
|
|
9
|
+
s.version = "1.2.0"
|
|
10
10
|
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
12
12
|
s.require_paths = ["lib".freeze]
|
|
13
13
|
s.authors = ["Ondrej Bartas".freeze]
|
|
14
|
-
s.date = "
|
|
14
|
+
s.date = "2020-04-03"
|
|
15
15
|
s.description = "Enables to set jobs to be run in specified time (using CRON notation)".freeze
|
|
16
16
|
s.email = "ondrej@bartas.cz".freeze
|
|
17
17
|
s.extra_rdoc_files = [
|
|
@@ -44,6 +44,8 @@ Gem::Specification.new do |s|
|
|
|
44
44
|
"lib/sidekiq/cron/support.rb",
|
|
45
45
|
"lib/sidekiq/cron/views/cron.erb",
|
|
46
46
|
"lib/sidekiq/cron/views/cron.slim",
|
|
47
|
+
"lib/sidekiq/cron/views/cron_show.erb",
|
|
48
|
+
"lib/sidekiq/cron/views/cron_show.slim",
|
|
47
49
|
"lib/sidekiq/cron/web.rb",
|
|
48
50
|
"lib/sidekiq/cron/web_extension.rb",
|
|
49
51
|
"sidekiq-cron.gemspec",
|
|
@@ -55,7 +57,7 @@ Gem::Specification.new do |s|
|
|
|
55
57
|
]
|
|
56
58
|
s.homepage = "http://github.com/ondrejbartas/sidekiq-cron".freeze
|
|
57
59
|
s.licenses = ["MIT".freeze]
|
|
58
|
-
s.rubygems_version = "2.5.2.
|
|
60
|
+
s.rubygems_version = "2.5.2.3".freeze
|
|
59
61
|
s.summary = "Sidekiq Cron helps to add repeated scheduled jobs".freeze
|
|
60
62
|
|
|
61
63
|
if s.respond_to? :specification_version then
|
|
@@ -6,9 +6,7 @@ describe 'Performance Poller' do
|
|
|
6
6
|
X = 10000
|
|
7
7
|
before do
|
|
8
8
|
Sidekiq.redis = REDIS
|
|
9
|
-
|
|
10
|
-
conn.flushdb
|
|
11
|
-
end
|
|
9
|
+
Redis.current.flushdb
|
|
12
10
|
|
|
13
11
|
#clear all previous saved data from redis
|
|
14
12
|
Sidekiq.redis do |conn|
|
|
@@ -33,7 +31,7 @@ describe 'Performance Poller' do
|
|
|
33
31
|
Time.stubs(:now).returns(enqueued_time)
|
|
34
32
|
end
|
|
35
33
|
|
|
36
|
-
it 'should enqueue 10000 jobs in less than
|
|
34
|
+
it 'should enqueue 10000 jobs in less than 40s' do
|
|
37
35
|
Sidekiq.redis do |conn|
|
|
38
36
|
assert_equal 0, conn.llen("queue:default"), 'Queue should be empty'
|
|
39
37
|
end
|
|
@@ -47,6 +45,6 @@ describe 'Performance Poller' do
|
|
|
47
45
|
end
|
|
48
46
|
|
|
49
47
|
puts "Performance test finished in #{bench.real}"
|
|
50
|
-
assert_operator bench.real, :<,
|
|
48
|
+
assert_operator bench.real, :<, 40
|
|
51
49
|
end
|
|
52
50
|
end
|
data/test/test_helper.rb
CHANGED
|
@@ -20,7 +20,7 @@ Coveralls.wear!
|
|
|
20
20
|
require "minitest/autorun"
|
|
21
21
|
require 'shoulda-context'
|
|
22
22
|
require "rack/test"
|
|
23
|
-
require
|
|
23
|
+
require 'mocha/minitest'
|
|
24
24
|
|
|
25
25
|
ENV['RACK_ENV'] = 'test'
|
|
26
26
|
|
|
@@ -66,6 +66,13 @@ end
|
|
|
66
66
|
|
|
67
67
|
module ActiveJob
|
|
68
68
|
class Base
|
|
69
|
+
attr_accessor *%i[job_class provider_job_id queue_name arguments]
|
|
70
|
+
|
|
71
|
+
def initialize
|
|
72
|
+
yield self if block_given?
|
|
73
|
+
self.provider_job_id ||= SecureRandom.hex(12)
|
|
74
|
+
end
|
|
75
|
+
|
|
69
76
|
def self.queue_name_prefix
|
|
70
77
|
@queue_name_prefix
|
|
71
78
|
end
|
|
@@ -80,12 +87,16 @@ module ActiveJob
|
|
|
80
87
|
self
|
|
81
88
|
end
|
|
82
89
|
|
|
90
|
+
def try(method, *args, &block)
|
|
91
|
+
send method, *args, &block if respond_to? method
|
|
92
|
+
end
|
|
93
|
+
|
|
83
94
|
def self.perform_later(*args)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
95
|
+
new do |instance|
|
|
96
|
+
instance.job_class = self.class.name
|
|
97
|
+
instance.queue_name = @queue
|
|
98
|
+
instance.arguments = [*args]
|
|
99
|
+
end
|
|
89
100
|
end
|
|
90
101
|
end
|
|
91
102
|
end
|
data/test/unit/job_test.rb
CHANGED
|
@@ -223,6 +223,34 @@ describe "Cron Job" do
|
|
|
223
223
|
"class"=>"CronTestClassWithQueue",
|
|
224
224
|
"args"=>[]}
|
|
225
225
|
end
|
|
226
|
+
|
|
227
|
+
it "be initialized with 'class' and date_as_argument" do
|
|
228
|
+
job = Sidekiq::Cron::Job.new('class' => 'CronTestClassWithQueue', "date_as_argument" => true)
|
|
229
|
+
|
|
230
|
+
job_message = job.message
|
|
231
|
+
job_args = job_message.delete("args")
|
|
232
|
+
assert_equal job_message, {"retry"=>false,
|
|
233
|
+
"queue"=>:super,
|
|
234
|
+
"backtrace"=>true,
|
|
235
|
+
"class"=>"CronTestClassWithQueue"}
|
|
236
|
+
assert job_args[-1].is_a?(Float)
|
|
237
|
+
assert job_args[-1].between?(Time.now.to_f - 1, Time.now.to_f)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it "be initialized with 'class', 2 arguments and date_as_argument" do
|
|
241
|
+
job = Sidekiq::Cron::Job.new('class' => 'CronTestClassWithQueue', "date_as_argument" => true, "args"=> ["arg1", :arg2])
|
|
242
|
+
|
|
243
|
+
job_message = job.message
|
|
244
|
+
job_args = job_message.delete("args")
|
|
245
|
+
assert_equal job_message, {"retry"=>false,
|
|
246
|
+
"queue"=>:super,
|
|
247
|
+
"backtrace"=>true,
|
|
248
|
+
"class"=>"CronTestClassWithQueue"}
|
|
249
|
+
assert job_args[-1].is_a?(Float)
|
|
250
|
+
assert job_args[-1].between?(Time.now.to_f - 1, Time.now.to_f)
|
|
251
|
+
assert_equal job_args[0..-2], ["arg1", :arg2]
|
|
252
|
+
end
|
|
253
|
+
|
|
226
254
|
end
|
|
227
255
|
|
|
228
256
|
describe "cron test" do
|
|
@@ -381,7 +409,7 @@ describe "Cron Job" do
|
|
|
381
409
|
|
|
382
410
|
it 'pushes to queue active jobs message' do
|
|
383
411
|
@job.expects(:enqueue_active_job)
|
|
384
|
-
.returns(
|
|
412
|
+
.returns(ActiveJobCronTestClass.new)
|
|
385
413
|
@job.enque!
|
|
386
414
|
end
|
|
387
415
|
end
|
|
@@ -399,7 +427,7 @@ describe "Cron Job" do
|
|
|
399
427
|
|
|
400
428
|
it 'pushes to queue active jobs message with queue_name_prefix' do
|
|
401
429
|
@job.expects(:enqueue_active_job)
|
|
402
|
-
.returns(
|
|
430
|
+
.returns(ActiveJobCronTestClass.new)
|
|
403
431
|
@job.enque!
|
|
404
432
|
end
|
|
405
433
|
end
|
|
@@ -907,7 +935,8 @@ describe "Cron Job" do
|
|
|
907
935
|
@jobs_hash['name_of_job']['cron'] = "bad cron"
|
|
908
936
|
out = Sidekiq::Cron::Job.load_from_hash @jobs_hash
|
|
909
937
|
assert_equal 1, out.size, "should have 1 error"
|
|
910
|
-
|
|
938
|
+
assert_includes out['name_of_job'].first, "bad cron"
|
|
939
|
+
assert_includes out['name_of_job'].first, "ArgumentError:"
|
|
911
940
|
assert_equal 1, Sidekiq::Cron::Job.all.size, "Should have only 1 job after load"
|
|
912
941
|
end
|
|
913
942
|
|
data/test/unit/poller_test.rb
CHANGED
|
@@ -9,7 +9,7 @@ describe 'Cron web' do
|
|
|
9
9
|
|
|
10
10
|
before do
|
|
11
11
|
Sidekiq.redis = REDIS
|
|
12
|
-
|
|
12
|
+
Redis.current.flushdb
|
|
13
13
|
|
|
14
14
|
#clear all previous saved data from redis
|
|
15
15
|
Sidekiq.redis do |conn|
|
|
@@ -66,6 +66,25 @@ describe 'Cron web' do
|
|
|
66
66
|
@cron_job_name = "TesQueueNameOfCronJob"
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
+
it 'shows history of a cron job' do
|
|
70
|
+
@job.enque!
|
|
71
|
+
get "/cron/#{@name}"
|
|
72
|
+
|
|
73
|
+
jid =
|
|
74
|
+
Sidekiq.redis do |conn|
|
|
75
|
+
history = conn.lrange Sidekiq::Cron::Job.jid_history_key(@name), 0, -1
|
|
76
|
+
Sidekiq.load_json(history.last)['jid']
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
assert last_response.body.include?(jid)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'redirects to cron path when name not found' do
|
|
83
|
+
get '/cron/some-fake-name'
|
|
84
|
+
|
|
85
|
+
assert_match %r{\/cron\z}, last_response['Location']
|
|
86
|
+
end
|
|
87
|
+
|
|
69
88
|
it "disable and enable all cron jobs" do
|
|
70
89
|
post "/cron/__all__/disable"
|
|
71
90
|
assert_equal Sidekiq::Cron::Job.find(@name).status, "disabled"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sidekiq-cron
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ondrej Bartas
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-04-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: sidekiq
|
|
@@ -309,6 +309,8 @@ files:
|
|
|
309
309
|
- lib/sidekiq/cron/support.rb
|
|
310
310
|
- lib/sidekiq/cron/views/cron.erb
|
|
311
311
|
- lib/sidekiq/cron/views/cron.slim
|
|
312
|
+
- lib/sidekiq/cron/views/cron_show.erb
|
|
313
|
+
- lib/sidekiq/cron/views/cron_show.slim
|
|
312
314
|
- lib/sidekiq/cron/web.rb
|
|
313
315
|
- lib/sidekiq/cron/web_extension.rb
|
|
314
316
|
- sidekiq-cron.gemspec
|
|
@@ -337,7 +339,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
337
339
|
version: '0'
|
|
338
340
|
requirements: []
|
|
339
341
|
rubyforge_project:
|
|
340
|
-
rubygems_version: 2.5.2.
|
|
342
|
+
rubygems_version: 2.5.2.3
|
|
341
343
|
signing_key:
|
|
342
344
|
specification_version: 4
|
|
343
345
|
summary: Sidekiq Cron helps to add repeated scheduled jobs
|