marty 9.5.1 → 10.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/README.md +40 -31
  4. data/app/components/marty/background_job/schedule_jobs_dashboard.rb +2 -2
  5. data/app/components/marty/background_job/schedule_jobs_grid.rb +22 -5
  6. data/app/components/marty/background_job/schedule_jobs_logs.rb +12 -0
  7. data/app/components/marty/base_rule_view.rb +0 -4
  8. data/app/components/marty/delorean_rule_view.rb +11 -5
  9. data/app/components/marty/promise_view.rb +15 -0
  10. data/app/jobs/marty/cron_job.rb +30 -28
  11. data/app/jobs/marty/delorean_background_job.rb +8 -0
  12. data/app/models/marty/background_job/schedule.rb +24 -1
  13. data/app/models/marty/delorean_rule.rb +1 -1
  14. data/app/models/marty/vw_promise.rb +6 -4
  15. data/app/services/marty/background_job/fetch_missing_in_schedule_cron_jobs.rb +8 -6
  16. data/app/services/marty/background_job/update_schedule.rb +15 -8
  17. data/app/services/marty/jobs/schedule.rb +8 -4
  18. data/app/services/marty/promises/delorean/create.rb +2 -1
  19. data/app/services/marty/promises/ruby/create.rb +2 -1
  20. data/config/locales/en.yml +1 -0
  21. data/db/migrate/510_schedule_job_to_remove_old_promises.rb +4 -2
  22. data/db/migrate/523_add_timeout_to_promises.rb +5 -0
  23. data/db/migrate/524_add_timeout_to_promise_view.rb +45 -0
  24. data/db/migrate/525_add_arguments_to_jobs_schedules.rb +10 -0
  25. data/db/migrate/526_add_schedule_id_to_delayed_jobs.rb +14 -0
  26. data/lib/marty/delayed_job/queue_adapter.rb +38 -0
  27. data/lib/marty/delayed_job/scheduled_job_plugin.rb +9 -6
  28. data/lib/marty/diagnostic/environment_variables.rb +1 -1
  29. data/lib/marty/monkey.rb +11 -0
  30. data/lib/marty/promise_job.rb +2 -1
  31. data/lib/marty/promise_ruby_job.rb +2 -1
  32. data/lib/marty/version.rb +1 -1
  33. data/spec/dummy/.foreman +2 -0
  34. data/spec/dummy/Procfile +2 -0
  35. data/spec/dummy/app/jobs/test_failing_job.rb +5 -1
  36. data/spec/dummy/app/models/gemini/my_rule.rb +2 -0
  37. data/spec/dummy/app/models/gemini/xyz_rule.rb +2 -0
  38. data/spec/dummy/delorean/jobs.dl +6 -0
  39. data/spec/features/delayed_jobs_grid_spec.rb +3 -2
  40. data/spec/features/schedule_jobs_dashboard_spec.rb +12 -12
  41. data/spec/jobs/cron_job_spec.rb +16 -12
  42. data/spec/jobs/delorean_background_job_spec.rb +50 -0
  43. data/spec/models/promise_spec.rb +1 -0
  44. data/spec/services/background_job/fetch_missing_in_schedule_cron_jobs_spec.rb +5 -3
  45. data/spec/services/jobs/schedule_spec.rb +5 -4
  46. metadata +12 -2
@@ -5,7 +5,11 @@ class TestFailingJob < Marty::CronJob
5
5
  end
6
6
 
7
7
  def self.trigger_destroy
8
- delayed_job.destroy!
8
+ dj = Marty::BackgroundJob::Schedule.find_by(
9
+ job_class: 'TestFailingJob'
10
+ ).delayed_job
11
+
12
+ dj.destroy!
9
13
  end
10
14
 
11
15
  def self.trigger_failure
@@ -1,6 +1,8 @@
1
1
  class Gemini::MyRule < Marty::DeloreanRule
2
2
  self.table_name = 'gemini_my_rules'
3
3
 
4
+ validates :rule_type, presence: true
5
+
4
6
  gen_mcfly_lookup :lookup, {
5
7
  name: false,
6
8
  }
@@ -1,6 +1,8 @@
1
1
  class Gemini::XyzRule < Marty::DeloreanRule
2
2
  self.table_name = 'gemini_xyz_rules'
3
3
 
4
+ validates :rule_type, presence: true
5
+
4
6
  gen_mcfly_lookup :lookup, {
5
7
  name: false,
6
8
  }
@@ -0,0 +1,6 @@
1
+ TestJob1:
2
+ perform = 1
3
+
4
+ TestJob2:
5
+ do_nothing = 2
6
+
@@ -29,11 +29,12 @@ feature 'Delayed Jobs Dashboard', js: true do
29
29
  Marty::BackgroundJob::Schedule.create(
30
30
  job_class: klass_name,
31
31
  cron: '0 0 * * *',
32
- state: 'on'
32
+ state: 'on',
33
+ arguments: []
33
34
  ).tap do |job|
34
35
  Marty::BackgroundJob::UpdateSchedule.call(
35
36
  id: job.id,
36
- job_class: job.job_class
37
+ job_class: job.job_class,
37
38
  )
38
39
  end
39
40
  end
@@ -28,17 +28,18 @@ feature 'Schedule Jobs Dashboard', js: true do
28
28
  Marty::BackgroundJob::Schedule.create(
29
29
  job_class: 'Test2Job',
30
30
  cron: '0 0 * * *',
31
- state: 'on'
31
+ state: 'on',
32
+ arguments: []
32
33
  ).tap do |job|
33
34
  Marty::BackgroundJob::UpdateSchedule.call(
34
35
  id: job.id,
35
- job_class: job.job_class
36
+ job_class: job.job_class,
36
37
  )
37
38
  end
38
39
  end
39
40
 
40
41
  before do
41
- expect(Test2Job.scheduled?).to be true
42
+ expect(Test2Job.scheduled?(schedule_id: schedule.id)).to be true
42
43
 
43
44
  log_in_as('admin1')
44
45
  wait_for_ajax
@@ -52,8 +53,6 @@ feature 'Schedule Jobs Dashboard', js: true do
52
53
  end
53
54
 
54
55
  it 'creates new schedule' do
55
- expect(TestJob.scheduled?).to be false
56
-
57
56
  press('Add')
58
57
 
59
58
  fill_in('Job class', with: 'TestJob')
@@ -69,11 +68,12 @@ feature 'Schedule Jobs Dashboard', js: true do
69
68
  expect(crons).to include('1 1 * * *')
70
69
  expect(crons).to include('0 0 * * *')
71
70
 
72
- expect(TestJob.scheduled?).to be true
73
- expect(TestJob.delayed_job.cron).to eq '1 1 * * *'
71
+ new_schedule = Marty::BackgroundJob::Schedule.order(:created_at).last
72
+ expect(TestJob.scheduled?(schedule_id: new_schedule.id)).to be true
73
+ expect(new_schedule.delayed_job.cron).to eq '1 1 * * *'
74
74
 
75
- expect(Test2Job.scheduled?).to be true
76
- expect(Test2Job.delayed_job.cron).to eq '0 0 * * *'
75
+ expect(Test2Job.scheduled?(schedule_id: schedule.id)).to be true
76
+ expect(schedule.delayed_job.cron).to eq '0 0 * * *'
77
77
  end
78
78
 
79
79
  it 'deletes schedule' do
@@ -83,7 +83,7 @@ feature 'Schedule Jobs Dashboard', js: true do
83
83
 
84
84
  wait_for_ajax
85
85
 
86
- expect(Test2Job.scheduled?).to be false
86
+ expect(Test2Job.scheduled?(schedule_id: schedule.id)).to be false
87
87
  end
88
88
 
89
89
  it 'turns the schedule off' do
@@ -93,7 +93,7 @@ feature 'Schedule Jobs Dashboard', js: true do
93
93
 
94
94
  press 'OK'
95
95
  wait_for_ajax
96
- expect(Test2Job.scheduled?).to be false
96
+ expect(Test2Job.scheduled?(schedule_id: schedule.id)).to be false
97
97
  end
98
98
 
99
99
  it 'shows validation errors' do
@@ -105,7 +105,7 @@ feature 'Schedule Jobs Dashboard', js: true do
105
105
 
106
106
  press 'OK'
107
107
  wait_for_ajax
108
- expect(page).to have_content('Job class has already been taken')
108
+ expect(page).to have_content('Arguments are not unique')
109
109
  expect(page).to have_content('Cron is invalid')
110
110
  end
111
111
  end
@@ -7,20 +7,21 @@ describe 'Cron jobs' do
7
7
  Marty::BackgroundJob::Schedule.create!(
8
8
  job_class: klass.name,
9
9
  cron: '* * * * *',
10
- state: 'on'
10
+ state: 'on',
11
+ arguments: []
11
12
  ).tap do |job|
12
13
  Marty::BackgroundJob::UpdateSchedule.call(
13
14
  id: job.id,
14
- job_class: job.job_class
15
+ job_class: job.job_class,
15
16
  )
16
17
 
17
- dj = klass.delayed_job
18
+ dj = job.delayed_job
18
19
  dj.update!(run_at: 1.minute.ago)
19
20
  end
20
21
  end
21
22
 
22
23
  def run_job
23
- expect(klass.delayed_job).to be_present
24
+ expect(schedule.delayed_job).to be_present
24
25
  expect(Delayed::Job.count).to eq 1
25
26
  worker = Delayed::Worker.new
26
27
  worker.work_off
@@ -34,8 +35,8 @@ describe 'Cron jobs' do
34
35
  end
35
36
 
36
37
  it 'job is recreated' do
37
- expect(klass).to be_scheduled
38
- expect(klass.delayed_job).to be_present
38
+ expect(klass.scheduled?(schedule_id: schedule.id)).to be true
39
+ expect(schedule.delayed_job).to be_present
39
40
  end
40
41
  end
41
42
 
@@ -46,8 +47,8 @@ describe 'Cron jobs' do
46
47
  end
47
48
 
48
49
  it 'job is not recreated' do
49
- expect(klass).to_not be_scheduled
50
- expect(klass.delayed_job).to_not be_present
50
+ expect(klass.scheduled?(schedule_id: schedule.id)).to be false
51
+ expect(schedule.reload.delayed_job).to_not be_present
51
52
  end
52
53
  end
53
54
  end
@@ -59,8 +60,8 @@ describe 'Cron jobs' do
59
60
  end
60
61
 
61
62
  it 'job is not recreated' do
62
- expect(klass).to_not be_scheduled
63
- expect(klass.delayed_job).to_not be_present
63
+ expect(klass.scheduled?(schedule_id: schedule.id)).to be false
64
+ expect(schedule.reload.delayed_job).to_not be_present
64
65
  end
65
66
  end
66
67
  end
@@ -75,7 +76,7 @@ describe 'Cron jobs' do
75
76
  log = Marty::BackgroundJob::Log.find_by(job_class: klass.name)
76
77
  expect(log.error).to be_present
77
78
  expect(log.failure?).to be true
78
- expect(klass).to be_scheduled
79
+ expect(klass.scheduled?(schedule_id: schedule.id)).to be true
79
80
  end
80
81
 
81
82
  it 'logs success' do
@@ -85,7 +86,10 @@ describe 'Cron jobs' do
85
86
  log = Marty::BackgroundJob::Log.find_by(job_class: klass.name)
86
87
  expect(log.error).to_not be_present
87
88
  expect(log.success?).to be true
88
- expect(klass).to be_scheduled
89
+ expect(klass.scheduled?(schedule_id: schedule.id)).to be true
90
+
91
+ dj = schedule.reload.delayed_job
92
+ expect(dj.schedule_id).to eq schedule.id
89
93
  end
90
94
  end
91
95
  end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ # Most of the code is tested in cron_job_spec.rb
4
+ describe 'Delorean Background Jobs' do
5
+ let(:klass) { Marty::DeloreanBackgroundJob }
6
+
7
+ before do
8
+ Marty::Script.load_scripts(nil)
9
+ end
10
+
11
+ let!(:schedule) do
12
+ Marty::BackgroundJob::Schedule.create!(
13
+ job_class: klass.name,
14
+ cron: '* * * * *',
15
+ state: 'on',
16
+ arguments: ['Jobs', 'TestJob1', 'perform']
17
+ ).tap do |job|
18
+ Marty::BackgroundJob::UpdateSchedule.call(
19
+ id: job.id,
20
+ job_class: job.job_class,
21
+ )
22
+
23
+ dj = job.delayed_job
24
+ dj.update!(run_at: 1.minute.ago)
25
+ end
26
+ end
27
+
28
+ def run_job
29
+ expect(schedule.delayed_job).to be_present
30
+ expect(Delayed::Job.count).to eq 1
31
+ worker = Delayed::Worker.new
32
+ worker.work_off
33
+ end
34
+
35
+ describe 'logs' do
36
+ it 'logs success' do
37
+ allow(klass).to receive(:trigger_failure).and_return(nil)
38
+
39
+ expect { run_job }.to change { Marty::BackgroundJob::Log.count }.by 1
40
+ log = Marty::BackgroundJob::Log.find_by(job_class: klass.name)
41
+ expect(log.error).to_not be_present
42
+ expect(log.arguments).to eq ['Jobs', 'TestJob1', 'perform']
43
+ expect(log.success?).to be true
44
+ expect(klass.scheduled?(schedule_id: schedule.id)).to be true
45
+
46
+ dj = schedule.reload.delayed_job
47
+ expect(dj.schedule_id).to eq schedule.id
48
+ end
49
+ end
50
+ end
@@ -92,6 +92,7 @@ describe Marty::Promise, slow: true, retry: 3 do
92
92
  expect(runtime > expected_time).to be true
93
93
  expect(runtime < expected_time + 0.5).to be true
94
94
  expect(error).to be_present
95
+ expect(error).to include('Triggered by Delayed::WorkerTimeout')
95
96
  end
96
97
  end
97
98
 
@@ -11,16 +11,18 @@ module Marty
11
11
 
12
12
  Marty::Jobs::Schedule.call
13
13
 
14
- dj = TestJob.delayed_job
14
+ dj = schedule.delayed_job
15
15
 
16
- TestJob.delayed_job.dup.tap do |new_dj|
16
+ schedule.delayed_job.dup.tap do |new_dj|
17
17
  new_dj.handler = new_dj.handler.gsub('TestJob', 'Test2Job')
18
+ new_dj.schedule_id = nil
18
19
  new_dj.cron = nil
19
20
  new_dj.save!
20
21
  end
21
22
 
22
- TestJob.delayed_job.dup.tap do |new_dj|
23
+ schedule.delayed_job.dup.tap do |new_dj|
23
24
  new_dj.handler = new_dj.handler.gsub('TestJob', 'MissingJob')
25
+ new_dj.schedule_id = nil
24
26
  new_dj.save!
25
27
  end
26
28
  end
@@ -5,20 +5,21 @@ module Marty
5
5
  let!(:schedule) do
6
6
  Marty::BackgroundJob::Schedule.create!(
7
7
  job_class: 'TestJob',
8
+ arguments: [],
8
9
  cron: '0 0 * * *',
9
10
  state: 'on'
10
11
  )
11
12
  end
12
13
 
13
14
  it 'schedules jobs' do
14
- expect(TestJob).to_not be_scheduled
15
+ expect(TestJob.scheduled?(schedule_id: schedule.id)).to be false
15
16
  described_class.call
16
- expect(TestJob).to be_scheduled
17
+ expect(TestJob.scheduled?(schedule_id: schedule.id)).to be true
17
18
  end
18
19
 
19
20
  it 'deletes previously scheduled jobs' do
20
21
  described_class.call
21
- expect(TestJob).to be_scheduled
22
+ expect(TestJob.scheduled?(schedule_id: schedule.id)).to be true
22
23
  schedule.destroy!
23
24
 
24
25
  non_cron_job = Delayed::Job.create!(handler: 'Non cron job')
@@ -29,7 +30,7 @@ module Marty
29
30
 
30
31
  described_class.call
31
32
 
32
- expect(TestJob).to_not be_scheduled
33
+ expect(TestJob.scheduled?(schedule_id: schedule.id)).to be false
33
34
  any_old_scheduled_jobs = Delayed::Job.where('handler ILIKE ?', '%WrongTestJob%').any?
34
35
  expect(any_old_scheduled_jobs).to be false
35
36
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marty
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.5.1
4
+ version: 10.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arman Bostani
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2020-02-18 00:00:00.000000000 Z
17
+ date: 2020-03-06 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: actioncable
@@ -391,6 +391,7 @@ files:
391
391
  - app/helpers/marty/enum_helper.rb
392
392
  - app/helpers/marty/script_set.rb
393
393
  - app/jobs/marty/cron_job.rb
394
+ - app/jobs/marty/delorean_background_job.rb
394
395
  - app/jobs/marty/remove_old_promises_job.rb
395
396
  - app/models/marty/api_auth.rb
396
397
  - app/models/marty/api_config.rb
@@ -512,6 +513,10 @@ files:
512
513
  - db/migrate/520_create_marty_notifications.rb
513
514
  - db/migrate/521_create_marty_notifications_deliveries.rb
514
515
  - db/migrate/522_create_marty_notifications_config.rb
516
+ - db/migrate/523_add_timeout_to_promises.rb
517
+ - db/migrate/524_add_timeout_to_promise_view.rb
518
+ - db/migrate/525_add_arguments_to_jobs_schedules.rb
519
+ - db/migrate/526_add_schedule_id_to_delayed_jobs.rb
515
520
  - db/seeds.rb
516
521
  - db/sql/lookup_grid_distinct_v1.sql
517
522
  - db/sql/query_grid_dir_v1.sql
@@ -538,6 +543,7 @@ files:
538
543
  - lib/marty/data_conversion.rb
539
544
  - lib/marty/data_exporter.rb
540
545
  - lib/marty/data_importer.rb
546
+ - lib/marty/delayed_job/queue_adapter.rb
541
547
  - lib/marty/delayed_job/scheduled_job_plugin.rb
542
548
  - lib/marty/diagnostic/aws/ec2_instance.rb
543
549
  - lib/marty/diagnostic/aws/error.rb
@@ -594,6 +600,8 @@ files:
594
600
  - spec/controllers/job_controller_spec.rb
595
601
  - spec/controllers/rpc_controller_spec.rb
596
602
  - spec/controllers/rpc_import_spec.rb
603
+ - spec/dummy/.foreman
604
+ - spec/dummy/Procfile
597
605
  - spec/dummy/README.rdoc
598
606
  - spec/dummy/Rakefile
599
607
  - spec/dummy/app/assets/config/manifest.js
@@ -683,6 +691,7 @@ files:
683
691
  - spec/dummy/delorean/delorean_fn.dl
684
692
  - spec/dummy/delorean/enum_report.dl
685
693
  - spec/dummy/delorean/fields.dl
694
+ - spec/dummy/delorean/jobs.dl
686
695
  - spec/dummy/delorean/styles.dl
687
696
  - spec/dummy/delorean/table_report.dl
688
697
  - spec/dummy/delorean/test_namespace/nested_namespace/test.dl
@@ -1753,6 +1762,7 @@ files:
1753
1762
  - spec/fixtures/scripts/load_tests/script2.dl
1754
1763
  - spec/job_helper.rb
1755
1764
  - spec/jobs/cron_job_spec.rb
1765
+ - spec/jobs/delorean_background_job_spec.rb
1756
1766
  - spec/lib/data_blame_spec.rb
1757
1767
  - spec/lib/data_conversion_spec.rb
1758
1768
  - spec/lib/data_exporter_spec.rb