canvas_sync 0.16.5 → 0.17.0.beta5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +49 -137
  3. data/app/models/canvas_sync/sync_batch.rb +5 -0
  4. data/db/migrate/20201018210836_create_canvas_sync_sync_batches.rb +11 -0
  5. data/lib/canvas_sync.rb +35 -97
  6. data/lib/canvas_sync/importers/bulk_importer.rb +4 -7
  7. data/lib/canvas_sync/job.rb +4 -10
  8. data/lib/canvas_sync/job_batches/batch.rb +403 -0
  9. data/lib/canvas_sync/job_batches/batch_aware_job.rb +62 -0
  10. data/lib/canvas_sync/job_batches/callback.rb +152 -0
  11. data/lib/canvas_sync/job_batches/chain_builder.rb +220 -0
  12. data/lib/canvas_sync/job_batches/context_hash.rb +147 -0
  13. data/lib/canvas_sync/job_batches/jobs/base_job.rb +7 -0
  14. data/lib/canvas_sync/job_batches/jobs/concurrent_batch_job.rb +19 -0
  15. data/lib/canvas_sync/job_batches/jobs/serial_batch_job.rb +75 -0
  16. data/lib/canvas_sync/job_batches/sidekiq.rb +93 -0
  17. data/lib/canvas_sync/job_batches/status.rb +83 -0
  18. data/lib/canvas_sync/jobs/begin_sync_chain_job.rb +35 -0
  19. data/lib/canvas_sync/jobs/report_checker.rb +3 -6
  20. data/lib/canvas_sync/jobs/report_processor_job.rb +2 -5
  21. data/lib/canvas_sync/jobs/report_starter.rb +28 -20
  22. data/lib/canvas_sync/jobs/sync_accounts_job.rb +3 -5
  23. data/lib/canvas_sync/jobs/sync_admins_job.rb +2 -4
  24. data/lib/canvas_sync/jobs/sync_assignment_groups_job.rb +2 -4
  25. data/lib/canvas_sync/jobs/sync_assignments_job.rb +2 -4
  26. data/lib/canvas_sync/jobs/sync_context_module_items_job.rb +2 -4
  27. data/lib/canvas_sync/jobs/sync_context_modules_job.rb +2 -4
  28. data/lib/canvas_sync/jobs/sync_provisioning_report_job.rb +4 -34
  29. data/lib/canvas_sync/jobs/sync_roles_job.rb +2 -5
  30. data/lib/canvas_sync/jobs/sync_simple_table_job.rb +11 -32
  31. data/lib/canvas_sync/jobs/sync_submissions_job.rb +2 -4
  32. data/lib/canvas_sync/jobs/sync_terms_job.rb +25 -8
  33. data/lib/canvas_sync/processors/assignment_groups_processor.rb +2 -3
  34. data/lib/canvas_sync/processors/assignments_processor.rb +2 -3
  35. data/lib/canvas_sync/processors/context_module_items_processor.rb +2 -3
  36. data/lib/canvas_sync/processors/context_modules_processor.rb +2 -3
  37. data/lib/canvas_sync/processors/normal_processor.rb +1 -2
  38. data/lib/canvas_sync/processors/provisioning_report_processor.rb +2 -10
  39. data/lib/canvas_sync/processors/submissions_processor.rb +2 -3
  40. data/lib/canvas_sync/version.rb +1 -1
  41. data/spec/canvas_sync/canvas_sync_spec.rb +136 -153
  42. data/spec/canvas_sync/jobs/job_spec.rb +9 -17
  43. data/spec/canvas_sync/jobs/report_checker_spec.rb +1 -3
  44. data/spec/canvas_sync/jobs/report_processor_job_spec.rb +0 -3
  45. data/spec/canvas_sync/jobs/report_starter_spec.rb +19 -28
  46. data/spec/canvas_sync/jobs/sync_admins_job_spec.rb +1 -4
  47. data/spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb +2 -1
  48. data/spec/canvas_sync/jobs/sync_assignments_job_spec.rb +3 -2
  49. data/spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb +3 -2
  50. data/spec/canvas_sync/jobs/sync_context_modules_job_spec.rb +3 -2
  51. data/spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb +3 -35
  52. data/spec/canvas_sync/jobs/sync_roles_job_spec.rb +1 -4
  53. data/spec/canvas_sync/jobs/sync_simple_table_job_spec.rb +5 -12
  54. data/spec/canvas_sync/jobs/sync_submissions_job_spec.rb +2 -1
  55. data/spec/canvas_sync/jobs/sync_terms_job_spec.rb +1 -4
  56. data/spec/dummy/config/environments/test.rb +2 -0
  57. data/spec/dummy/db/schema.rb +9 -1
  58. data/spec/job_batching/batch_aware_job_spec.rb +100 -0
  59. data/spec/job_batching/batch_spec.rb +372 -0
  60. data/spec/job_batching/callback_spec.rb +38 -0
  61. data/spec/job_batching/flow_spec.rb +88 -0
  62. data/spec/job_batching/integration/integration.rb +57 -0
  63. data/spec/job_batching/integration/nested.rb +88 -0
  64. data/spec/job_batching/integration/simple.rb +47 -0
  65. data/spec/job_batching/integration/workflow.rb +134 -0
  66. data/spec/job_batching/integration_helper.rb +48 -0
  67. data/spec/job_batching/sidekiq_spec.rb +124 -0
  68. data/spec/job_batching/status_spec.rb +92 -0
  69. data/spec/job_batching/support/base_job.rb +14 -0
  70. data/spec/job_batching/support/sample_callback.rb +2 -0
  71. data/spec/spec_helper.rb +17 -0
  72. metadata +85 -8
  73. data/lib/canvas_sync/job_chain.rb +0 -102
  74. data/lib/canvas_sync/jobs/fork_gather.rb +0 -74
  75. data/spec/canvas_sync/jobs/fork_gather_spec.rb +0 -73
@@ -5,12 +5,10 @@ RSpec.describe CanvasSync::Jobs::ReportChecker do
5
5
  let(:report_id) { 1 }
6
6
  let(:report_name) { 'provisioning_csv' }
7
7
  let(:processor) { 'FakeProcessor' }
8
- let(:job_chain) { { jobs: [], global_options: {} } }
9
8
 
10
9
  describe '#perform' do
11
10
  def start_job
12
11
  CanvasSync::Jobs::ReportChecker.perform_now(
13
- job_chain,
14
12
  'provisioning_csv',
15
13
  report_id,
16
14
  processor,
@@ -25,7 +23,7 @@ RSpec.describe CanvasSync::Jobs::ReportChecker do
25
23
  .and_return({ 'status' => 'complete', 'attachment' => { 'url' => 'blah' } })
26
24
 
27
25
  expect(CanvasSync::Jobs::ReportProcessorJob).to receive(:perform_later)
28
- .with(job_chain, report_name, 'blah', processor, {}, report_id)
26
+ .with(report_name, 'blah', processor, {}, report_id)
29
27
 
30
28
  start_job
31
29
  end
@@ -6,17 +6,14 @@ RSpec.describe CanvasSync::Jobs::ReportProcessorJob do
6
6
  let(:report_name) { 'provisioning_csv' }
7
7
  let(:report_url) { 'https://test.instructure.com/sample_report_download' }
8
8
  let(:processor) { FakeProcessor.to_s }
9
- let(:job_chain) { { jobs: [], global_options: {} } }
10
9
  let(:report_id) { 1 }
11
10
 
12
11
  describe '#perform' do
13
12
  it 'downloads the report to a file and then calls the process method on the processor, and then invokes the next job' do
14
13
  expect(IO).to receive(:copy_stream)
15
14
  expect(FakeProcessor).to receive(:process)
16
- expect(CanvasSync).to receive(:invoke_next).with(job_chain)
17
15
 
18
16
  CanvasSync::Jobs::ReportProcessorJob.perform_now(
19
- job_chain,
20
17
  report_name,
21
18
  report_url,
22
19
  processor,
@@ -16,7 +16,6 @@ RSpec.describe CanvasSync::Jobs::ReportStarter do
16
16
  expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
17
17
 
18
18
  CanvasSync::Jobs::ReportStarter.perform_now(
19
- { jobs: [], global_options: {} },
20
19
  report_name,
21
20
  report_params,
22
21
  processor,
@@ -24,30 +23,27 @@ RSpec.describe CanvasSync::Jobs::ReportStarter do
24
23
  end
25
24
 
26
25
  context 'allow_redownloads is true' do
27
- context 'the report has already been cached' do
28
- it 'runs the report checker for the already started report' do
29
- expect_any_instance_of(Bearcat::Client).to_not receive(:start_report)
30
- job_chain = { jobs: [], global_options: { report_name => 1 } }
26
+ # context 'the report has already been cached' do
27
+ # it 'runs the report checker for the already started report' do
28
+ # expect_any_instance_of(Bearcat::Client).to_not receive(:start_report)
31
29
 
32
- expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_return(report_checker_double)
33
- expect(report_checker_double).to receive(:perform_later).with(
34
- job_chain,
35
- report_name,
36
- 1,
37
- processor,
38
- options
39
- )
30
+ # expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_return(report_checker_double)
31
+ # expect(report_checker_double).to receive(:perform_later).with(
32
+ # report_name,
33
+ # 1,
34
+ # processor,
35
+ # options
36
+ # )
40
37
 
41
- CanvasSync::Jobs::ReportStarter.perform_now(
42
- job_chain,
43
- report_name,
44
- report_params,
45
- processor,
46
- options,
47
- allow_redownloads: true
48
- )
49
- end
50
- end
38
+ # CanvasSync::Jobs::ReportStarter.perform_now(
39
+ # report_name,
40
+ # report_params,
41
+ # processor,
42
+ # options,
43
+ # allow_redownloads: true
44
+ # )
45
+ # end
46
+ # end
51
47
 
52
48
  context 'the report has not been started before' do
53
49
  it 'starts a new report and caches the report id' do
@@ -55,12 +51,8 @@ RSpec.describe CanvasSync::Jobs::ReportStarter do
55
51
  .with('self', report_name, report_params)
56
52
  .and_return({ 'id' => 1 })
57
53
 
58
- orig_job_chain = { jobs: [], global_options: {} }
59
- new_job_chain = { jobs: [], global_options: { report_name => 1 } }
60
-
61
54
  expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_return(report_checker_double)
62
55
  expect(report_checker_double).to receive(:perform_later).with(
63
- new_job_chain,
64
56
  report_name,
65
57
  1,
66
58
  processor,
@@ -68,7 +60,6 @@ RSpec.describe CanvasSync::Jobs::ReportStarter do
68
60
  )
69
61
 
70
62
  CanvasSync::Jobs::ReportStarter.perform_now(
71
- orig_job_chain,
72
63
  report_name,
73
64
  report_params,
74
65
  processor,
@@ -4,13 +4,10 @@ RSpec.describe CanvasSync::Jobs::SyncAdminsJob do
4
4
  describe '#perform' do
5
5
  let!(:account) { FactoryGirl.create(:account, canvas_id: 1) }
6
6
  let(:admin_params) { open_canvas_fixture('admins') }
7
- let(:job_chain) { { jobs: [], global_options: {}} }
8
7
 
9
8
  it 'retrieves all admins from the Canvas API and then invokes the next job' do
10
- expect(CanvasSync).to receive(:invoke_next).with(job_chain)
11
-
12
9
  expect {
13
- CanvasSync::Jobs::SyncAdminsJob.perform_now(job_chain, {})
10
+ CanvasSync::Jobs::SyncAdminsJob.perform_now({})
14
11
  }.to change { Admin.count }.by(admin_params.length)
15
12
  end
16
13
  end
@@ -10,7 +10,8 @@ RSpec.describe CanvasSync::Jobs::SyncAssignmentGroupsJob do
10
10
 
11
11
  expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
12
12
 
13
- CanvasSync::Jobs::SyncAssignmentGroupsJob.perform_now({ jobs: [], global_options: { canvas_term_id: 1 } }, {})
13
+ set_batch_context(canvas_term_id: 1)
14
+ CanvasSync::Jobs::SyncAssignmentGroupsJob.perform_now({})
14
15
  end
15
16
  end
16
17
  end
@@ -10,7 +10,8 @@ RSpec.describe CanvasSync::Jobs::SyncAssignmentsJob do
10
10
 
11
11
  expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
12
12
 
13
- CanvasSync::Jobs::SyncAssignmentsJob.perform_now({ jobs: [], global_options: { canvas_term_id: 1 } }, {})
13
+ set_batch_context(canvas_term_id: 1)
14
+ CanvasSync::Jobs::SyncAssignmentsJob.perform_now({})
14
15
  end
15
16
  end
16
17
 
@@ -22,7 +23,7 @@ RSpec.describe CanvasSync::Jobs::SyncAssignmentsJob do
22
23
 
23
24
  expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
24
25
 
25
- CanvasSync::Jobs::SyncAssignmentsJob.perform_now({ jobs: [], global_options: {} }, {})
26
+ CanvasSync::Jobs::SyncAssignmentsJob.perform_now({})
26
27
  end
27
28
  end
28
29
  end
@@ -10,7 +10,8 @@ RSpec.describe CanvasSync::Jobs::SyncContextModuleItemsJob do
10
10
 
11
11
  expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
12
12
 
13
- CanvasSync::Jobs::SyncContextModuleItemsJob.perform_now({ jobs: [], global_options: { canvas_term_id: 1 } }, {})
13
+ set_batch_context(canvas_term_id: 1)
14
+ CanvasSync::Jobs::SyncContextModuleItemsJob.perform_now({})
14
15
  end
15
16
  end
16
17
 
@@ -22,7 +23,7 @@ RSpec.describe CanvasSync::Jobs::SyncContextModuleItemsJob do
22
23
 
23
24
  expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
24
25
 
25
- CanvasSync::Jobs::SyncContextModuleItemsJob.perform_now({ jobs: [], global_options: {} }, {})
26
+ CanvasSync::Jobs::SyncContextModuleItemsJob.perform_now({})
26
27
  end
27
28
  end
28
29
  end
@@ -10,7 +10,8 @@ RSpec.describe CanvasSync::Jobs::SyncContextModulesJob do
10
10
 
11
11
  expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
12
12
 
13
- CanvasSync::Jobs::SyncContextModulesJob.perform_now({ jobs: [], global_options: { canvas_term_id: 1 } }, {})
13
+ set_batch_context(canvas_term_id: 1)
14
+ CanvasSync::Jobs::SyncContextModulesJob.perform_now({})
14
15
  end
15
16
  end
16
17
 
@@ -22,7 +23,7 @@ RSpec.describe CanvasSync::Jobs::SyncContextModulesJob do
22
23
 
23
24
  expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
24
25
 
25
- CanvasSync::Jobs::SyncContextModulesJob.perform_now({ jobs: [], global_options: {} }, {})
26
+ CanvasSync::Jobs::SyncContextModulesJob.perform_now({})
26
27
  end
27
28
  end
28
29
  end
@@ -2,59 +2,29 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe CanvasSync::Jobs::SyncProvisioningReportJob do
4
4
  describe '#perform' do
5
- let(:job_chain) { {jobs: [], global_options: {}} }
6
-
7
5
  context 'a term scope is specified' do
8
- let!(:active_term_1) { FactoryGirl.create(:term) }
9
- let!(:active_term_2) { FactoryGirl.create(:term) }
10
- let!(:inactive_term_1) { FactoryGirl.create(:term, workflow_state: 'inactive') }
6
+ let!(:term) { FactoryGirl.create(:term) }
11
7
 
12
8
  it 'enqueues a ReportStarter for a provisioning report for the specified models for each term' do
13
- expected_job_chain = Marshal.load(Marshal.dump(job_chain))
14
- expected_job_chain[:global_options][:canvas_term_id] = active_term_1.canvas_id
15
- expected_job_chain[:global_options] = hash_including(expected_job_chain[:global_options])
16
-
17
- expect(CanvasSync::Jobs::ReportStarter).to receive(:perform_later)
18
- .with(
19
- hash_including(expected_job_chain),
20
- 'proservices_provisioning_csv',
21
- {
22
- parameters: {
23
- include_deleted: true,
24
- 'users' => true,
25
- 'courses' => true,
26
- enrollment_term_id: active_term_1.canvas_id
27
- }
28
- },
29
- CanvasSync::Processors::ProvisioningReportProcessor.to_s,
30
- { models: ['users', 'courses'], term_scope: 'active' }
31
- )
32
-
33
- expected_job_chain_2 = Marshal.load(Marshal.dump(job_chain))
34
- expected_job_chain_2[:global_options][:canvas_term_id] = active_term_2.canvas_id
35
- expected_job_chain_2[:global_options] = hash_including(expected_job_chain_2[:global_options])
36
-
37
9
  expect(CanvasSync::Jobs::ReportStarter).to receive(:perform_later)
38
10
  .with(
39
- hash_including(expected_job_chain_2),
40
11
  'proservices_provisioning_csv',
41
12
  {
42
13
  parameters: {
43
14
  include_deleted: true,
44
15
  'users' => true,
45
16
  'courses' => true,
46
- enrollment_term_id: active_term_2.canvas_id
17
+ enrollment_term_id: term.canvas_id
47
18
  }
48
19
  },
49
20
  CanvasSync::Processors::ProvisioningReportProcessor.to_s,
50
21
  { models: ['users', 'courses'], term_scope: 'active' }
51
22
  )
52
23
 
24
+ set_batch_context(canvas_term_id: term.canvas_id)
53
25
  CanvasSync::Jobs::SyncProvisioningReportJob.perform_now(
54
- job_chain,
55
26
  { models: ['users', 'courses'], term_scope: 'active' }
56
27
  )
57
- expect(CanvasSync::JobLog.last.fork_count).to eq 2
58
28
  end
59
29
  end
60
30
 
@@ -62,7 +32,6 @@ RSpec.describe CanvasSync::Jobs::SyncProvisioningReportJob do
62
32
  it 'enqueues a single ReportStarter for a provisioning report across all terms for the specified models' do
63
33
  expect(CanvasSync::Jobs::ReportStarter).to receive(:perform_later)
64
34
  .with(
65
- job_chain,
66
35
  'proservices_provisioning_csv',
67
36
  {
68
37
  parameters: {
@@ -76,7 +45,6 @@ RSpec.describe CanvasSync::Jobs::SyncProvisioningReportJob do
76
45
  )
77
46
 
78
47
  CanvasSync::Jobs::SyncProvisioningReportJob.perform_now(
79
- job_chain,
80
48
  { models: ['users', 'courses'] }
81
49
  )
82
50
  end
@@ -4,13 +4,10 @@ RSpec.describe CanvasSync::Jobs::SyncRolesJob do
4
4
  describe '#perform' do
5
5
  let!(:account) { FactoryGirl.create(:account, canvas_id: 1) }
6
6
  let(:role_params) { open_canvas_fixture('roles') }
7
- let(:job_chain) { { jobs: [], global_options: {}} }
8
7
 
9
8
  it 'retrieves all roles from the Canvas API and then invokes the next job' do
10
- expect(CanvasSync).to receive(:invoke_next).with(job_chain)
11
-
12
9
  expect {
13
- CanvasSync::Jobs::SyncRolesJob.perform_now(job_chain, {})
10
+ CanvasSync::Jobs::SyncRolesJob.perform_now({})
14
11
  }.to change { Role.count }.by(role_params.length)
15
12
  end
16
13
  end
@@ -2,25 +2,17 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe CanvasSync::Jobs::SyncSimpleTableJob do
4
4
  describe '#perform' do
5
- let(:job_chain) { {jobs: [], global_options: {}} }
6
-
7
5
  context 'Simple report' do
8
- let!(:active_term_1) { FactoryGirl.create(:term) }
9
- let!(:inactive_term_1) { FactoryGirl.create(:term, workflow_state: 'inactive') }
6
+ let!(:term) { FactoryGirl.create(:term) }
10
7
 
11
8
  it 'enqueues a ReportStarter for a provisioning report for the specified model for a term' do
12
- expected_job_chain = Marshal.load(Marshal.dump(job_chain))
13
- expected_job_chain[:global_options][:canvas_term_id] = active_term_1.canvas_id
14
- expected_job_chain[:global_options] = hash_including(expected_job_chain[:global_options])
15
-
16
9
  expect(CanvasSync::Jobs::ReportStarter).to receive(:perform_later)
17
10
  .with(
18
- hash_including(expected_job_chain),
19
11
  'proservices_provisioning_csv',
20
12
  {
21
13
  "parameters[include_deleted]" => true,
22
14
  "parameters[courses]" => true,
23
- "parameters[enrollment_term_id]" => active_term_1.canvas_id
15
+ "parameters[enrollment_term_id]" => term.canvas_id
24
16
  },
25
17
  CanvasSync::Processors::NormalProcessor.to_s,
26
18
  {
@@ -32,13 +24,14 @@ RSpec.describe CanvasSync::Jobs::SyncSimpleTableJob do
32
24
  params: {
33
25
  "parameters[include_deleted]" => true,
34
26
  "parameters[courses]" => true,
35
- "parameters[enrollment_term_id]" => active_term_1.canvas_id
27
+ "parameters[enrollment_term_id]" => term.canvas_id
36
28
  }
37
29
  }
38
30
  )
39
31
 
32
+ set_batch_context(canvas_term_id: term.canvas_id)
33
+
40
34
  CanvasSync::Jobs::SyncSimpleTableJob.perform_now(
41
- job_chain,
42
35
  {
43
36
  report_name: 'proservices_provisioning_csv',
44
37
  model: 'courses',
@@ -10,7 +10,8 @@ RSpec.describe CanvasSync::Jobs::SyncSubmissionsJob do
10
10
 
11
11
  expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
12
12
 
13
- CanvasSync::Jobs::SyncSubmissionsJob.perform_now({ jobs: [], global_options: { canvas_term_id: 1 } }, {})
13
+ set_batch_context(canvas_term_id: 1)
14
+ CanvasSync::Jobs::SyncSubmissionsJob.perform_now({})
14
15
  end
15
16
  end
16
17
  end
@@ -3,13 +3,10 @@ require 'spec_helper'
3
3
  RSpec.describe CanvasSync::Jobs::SyncTermsJob do
4
4
  describe '#perform' do
5
5
  let(:term_params) { open_canvas_fixture('terms')['enrollment_terms'] }
6
- let(:job_chain) { { jobs: [], global_options: {}} }
7
6
 
8
7
  it 'retrieves all terms from the Canvas API and then invokes the next job' do
9
- expect(CanvasSync).to receive(:invoke_next).with(job_chain)
10
-
11
8
  expect {
12
- CanvasSync::Jobs::SyncTermsJob.perform_now(job_chain, {})
9
+ CanvasSync::Jobs::SyncTermsJob.perform_now({})
13
10
  }.to change { Term.count }.by(term_params.length)
14
11
  end
15
12
  end
@@ -37,6 +37,8 @@ Rails.application.configure do
37
37
  # Print deprecation notices to the stderr.
38
38
  config.active_support.deprecation = :stderr
39
39
 
40
+ config.active_job.queue_adapter = :test
41
+
40
42
  # Raises error for missing translations
41
43
  # config.action_view.raise_on_missing_translations = true
42
44
  end
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 2020_10_16_181346) do
13
+ ActiveRecord::Schema.define(version: 2020_10_18_210836) do
14
14
 
15
15
  # These are extensions that must be enabled in order to support this database
16
16
  enable_extension "plpgsql"
@@ -99,6 +99,14 @@ ActiveRecord::Schema.define(version: 2020_10_16_181346) do
99
99
  t.index ["job_id"], name: "index_canvas_sync_job_logs_on_job_id"
100
100
  end
101
101
 
102
+ create_table "canvas_sync_sync_batches", id: :serial, force: :cascade do |t|
103
+ t.datetime "started_at"
104
+ t.datetime "completed_at"
105
+ t.string "status"
106
+ t.datetime "created_at"
107
+ t.datetime "updated_at"
108
+ end
109
+
102
110
  create_table "context_module_items", force: :cascade do |t|
103
111
  t.bigint "canvas_id"
104
112
  t.bigint "canvas_context_module_id"
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe CanvasSync::JobBatches::BatchAwareJob do
4
+ include ActiveJob::TestHelper
5
+
6
+ after do
7
+ clear_enqueued_jobs
8
+ clear_performed_jobs
9
+ end
10
+
11
+ context "When Performing" do
12
+ context 'when without batch' do
13
+ it 'just yields' do
14
+ expect(CanvasSync::JobBatches::Batch).not_to receive(:process_successful_job)
15
+ expect(CanvasSync::JobBatches::Batch).not_to receive(:process_failed_job)
16
+ expect_any_instance_of(BatchTestJobBase).to receive(:perform)
17
+
18
+ BatchTestJobBase.perform_now
19
+ end
20
+ end
21
+
22
+ context 'when in batch' do
23
+ let(:bid) { 'SAMPLEBID' }
24
+
25
+ context 'when successful' do
26
+ it 'yields' do
27
+ expect_any_instance_of(BatchTestJobBase).to receive(:perform)
28
+ BatchTestJobBase.perform_now
29
+ end
30
+
31
+ it 'calls process_successful_job' do
32
+ job = BatchTestJobBase.new
33
+ job.instance_variable_set(:@bid, bid)
34
+ expect(CanvasSync::JobBatches::Batch).to receive(:process_successful_job).with(bid, job.job_id)
35
+ job.perform_now
36
+ end
37
+ end
38
+
39
+ context 'when failed' do
40
+ it 'calls process_failed_job and reraises exception' do
41
+ reraised = false
42
+ job = FailingBatchTestJobBase.new
43
+ job.instance_variable_set(:@bid, bid)
44
+ expect(CanvasSync::JobBatches::Batch).to receive(:process_failed_job)
45
+ begin
46
+ job.perform_now
47
+ rescue
48
+ reraised = true
49
+ end
50
+ expect(reraised).to be_truthy
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ context "When Enqueueing" do
57
+ context 'when without batch' do
58
+ it 'just yields' do
59
+ expect(CanvasSync::JobBatches::Batch).not_to receive(:increment_job_queue)
60
+ BatchTestJobBase.perform_later
61
+ expect(BatchTestJobBase).to have_been_enqueued
62
+ end
63
+ end
64
+
65
+ context 'when in batch' do
66
+ let(:bid) { 'SAMPLEBID' }
67
+
68
+ before do
69
+ Thread.current[:batch] = CanvasSync::JobBatches::Batch.new(bid)
70
+ Thread.current[:batch].instance_variable_set(:@open, true)
71
+ end
72
+
73
+ it 'yields' do
74
+ expect {
75
+ BatchTestJobBase.perform_later
76
+ }.to enqueue_job(BatchTestJobBase)
77
+ end
78
+
79
+ it 'assigns bid to job metadata' do
80
+ job = BatchTestJobBase.perform_later
81
+ expect(job.bid).to eq bid
82
+ expect(job.serialize['batch_id']).to eq bid
83
+ end
84
+ end
85
+ end
86
+
87
+ context 'worker' do
88
+ it 'defines method bid' do
89
+ expect(ActiveJob::Base.instance_methods).to include(:bid)
90
+ end
91
+
92
+ it 'defines method batch' do
93
+ expect(ActiveJob::Base.instance_methods).to include(:batch)
94
+ end
95
+
96
+ it 'defines method valid_within_batch?' do
97
+ expect(ActiveJob::Base.instance_methods).to include(:valid_within_batch?)
98
+ end
99
+ end
100
+ end