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
@@ -0,0 +1,33 @@
1
+ require './test/test_helper'
2
+
3
+ describe 'Cron launcher' do
4
+ describe 'initialization' do
5
+ before do
6
+ Sidekiq::Options[:cron_poll_interval] = nil
7
+ end
8
+
9
+ it 'initializes poller with default poll interval when not configured' do
10
+ Sidekiq::Cron::Poller.expects(:new).with do |options|
11
+ assert_equal Sidekiq::Cron::Launcher::DEFAULT_POLL_INTERVAL, options[:cron_poll_interval]
12
+ end
13
+
14
+ Sidekiq::Launcher.new(Sidekiq.respond_to?(:default_configuration) ? Sidekiq.default_configuration : Sidekiq)
15
+ end
16
+
17
+ it 'initializes poller with the configured poll interval' do
18
+ Sidekiq::Cron::Poller.expects(:new).with do |options|
19
+ assert_equal 99, options[:cron_poll_interval]
20
+ end
21
+
22
+ Sidekiq::Options[:cron_poll_interval] = 99
23
+ Sidekiq::Launcher.new(Sidekiq.respond_to?(:default_configuration) ? Sidekiq.default_configuration : Sidekiq)
24
+ end
25
+
26
+ it 'does not initialize the poller when interval is 0' do
27
+ Sidekiq::Cron::Poller.expects(:new).never
28
+
29
+ Sidekiq::Options[:cron_poll_interval] = 0
30
+ Sidekiq::Launcher.new(Sidekiq.respond_to?(:default_configuration) ? Sidekiq.default_configuration : Sidekiq)
31
+ end
32
+ end
33
+ end
@@ -1,22 +1,12 @@
1
- # -*- encoding : utf-8 -*-
2
1
  require './test/test_helper'
3
2
 
4
-
5
3
  describe 'Cron Poller' do
6
4
  before do
7
- Sidekiq.redis = REDIS
5
+ # Clear all previous saved data from Redis.
8
6
  Sidekiq.redis do |conn|
9
7
  conn.flushdb
10
8
  end
11
9
 
12
- #clear all previous saved data from redis
13
- Sidekiq.redis do |conn|
14
- conn.keys("cron_job*").each do |key|
15
- conn.del(key)
16
- end
17
- end
18
-
19
-
20
10
  @args = {
21
11
  name: "Test",
22
12
  cron: "*/2 * * * *",
@@ -24,14 +14,14 @@ describe 'Cron Poller' do
24
14
  }
25
15
  @args2 = @args.merge(name: 'with_queue', klass: 'CronTestClassWithQueue', cron: "*/10 * * * *")
26
16
 
27
- @poller = Sidekiq::Cron::Poller.new
17
+ @poller = Sidekiq::Cron::Poller.new(Sidekiq.const_defined?(:Config) ? Sidekiq::Config.new : {})
28
18
  end
29
19
 
30
20
  it 'not enqueue any job - new jobs' do
31
- now = Time.now.utc
32
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 5, 1)
21
+ now = Time.now.utc + 3600
22
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 5, 1)
33
23
  Time.stubs(:now).returns(enqueued_time)
34
- #new jobs!
24
+
35
25
  Sidekiq::Cron::Job.create(@args)
36
26
  Sidekiq::Cron::Job.create(@args2)
37
27
 
@@ -42,22 +32,23 @@ describe 'Cron Poller' do
42
32
  assert_equal 0, conn.llen("queue:super")
43
33
  end
44
34
 
45
- #30 seconds after!
46
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 5, 30)
35
+ # 30 seconds after!
36
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 5, 30)
47
37
  Time.stubs(:now).returns(enqueued_time)
48
- @poller.enqueue
49
38
 
50
- Sidekiq.redis do |conn|
51
- assert_equal 0, conn.llen("queue:default")
52
- assert_equal 0, conn.llen("queue:super")
53
- end
39
+ @poller.enqueue
40
+
41
+ Sidekiq.redis do |conn|
42
+ assert_equal 0, conn.llen("queue:default")
43
+ assert_equal 0, conn.llen("queue:super")
44
+ end
54
45
  end
55
46
 
56
47
  it 'should enqueue only job with cron */2' do
57
- now = Time.now.utc
58
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 5, 1)
48
+ now = Time.now.utc + 3600
49
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 5, 1)
59
50
  Time.stubs(:now).returns(enqueued_time)
60
- #new jobs!
51
+
61
52
  Sidekiq::Cron::Job.create(@args)
62
53
  Sidekiq::Cron::Job.create(@args2)
63
54
 
@@ -68,7 +59,7 @@ describe 'Cron Poller' do
68
59
  assert_equal 0, conn.llen("queue:super")
69
60
  end
70
61
 
71
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 6, 1)
62
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 6, 1)
72
63
  Time.stubs(:now).returns(enqueued_time)
73
64
  @poller.enqueue
74
65
 
@@ -79,10 +70,10 @@ describe 'Cron Poller' do
79
70
  end
80
71
 
81
72
  it 'should enqueue both jobs' do
82
- now = Time.now.utc
83
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 8, 1)
73
+ now = Time.now.utc + 3600
74
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 8, 1)
84
75
  Time.stubs(:now).returns(enqueued_time)
85
- #new jobs!
76
+
86
77
  Sidekiq::Cron::Job.create(@args)
87
78
  Sidekiq::Cron::Job.create(@args2)
88
79
 
@@ -93,7 +84,7 @@ describe 'Cron Poller' do
93
84
  assert_equal 0, conn.llen("queue:super")
94
85
  end
95
86
 
96
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 10, 5)
87
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 10, 5)
97
88
  Time.stubs(:now).returns(enqueued_time)
98
89
  @poller.enqueue
99
90
 
@@ -104,10 +95,10 @@ describe 'Cron Poller' do
104
95
  end
105
96
 
106
97
  it 'should enqueue both jobs but only one time each' do
107
- now = Time.now.utc
108
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 8, 1)
98
+ now = Time.now.utc + 3600
99
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 8, 1)
109
100
  Time.stubs(:now).returns(enqueued_time)
110
- #new jobs!
101
+
111
102
  Sidekiq::Cron::Job.create(@args)
112
103
  Sidekiq::Cron::Job.create(@args2)
113
104
 
@@ -118,7 +109,7 @@ describe 'Cron Poller' do
118
109
  assert_equal 0, conn.llen("queue:super")
119
110
  end
120
111
 
121
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 20, 1)
112
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 20, 1)
122
113
  Time.stubs(:now).returns(enqueued_time)
123
114
  @poller.enqueue
124
115
  Sidekiq.redis do |conn|
@@ -126,7 +117,7 @@ describe 'Cron Poller' do
126
117
  assert_equal 1, conn.llen("queue:super")
127
118
  end
128
119
 
129
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 20, 2)
120
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 20, 2)
130
121
  Time.stubs(:now).returns(enqueued_time)
131
122
  @poller.enqueue
132
123
  Sidekiq.redis do |conn|
@@ -134,7 +125,7 @@ describe 'Cron Poller' do
134
125
  assert_equal 1, conn.llen("queue:super")
135
126
  end
136
127
 
137
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 20, 20)
128
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 20, 20)
138
129
  Time.stubs(:now).returns(enqueued_time)
139
130
  @poller.enqueue
140
131
  Sidekiq.redis do |conn|
@@ -142,7 +133,7 @@ describe 'Cron Poller' do
142
133
  assert_equal 1, conn.llen("queue:super")
143
134
  end
144
135
 
145
- enqueued_time = Time.new(now.year, now.month, now.day, now.hour + 1, 20, 50)
136
+ enqueued_time = Time.new(now.year, now.month, now.day, now.hour, 20, 50)
146
137
  Time.stubs(:now).returns(enqueued_time)
147
138
  @poller.enqueue
148
139
  Sidekiq.redis do |conn|
@@ -0,0 +1,58 @@
1
+ require './test/test_helper'
2
+
3
+ describe 'ScheduleLoader' do
4
+ before do
5
+ Sidekiq::Options[:lifecycle_events][:startup].clear
6
+ end
7
+
8
+ describe 'Schedule is defined in hash' do
9
+ before do
10
+ Sidekiq::Options[:cron_schedule_file] = 'test/unit/fixtures/schedule_hash.yml'
11
+ load 'sidekiq/cron/schedule_loader.rb'
12
+ end
13
+
14
+ it 'calls Sidekiq::Cron::Job.load_from_hash' do
15
+ Sidekiq::Cron::Job.expects(:load_from_hash!)
16
+ Sidekiq::Options[:lifecycle_events][:startup].first.call
17
+ end
18
+ end
19
+
20
+ describe 'Schedule is defined in array' do
21
+ before do
22
+ Sidekiq::Options[:cron_schedule_file] = 'test/unit/fixtures/schedule_array.yml'
23
+ load 'sidekiq/cron/schedule_loader.rb'
24
+ end
25
+
26
+ it 'calls Sidekiq::Cron::Job.load_from_array' do
27
+ Sidekiq::Cron::Job.expects(:load_from_array!)
28
+ Sidekiq::Options[:lifecycle_events][:startup].first.call
29
+ end
30
+ end
31
+
32
+ describe 'Schedule is not defined in hash nor array' do
33
+ before do
34
+ Sidekiq::Options[:cron_schedule_file] = 'test/unit/fixtures/schedule_string.yml'
35
+ load 'sidekiq/cron/schedule_loader.rb'
36
+ end
37
+
38
+ it 'raises an error' do
39
+ e = assert_raises StandardError do
40
+ Sidekiq::Options[:lifecycle_events][:startup].first.call
41
+ end
42
+ assert_equal 'Not supported schedule format. Confirm your test/unit/fixtures/schedule_string.yml', e.message
43
+ end
44
+ end
45
+
46
+ describe 'Schedule is defined using ERB' do
47
+ it 'properly parses the schedule file' do
48
+ Sidekiq::Options[:cron_schedule_file] = 'test/unit/fixtures/schedule_erb.yml'
49
+ load 'sidekiq/cron/schedule_loader.rb'
50
+
51
+ Sidekiq::Options[:lifecycle_events][:startup].first.call
52
+
53
+ job = Sidekiq::Cron::Job.find("daily_job")
54
+ assert_equal job.klass, "DailyJob"
55
+ assert_equal job.cron, "every day at 5 pm"
56
+ end
57
+ end
58
+ end
@@ -1,37 +1,38 @@
1
1
  require './test/test_helper'
2
2
 
3
- def app
4
- Sidekiq::Web
5
- end
6
-
7
3
  describe 'Cron web' do
8
4
  include Rack::Test::Methods
9
5
 
6
+ TOKEN = SecureRandom.base64(32).freeze
7
+
8
+ def app
9
+ Sidekiq::Web
10
+ end
11
+
10
12
  before do
11
- Sidekiq.redis = REDIS
12
- Sidekiq.redis {|c| c.flushdb }
13
+ env 'rack.session', { csrf: TOKEN }
14
+ env 'HTTP_X_CSRF_TOKEN', TOKEN
15
+ Sidekiq.redis { |c| c.flushdb }
16
+ end
13
17
 
14
- #clear all previous saved data from redis
15
- Sidekiq.redis do |conn|
16
- conn.keys("cron_job*").each do |key|
17
- conn.del(key)
18
- end
19
- end
18
+ let(:job_name) { "TestNameOfCronJob" }
19
+ let(:cron_job_name) { "TesQueueNameOfCronJob" }
20
20
 
21
- @args = {
22
- name: "TestNameOfCronJob",
21
+ let(:args) do
22
+ {
23
+ name: job_name,
23
24
  cron: "*/2 * * * *",
24
25
  klass: "CronTestClass"
25
26
  }
27
+ end
26
28
 
27
-
28
- @cron_args = {
29
- name: "TesQueueNameOfCronJob",
29
+ let(:cron_args) do
30
+ {
31
+ name: cron_job_name,
30
32
  cron: "*/2 * * * *",
31
33
  klass: "CronQueueTestClass",
32
34
  queue: "cron"
33
35
  }
34
-
35
36
  end
36
37
 
37
38
  it 'display cron web' do
@@ -41,45 +42,62 @@ describe 'Cron web' do
41
42
 
42
43
  it 'display cron web with message - no cron jobs' do
43
44
  get '/cron'
44
- assert last_response.body.include?('No cron jobs found')
45
+ assert last_response.body.include?('No cron jobs were found')
45
46
  end
46
47
 
47
48
  it 'display cron web with cron jobs table' do
48
- Sidekiq::Cron::Job.create(@args)
49
+ Sidekiq::Cron::Job.create(args)
49
50
 
50
51
  get '/cron'
51
52
  assert_equal 200, last_response.status
52
- refute last_response.body.include?('No cron jobs found')
53
+ refute last_response.body.include?('No cron jobs were found')
53
54
  assert last_response.body.include?('table')
54
55
  assert last_response.body.include?("TestNameOfCronJob")
55
56
  end
56
57
 
57
58
  describe "work with cron job" do
58
-
59
59
  before do
60
- @job = Sidekiq::Cron::Job.new(@args.merge(status: "enabled"))
61
- @job.save
62
- @name = "TestNameOfCronJob"
60
+ @job = Sidekiq::Cron::Job.new(args.merge(status: "enabled"))
61
+ assert @job.save
62
+
63
+ @cron_job = Sidekiq::Cron::Job.new(cron_args.merge(status: "enabled"))
64
+ assert @cron_job.save
65
+ end
66
+
67
+ it 'shows history of a cron job' do
68
+ @job.enque!
69
+ get "/cron/#{job_name}"
70
+
71
+ jid =
72
+ Sidekiq.redis do |conn|
73
+ history = conn.lrange Sidekiq::Cron::Job.jid_history_key(job_name), 0, -1
74
+ Sidekiq.load_json(history.last)['jid']
75
+ end
76
+
77
+ assert jid
78
+ assert last_response.body.include?(jid)
79
+ end
80
+
81
+ it 'redirects to cron path when name not found' do
82
+ get '/cron/some-fake-name'
63
83
 
64
- @cron_job = Sidekiq::Cron::Job.new(@cron_args.merge(status: "enabled"))
65
- @cron_job.save
66
- @cron_job_name = "TesQueueNameOfCronJob"
84
+ assert_match %r{\/cron\z}, last_response['Location']
67
85
  end
68
86
 
69
87
  it "disable and enable all cron jobs" do
70
88
  post "/cron/__all__/disable"
71
- assert_equal Sidekiq::Cron::Job.find(@name).status, "disabled"
89
+ assert_equal Sidekiq::Cron::Job.find(job_name).status, "disabled"
72
90
 
73
91
  post "/cron/__all__/enable"
74
- assert_equal Sidekiq::Cron::Job.find(@name).status, "enabled"
92
+ assert_equal Sidekiq::Cron::Job.find(job_name).status, "enabled"
75
93
  end
76
94
 
77
95
  it "disable and enable cron job" do
78
- post "/cron/#{@name}/disable"
79
- assert_equal Sidekiq::Cron::Job.find(@name).status, "disabled"
96
+ post "/cron/#{job_name}/disable"
97
+ assert_equal Sidekiq::Cron::Job.find(job_name).status, "disabled"
80
98
 
81
- post "/cron/#{@name}/enable"
82
- assert_equal Sidekiq::Cron::Job.find(@name).status, "enabled"
99
+ post "/cron/#{job_name}/enable"
100
+ assert_equal Sidekiq::Cron::Job.find(job_name).status, "enabled"
83
101
  end
84
102
 
85
103
  it "enqueue all jobs" do
@@ -100,21 +118,21 @@ describe 'Cron web' do
100
118
  assert_equal 0, conn.llen("queue:default"), "Queue should have no jobs"
101
119
  end
102
120
 
103
- post "/cron/#{@name}/enque"
121
+ post "/cron/#{job_name}/enque"
104
122
 
105
123
  Sidekiq.redis do |conn|
106
124
  assert_equal 1, conn.llen("queue:default"), "Queue should have 1 job"
107
125
  end
108
126
 
109
- #should enqueue more times
110
- post "/cron/#{@name}/enque"
127
+ # Should enqueue more times.
128
+ post "/cron/#{job_name}/enque"
111
129
 
112
130
  Sidekiq.redis do |conn|
113
131
  assert_equal 2, conn.llen("queue:default"), "Queue should have 2 job"
114
132
  end
115
133
 
116
- #should enqueue to cron job queue
117
- post "/cron/#{@cron_job_name}/enque"
134
+ # Should enqueue to cron job queue.
135
+ post "/cron/#{cron_job_name}/enque"
118
136
 
119
137
  Sidekiq.redis do |conn|
120
138
  assert_equal 1, conn.llen("queue:cron"), "Queue should have 1 cron job"
@@ -123,8 +141,8 @@ describe 'Cron web' do
123
141
 
124
142
  it "destroy job" do
125
143
  assert_equal Sidekiq::Cron::Job.all.size, 2, "Should have 2 job"
126
- post "/cron/#{@name}/delete"
127
- post "/cron/#{@cron_job_name}/delete"
144
+ post "/cron/#{job_name}/delete"
145
+ post "/cron/#{cron_job_name}/delete"
128
146
  assert_equal Sidekiq::Cron::Job.all.size, 0, "Should have zero jobs"
129
147
  end
130
148