marty 9.5.1 → 10.0.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 (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