canvas_sync 0.26.1 → 0.27.1.beta2

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +117 -20
  3. data/app/controllers/canvas_sync/api/v1/live_events_controller.rb +1 -0
  4. data/lib/canvas_sync/config.rb +1 -1
  5. data/lib/canvas_sync/importers/bulk_importer.rb +2 -0
  6. data/lib/canvas_sync/jobs/begin_sync_chain_job.rb +1 -1
  7. data/lib/canvas_sync/jobs/beta_cleanup/create_temp_tables_job.rb +30 -0
  8. data/lib/canvas_sync/jobs/beta_cleanup/delete_related_records_job.rb +125 -0
  9. data/lib/canvas_sync/jobs/beta_cleanup/delete_temp_tables_job.rb +16 -0
  10. data/lib/canvas_sync/jobs/report_starter.rb +33 -46
  11. data/lib/canvas_sync/jobs/report_sync_task.rb +273 -0
  12. data/lib/canvas_sync/jobs/sync_accounts_job.rb +10 -7
  13. data/lib/canvas_sync/jobs/sync_assignment_groups_job.rb +2 -15
  14. data/lib/canvas_sync/jobs/sync_assignment_overrides_job.rb +26 -14
  15. data/lib/canvas_sync/jobs/sync_assignments_job.rb +2 -15
  16. data/lib/canvas_sync/jobs/sync_content_migrations_job.rb +2 -15
  17. data/lib/canvas_sync/jobs/sync_context_module_items_job.rb +2 -15
  18. data/lib/canvas_sync/jobs/sync_context_modules_job.rb +2 -15
  19. data/lib/canvas_sync/jobs/sync_course_progresses_job.rb +2 -16
  20. data/lib/canvas_sync/jobs/sync_provisioning_report_job.rb +135 -14
  21. data/lib/canvas_sync/jobs/sync_rubric_assessments_job.rb +2 -10
  22. data/lib/canvas_sync/jobs/sync_rubric_associations_job.rb +2 -10
  23. data/lib/canvas_sync/jobs/sync_rubrics_job.rb +2 -10
  24. data/lib/canvas_sync/jobs/sync_scores_job.rb +2 -13
  25. data/lib/canvas_sync/jobs/sync_submissions_job.rb +9 -18
  26. data/lib/canvas_sync/jobs/term_batches_job.rb +4 -2
  27. data/lib/canvas_sync/version.rb +1 -1
  28. data/lib/canvas_sync.rb +31 -4
  29. data/spec/canvas_sync/canvas_sync_spec.rb +62 -22
  30. data/spec/canvas_sync/jobs/report_starter_spec.rb +102 -55
  31. data/spec/canvas_sync/jobs/report_sync_task_spec.rb +367 -0
  32. data/spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb +24 -35
  33. data/spec/canvas_sync/processors/assignment_groups_processor_spec.rb +3 -4
  34. data/spec/canvas_sync/processors/assignment_overrides_processor_spec.rb +7 -4
  35. data/spec/canvas_sync/processors/assignments_processor_spec.rb +3 -4
  36. data/spec/canvas_sync/processors/content_migrations_processor_spec.rb +3 -4
  37. data/spec/canvas_sync/processors/context_module_items_processor_spec.rb +4 -5
  38. data/spec/canvas_sync/processors/context_modules_processor_spec.rb +3 -4
  39. data/spec/canvas_sync/processors/course_completion_report_processor_spec.rb +7 -4
  40. data/spec/canvas_sync/processors/provisioning_report_processor_spec.rb +46 -24
  41. data/spec/canvas_sync/processors/rubric_assessments_spec.rb +3 -4
  42. data/spec/canvas_sync/processors/rubric_associations_spec.rb +3 -4
  43. data/spec/canvas_sync/processors/rubrics_processor_spec.rb +3 -4
  44. data/spec/canvas_sync/processors/submissions_processor_spec.rb +3 -4
  45. data/spec/factories/account_factory.rb +1 -1
  46. metadata +7 -33
  47. data/lib/canvas_sync/jobs/report_checker.rb +0 -108
  48. data/lib/canvas_sync/jobs/report_processor_job.rb +0 -35
  49. data/lib/canvas_sync/processors/assignment_groups_processor.rb +0 -19
  50. data/lib/canvas_sync/processors/assignment_overrides_processor.rb +0 -41
  51. data/lib/canvas_sync/processors/assignments_processor.rb +0 -19
  52. data/lib/canvas_sync/processors/content_migrations_processor.rb +0 -19
  53. data/lib/canvas_sync/processors/context_module_items_processor.rb +0 -19
  54. data/lib/canvas_sync/processors/context_modules_processor.rb +0 -19
  55. data/lib/canvas_sync/processors/course_completion_report_processor.rb +0 -20
  56. data/lib/canvas_sync/processors/provisioning_report_processor.rb +0 -149
  57. data/lib/canvas_sync/processors/rubric_assessments_processor.rb +0 -19
  58. data/lib/canvas_sync/processors/rubric_associations_processor.rb +0 -19
  59. data/lib/canvas_sync/processors/rubrics_processor.rb +0 -19
  60. data/lib/canvas_sync/processors/submissions_processor.rb +0 -19
  61. data/spec/canvas_sync/jobs/report_checker_spec.rb +0 -57
  62. data/spec/canvas_sync/jobs/report_processor_job_spec.rb +0 -25
  63. data/spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb +0 -18
  64. data/spec/canvas_sync/jobs/sync_assignments_job_spec.rb +0 -30
  65. data/spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb +0 -30
  66. data/spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb +0 -30
  67. data/spec/canvas_sync/jobs/sync_context_modules_job_spec.rb +0 -30
  68. data/spec/canvas_sync/jobs/sync_scores_job_spec.rb +0 -15
  69. data/spec/canvas_sync/jobs/sync_submissions_job_spec.rb +0 -23
@@ -1,12 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
4
- let(:subject) { CanvasSync::Processors::ProvisioningReportProcessor }
3
+ RSpec.describe CanvasSync::Jobs::SyncProvisioningReportJob do
4
+ let(:task) { described_class.new({ models: ['users'] }, {}, {}) }
5
5
 
6
6
  describe '#process' do
7
7
  it 'process users' do
8
+ task = described_class.new({ models: ['users'] }, {}, {})
8
9
  expect {
9
- subject.process('spec/support/fixtures/reports/users.csv', { models: ['users'] }, 1)
10
+ task.process('spec/support/fixtures/reports/users.csv')
10
11
  }.to change { User.count }.by(2)
11
12
  end
12
13
 
@@ -30,19 +31,22 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
30
31
  end
31
32
 
32
33
  it 'uses keeps support with old installations' do
33
- subject.process('spec/support/fixtures/reports/users.csv', { models: ['users'] }, 1)
34
+ task = described_class.new({ models: ['users'] }, {}, {})
35
+ task.process('spec/support/fixtures/reports/users.csv')
34
36
  expect(User.find_by(canvas_id: 2).sis_id).to eq 'sis_id_2'
35
37
  end
36
38
 
37
39
  it 'uses a User row with a sis_id' do
38
- subject.process('spec/support/fixtures/reports/users.csv', { models: ['users'] }, 1)
40
+ task = described_class.new({ models: ['users'] }, {}, {})
41
+ task.process('spec/support/fixtures/reports/users.csv')
39
42
  expect(User.find_by(canvas_id: 2).sis_id).to eq 'sis_id_2'
40
43
  end
41
44
  end
42
45
 
43
46
  it 'processes courses' do
47
+ task = described_class.new({ models: ['courses'] }, {}, {})
44
48
  expect {
45
- subject.process('spec/support/fixtures/reports/courses.csv', { models: ['courses'] }, 1)
49
+ task.process('spec/support/fixtures/reports/courses.csv')
46
50
  }.to change { Course.count }.by(2)
47
51
  course = Course.first
48
52
  expect(course.start_at).to eq DateTime.parse("2017-03-27 21:53:18")
@@ -50,14 +54,16 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
50
54
  end
51
55
 
52
56
  it 'processes enrollments' do
57
+ task = described_class.new({ models: ['enrollments'] }, {}, {})
53
58
  expect {
54
- subject.process('spec/support/fixtures/reports/enrollments.csv', { models: ['enrollments'] }, 1)
59
+ task.process('spec/support/fixtures/reports/enrollments.csv')
55
60
  }.to change { Enrollment.count }.by(2)
56
61
  end
57
62
 
58
63
  it 'processes sections' do
64
+ task = described_class.new({ models: ['sections'] }, {}, {})
59
65
  expect {
60
- subject.process('spec/support/fixtures/reports/sections.csv', { models: ['sections'] }, 1)
66
+ task.process('spec/support/fixtures/reports/sections.csv')
61
67
  }.to change { Section.count }.by(2)
62
68
  section = Section.first
63
69
  expect(section.start_at).to eq DateTime.parse("2017-03-27 21:53:18")
@@ -65,10 +71,12 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
65
71
  end
66
72
 
67
73
  it 'processes xlist' do
68
- subject.process('spec/support/fixtures/reports/sections.csv', { models: ['sections'] }, 1)
74
+ task = described_class.new({ models: ['sections'] }, {}, {})
75
+ task.process('spec/support/fixtures/reports/sections.csv')
69
76
  expect(Section.find_by(canvas_id: 2).name).to eq "Lame Section"
70
77
 
71
- subject.process('spec/support/fixtures/reports/xlist.csv', { models: ['xlist'] }, 1)
78
+ task = described_class.new({ models: ['xlist'] }, {}, {})
79
+ task.process('spec/support/fixtures/reports/xlist.csv')
72
80
 
73
81
  expect(Section.where.not(canvas_nonxlist_course_id: nil).count).to eq 1
74
82
  cross_listed_section = Section.where.not(canvas_nonxlist_course_id: nil).first
@@ -80,8 +88,9 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
80
88
  end
81
89
 
82
90
  it 'processes groups' do
91
+ task = described_class.new({ models: ['groups'] }, {}, {})
83
92
  expect {
84
- subject.process('spec/support/fixtures/reports/groups.csv', { models: ['groups'] }, 1)
93
+ task.process('spec/support/fixtures/reports/groups.csv')
85
94
  }.to change { Group.count }.by(2)
86
95
  group = Group.find_by_name('Group1')
87
96
  expect(group.workflow_state).to eq 'available'
@@ -90,8 +99,9 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
90
99
  end
91
100
 
92
101
  it 'processes group memberships' do
102
+ task = described_class.new({ models: ['group_membership'] }, {}, {})
93
103
  expect {
94
- subject.process('spec/support/fixtures/reports/group_memberships.csv', { models: ['group_membership'] }, 1)
104
+ task.process('spec/support/fixtures/reports/group_memberships.csv')
95
105
  }.to change { GroupMembership.count }.by(2)
96
106
  group = GroupMembership.find_by_canvas_id(50)
97
107
  expect(group.workflow_state).to eq 'accepted'
@@ -100,8 +110,9 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
100
110
  end
101
111
 
102
112
  it 'processes user_observers' do
113
+ task = described_class.new({ models: ['user_observers'] }, {}, {})
103
114
  expect {
104
- subject.process('spec/support/fixtures/reports/user_observers.csv', { models: ['user_observers'] }, 1)
115
+ task.process('spec/support/fixtures/reports/user_observers.csv')
105
116
  }.to change { UserObserver.count }.by(2)
106
117
  obj = UserObserver.find_by(observed_user_id: 3)
107
118
  expect(obj.workflow_state).to eq 'active'
@@ -109,8 +120,9 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
109
120
  end
110
121
 
111
122
  it 'processes grading_periods' do
123
+ task = described_class.new({ models: ['grading_periods'] }, {}, {})
112
124
  expect {
113
- subject.process('spec/support/fixtures/reports/grading_periods.csv', { models: ['grading_periods'] }, 1)
125
+ task.process('spec/support/fixtures/reports/grading_periods.csv')
114
126
  }.to change { GradingPeriod.count }.by(2)
115
127
  obj = GradingPeriod.find_by(canvas_id: 1)
116
128
  expect(obj.title).to eq 'Period 1'
@@ -119,8 +131,9 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
119
131
  end
120
132
 
121
133
  it 'processes grading_period_groups' do
134
+ task = described_class.new({ models: ['grading_period_groups'] }, {}, {})
122
135
  expect {
123
- subject.process('spec/support/fixtures/reports/grading_period_groups.csv', { models: ['grading_period_groups'] }, 1)
136
+ task.process('spec/support/fixtures/reports/grading_period_groups.csv')
124
137
  }.to change { GradingPeriodGroup.count }.by(1)
125
138
  obj = GradingPeriodGroup.find_by(canvas_id: 1)
126
139
  expect(obj.title).to eq 'Test Group'
@@ -128,14 +141,16 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
128
141
  end
129
142
 
130
143
  it 'processes learning_outcomes' do
144
+ task = described_class.new({ models: ['learning_outcomes'] }, {}, {})
131
145
  expect {
132
- subject.process('spec/support/fixtures/reports/learning_outcomes.csv', { models: ['learning_outcomes'] }, 1)
146
+ task.process('spec/support/fixtures/reports/learning_outcomes.csv')
133
147
  }.to change { LearningOutcome.count }.by(2)
134
148
  end
135
149
 
136
150
  it 'processes learning_outcome_results' do
151
+ task = described_class.new({ models: ['learning_outcome_results'] }, {}, {})
137
152
  expect {
138
- subject.process('spec/support/fixtures/reports/learning_outcome_results.csv', { models: ['learning_outcome_results'] }, 1)
153
+ task.process('spec/support/fixtures/reports/learning_outcome_results.csv')
139
154
  }.to change { LearningOutcomeResult.count }.by(2)
140
155
 
141
156
  columns = LearningOutcomeResult.attribute_names - ['id', 'created_at', 'updated_at']
@@ -146,29 +161,32 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
146
161
  end
147
162
 
148
163
  it 'processes course_nicknames' do
164
+ task = described_class.new({ models: ['course_nicknames'] }, {}, {})
149
165
  CourseNickname.create(canvas_user_preference_value_id: 42, canvas_course_id: 42, canvas_user_id: 42, nickname: 'test')
150
166
  expect(CourseNickname.all.pluck(:canvas_user_preference_value_id)).to include(42)
151
167
  expect {
152
- subject.process('spec/support/fixtures/reports/course_nicknames.csv', { models: ['course_nicknames'] }, 1)
168
+ task.process('spec/support/fixtures/reports/course_nicknames.csv')
153
169
  }.to change { CourseNickname.count }.by(1)
154
170
  expect(CourseNickname.all.pluck(:canvas_user_preference_value_id)).not_to include(42)
155
171
  end
156
172
 
157
173
  it 'model with composite key behaves as expected' do
174
+ task = described_class.new({ models: ['user_observers'] }, {}, {})
158
175
  expect {
159
- subject.process('spec/support/fixtures/reports/user_observers.csv', { models: ['user_observers'] }, 1)
176
+ task.process('spec/support/fixtures/reports/user_observers.csv')
160
177
  }.to change { UserObserver.count }.by(2)
161
178
 
162
179
  expect {
163
- subject.process('spec/support/fixtures/reports/user_observers.csv', { models: ['user_observers'] }, 1)
180
+ task.process('spec/support/fixtures/reports/user_observers.csv')
164
181
  }.to change { UserObserver.count }.by(0)
165
182
  end
166
183
 
167
184
  context 'options[:models] is multiple models' do
168
185
  it 'extracts the ZIP and processes each model' do
186
+ task = described_class.new({ models: ['courses', 'users'] }, {}, {})
169
187
  user_count = User.count
170
188
  course_count = Course.count
171
- subject.process('spec/support/fixtures/reports/provisioning_csv', { models: ['courses', 'users'] }, 1)
189
+ task.process('spec/support/fixtures/reports/provisioning_csv')
172
190
  expect(User.count).to eq(user_count + 2)
173
191
  expect(Course.count).to eq(course_count + 2)
174
192
  end
@@ -176,15 +194,19 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
176
194
 
177
195
  context 'legacy_support is true' do
178
196
  it 'uses the LegacyImporter' do
197
+ task = described_class.new({ models: ['users'], legacy_support: true }, {}, {})
179
198
  expect(User).to receive(:create_or_update_from_csv).at_least(:once)
180
- subject.process('spec/support/fixtures/reports/users.csv', { models: ['users'], legacy_support: true }, 1)
199
+ task.process('spec/support/fixtures/reports/users.csv')
181
200
  end
182
201
 
183
202
  it 'uses the LegacyImporter for specific models' do
203
+ task = described_class.new({ models: ['users'], legacy_support: ['users'] }, {}, {})
184
204
  expect(User).to receive(:create_or_update_from_csv).at_least(:once)
185
205
  expect(Course).to_not receive(:create_or_update_from_csv)
186
- subject.process('spec/support/fixtures/reports/users.csv', { models: ['users'], legacy_support: ['users'] }, 1)
187
- subject.process('spec/support/fixtures/reports/courses.csv', { models: ['courses'], legacy_support: ['users'] }, 1)
206
+ task.process('spec/support/fixtures/reports/users.csv')
207
+
208
+ task = described_class.new({ models: ['courses'], legacy_support: ['users'] }, {}, {})
209
+ task.process('spec/support/fixtures/reports/courses.csv')
188
210
  end
189
211
  end
190
212
  end
@@ -1,12 +1,11 @@
1
1
  require "spec_helper"
2
2
 
3
- RSpec.describe CanvasSync::Processors::RubricAssessmentsProcessor do
4
- let(:subject) { CanvasSync::Processors::RubricAssessmentsProcessor }
5
-
3
+ RSpec.describe CanvasSync::Jobs::SyncRubricAssessmentsJob do
6
4
  describe "#process" do
7
5
  it 'processes rubric assessments' do
6
+ task = described_class.new({}, {}, {})
8
7
  expect {
9
- subject.process('spec/support/fixtures/reports/rubric_assessments.csv', { models: ['rubric_assessments'] }, 1)
8
+ task.process('spec/support/fixtures/reports/rubric_assessments.csv')
10
9
  }.to change { RubricAssessment.count }.by(2)
11
10
  rubric_assessment = RubricAssessment.first
12
11
  expect(rubric_assessment.canvas_rubric_association_id).to eq(1)
@@ -1,12 +1,11 @@
1
1
  require "spec_helper"
2
2
 
3
- RSpec.describe CanvasSync::Processors::RubricAssociationsProcessor do
4
- let(:subject) { CanvasSync::Processors::RubricAssociationsProcessor }
5
-
3
+ RSpec.describe CanvasSync::Jobs::SyncRubricAssociationsJob do
6
4
  describe "#process" do
7
5
  it 'processes rubric associations' do
6
+ task = described_class.new({}, {}, {})
8
7
  expect {
9
- subject.process('spec/support/fixtures/reports/rubric_associations.csv', { models: ['rubric_associations'] }, 1)
8
+ task.process('spec/support/fixtures/reports/rubric_associations.csv')
10
9
  }.to change { RubricAssociation.count }.by(2)
11
10
  rubric_association = RubricAssociation.first
12
11
  expect(rubric_association.title).to eq("Rubric Association Title")
@@ -1,12 +1,11 @@
1
1
  require "spec_helper"
2
2
 
3
- RSpec.describe CanvasSync::Processors::RubricsProcessor do
4
- let(:subject) { CanvasSync::Processors::RubricsProcessor }
5
-
3
+ RSpec.describe CanvasSync::Jobs::SyncRubricsJob do
6
4
  describe "#process" do
7
5
  it 'inserts rubrics' do
6
+ task = described_class.new({}, {}, {})
8
7
  expect {
9
- subject.process('spec/support/fixtures/reports/rubrics.csv', { models: ['rubrics'] }, 1)
8
+ task.process('spec/support/fixtures/reports/rubrics.csv')
10
9
  }.to change { Rubric.count }.by(2)
11
10
  rubric = Rubric.first
12
11
  expect(rubric.title).to eq("Assignment 1")
@@ -1,12 +1,11 @@
1
1
  require "spec_helper"
2
2
 
3
- RSpec.describe CanvasSync::Processors::SubmissionsProcessor do
4
- let(:subject) { CanvasSync::Processors::SubmissionsProcessor }
5
-
3
+ RSpec.describe CanvasSync::Jobs::SyncSubmissionsJob do
6
4
  describe "#process" do
7
5
  it "inserts submissions" do
6
+ task = described_class.new({}, {}, {})
8
7
  expect {
9
- subject.process("spec/support/fixtures/reports/submissions.csv", {}, 1)
8
+ task.process("spec/support/fixtures/reports/submissions.csv")
10
9
  }.to change { Submission.count }.by(2)
11
10
  end
12
11
  end
@@ -1,6 +1,6 @@
1
1
  FactoryBot.define do
2
2
  factory :account do
3
- canvas_id { SecureRandom.random_number(100_000_000) }
3
+ sequence(:canvas_id) { |n| n }
4
4
  sis_id { SecureRandom.hex }
5
5
  canvas_parent_account_id { 1 }
6
6
  sis_parent_account_id { SecureRandom.hex }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canvas_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.26.1
4
+ version: 0.27.1.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Instructure CustomDev
@@ -534,10 +534,12 @@ files:
534
534
  - lib/canvas_sync/importers/legacy_importer.rb
535
535
  - lib/canvas_sync/job.rb
536
536
  - lib/canvas_sync/jobs/begin_sync_chain_job.rb
537
+ - lib/canvas_sync/jobs/beta_cleanup/create_temp_tables_job.rb
538
+ - lib/canvas_sync/jobs/beta_cleanup/delete_related_records_job.rb
539
+ - lib/canvas_sync/jobs/beta_cleanup/delete_temp_tables_job.rb
537
540
  - lib/canvas_sync/jobs/canvas_process_waiter.rb
538
- - lib/canvas_sync/jobs/report_checker.rb
539
- - lib/canvas_sync/jobs/report_processor_job.rb
540
541
  - lib/canvas_sync/jobs/report_starter.rb
542
+ - lib/canvas_sync/jobs/report_sync_task.rb
541
543
  - lib/canvas_sync/jobs/sync_accounts_job.rb
542
544
  - lib/canvas_sync/jobs/sync_admins_job.rb
543
545
  - lib/canvas_sync/jobs/sync_assignment_groups_job.rb
@@ -561,41 +563,21 @@ files:
561
563
  - lib/canvas_sync/live_events/base_handler.rb
562
564
  - lib/canvas_sync/live_events/process_event_job.rb
563
565
  - lib/canvas_sync/misc_helper.rb
564
- - lib/canvas_sync/processors/assignment_groups_processor.rb
565
- - lib/canvas_sync/processors/assignment_overrides_processor.rb
566
- - lib/canvas_sync/processors/assignments_processor.rb
567
- - lib/canvas_sync/processors/content_migrations_processor.rb
568
- - lib/canvas_sync/processors/context_module_items_processor.rb
569
- - lib/canvas_sync/processors/context_modules_processor.rb
570
- - lib/canvas_sync/processors/course_completion_report_processor.rb
571
566
  - lib/canvas_sync/processors/model_mappings.yml
572
567
  - lib/canvas_sync/processors/normal_processor.rb
573
- - lib/canvas_sync/processors/provisioning_report_processor.rb
574
568
  - lib/canvas_sync/processors/report_processor.rb
575
- - lib/canvas_sync/processors/rubric_assessments_processor.rb
576
- - lib/canvas_sync/processors/rubric_associations_processor.rb
577
- - lib/canvas_sync/processors/rubrics_processor.rb
578
- - lib/canvas_sync/processors/submissions_processor.rb
579
569
  - lib/canvas_sync/record.rb
580
570
  - lib/canvas_sync/sidekiq_job.rb
581
571
  - lib/canvas_sync/version.rb
582
572
  - spec/canvas_sync/canvas_sync_spec.rb
583
573
  - spec/canvas_sync/jobs/canvas_process_waiter_spec.rb
584
574
  - spec/canvas_sync/jobs/job_spec.rb
585
- - spec/canvas_sync/jobs/report_checker_spec.rb
586
- - spec/canvas_sync/jobs/report_processor_job_spec.rb
587
575
  - spec/canvas_sync/jobs/report_starter_spec.rb
576
+ - spec/canvas_sync/jobs/report_sync_task_spec.rb
588
577
  - spec/canvas_sync/jobs/sync_admins_job_spec.rb
589
- - spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb
590
- - spec/canvas_sync/jobs/sync_assignments_job_spec.rb
591
- - spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb
592
- - spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb
593
- - spec/canvas_sync/jobs/sync_context_modules_job_spec.rb
594
578
  - spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb
595
579
  - spec/canvas_sync/jobs/sync_roles_job_spec.rb
596
- - spec/canvas_sync/jobs/sync_scores_job_spec.rb
597
580
  - spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
598
- - spec/canvas_sync/jobs/sync_submissions_job_spec.rb
599
581
  - spec/canvas_sync/jobs/sync_terms_job_spec.rb
600
582
  - spec/canvas_sync/live_events/live_event_sync_spec.rb
601
583
  - spec/canvas_sync/live_events/live_events_controller_spec.rb
@@ -783,20 +765,12 @@ test_files:
783
765
  - spec/canvas_sync/canvas_sync_spec.rb
784
766
  - spec/canvas_sync/jobs/canvas_process_waiter_spec.rb
785
767
  - spec/canvas_sync/jobs/job_spec.rb
786
- - spec/canvas_sync/jobs/report_checker_spec.rb
787
- - spec/canvas_sync/jobs/report_processor_job_spec.rb
788
768
  - spec/canvas_sync/jobs/report_starter_spec.rb
769
+ - spec/canvas_sync/jobs/report_sync_task_spec.rb
789
770
  - spec/canvas_sync/jobs/sync_admins_job_spec.rb
790
- - spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb
791
- - spec/canvas_sync/jobs/sync_assignments_job_spec.rb
792
- - spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb
793
- - spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb
794
- - spec/canvas_sync/jobs/sync_context_modules_job_spec.rb
795
771
  - spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb
796
772
  - spec/canvas_sync/jobs/sync_roles_job_spec.rb
797
- - spec/canvas_sync/jobs/sync_scores_job_spec.rb
798
773
  - spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
799
- - spec/canvas_sync/jobs/sync_submissions_job_spec.rb
800
774
  - spec/canvas_sync/jobs/sync_terms_job_spec.rb
801
775
  - spec/canvas_sync/live_events/live_event_sync_spec.rb
802
776
  - spec/canvas_sync/live_events/live_events_controller_spec.rb
@@ -1,108 +0,0 @@
1
- module CanvasSync
2
- module Jobs
3
- # ActiveJob class used to check the status of a pending Canvas report.
4
- # Re-enqueues itself if the report is still processing on Canvas.
5
- # Enqueues the ReportProcessor when the report has completed.
6
- class ReportChecker < CanvasSync::Job
7
- REPORT_TIMEOUT = 24.hours
8
- COMPILATION_TIMEOUT = 3.hours
9
- MAX_TRIES = 3
10
-
11
- class FatalReportError < ::RuntimeError; end
12
-
13
- discard_on FatalReportError
14
-
15
- # @param report_name [Hash] e.g., 'provisioning_csv'
16
- # @param report_id [Integer]
17
- # @param processor [String] a stringified report processor class name
18
- # @param options [Hash] hash of options that will be passed to the job processor
19
- # @return [nil]
20
- def perform(report_name, report_id, processor, options, checker_context = {}) # rubocop:disable Metrics/AbcSize
21
- max_tries = options[:report_max_tries] || batch_context[:report_max_tries] || MAX_TRIES
22
- account_id = options[:account_id] || batch_context[:account_id] || "self"
23
- report_status = CanvasSync.get_canvas_sync_client(batch_context)
24
- .report_status(account_id, report_name, report_id)
25
-
26
- case report_status["status"].downcase
27
- when "complete"
28
- CanvasSync::Jobs::ReportProcessorJob.perform_later(
29
- report_name,
30
- report_status["attachment"]["url"],
31
- processor,
32
- options,
33
- report_id,
34
- )
35
- when "error", "deleted"
36
- checker_context[:failed_attempts] ||= 0
37
- checker_context[:failed_attempts] += 1
38
- failed_attempts = checker_context[:failed_attempts]
39
- message = "Report failed to process; status was #{report_status} for report_name: #{report_name}, report_id: #{report_id}, #{current_organization.name}. This report has now failed #{checker_context[:failed_attempts]} time." # rubocop:disable Metrics/LineLength
40
- Rails.logger.error(message)
41
- if failed_attempts >= max_tries
42
- Rails.logger.error("This report has failed #{failed_attempts} times. Giving up.")
43
- raise FatalReportError, message
44
- else
45
- restart_report(options, report_name, processor, checker_context)
46
- end
47
- else
48
- report_timeout = parse_timeout(options[:report_timeout] || batch_context[:report_timeout] || REPORT_TIMEOUT)
49
- if timeout_met?(options[:sync_start_time], report_timeout)
50
- raise FatalReportError, "Report appears to be stuck #{report_name}##{report_id}"
51
- end
52
-
53
- if report_status["status"].downcase == 'compiling'
54
- checker_context['compiling_since'] ||= DateTime.now.iso8601
55
- compilation_timeout = parse_timeout(options[:report_compilation_timeout] || batch_context[:report_compilation_timeout] || COMPILATION_TIMEOUT)
56
- if timeout_met?(checker_context['compiling_since'], compilation_timeout)
57
- raise FatalReportError, "Report appears to be stuck #{report_name}##{report_id}"
58
- end
59
- end
60
-
61
- CanvasSync::Jobs::ReportChecker
62
- .set(wait: report_checker_wait_time)
63
- .perform_later(
64
- report_name,
65
- report_id,
66
- processor,
67
- options,
68
- checker_context
69
- )
70
- end
71
- end
72
-
73
- protected
74
-
75
- def timeout_met?(base_time, timeout_length)
76
- return false unless base_time.present? && timeout_length.present?
77
- DateTime.now > (DateTime.parse(base_time) + timeout_length)
78
- end
79
-
80
- def parse_timeout(val)
81
- val
82
- end
83
-
84
- def restart_report(options, report_name, processor, checker_context)
85
- account_id = options[:account_id] || batch_context[:account_id] || "self"
86
- options[:sync_start_time] = DateTime.now.utc.iso8601
87
- new_context = {}
88
- new_context[:failed_attempts] = checker_context[:failed_attempts]
89
- report_id = start_report(account_id, report_name, options[:report_params])
90
- CanvasSync::Jobs::ReportChecker
91
- .set(wait: report_checker_wait_time)
92
- .perform_later(
93
- report_name,
94
- report_id,
95
- processor,
96
- options,
97
- new_context
98
- )
99
- end
100
-
101
- def start_report(account_id, report_name, report_params)
102
- report = CanvasSync.get_canvas_sync_client(batch_context)
103
- .start_report(account_id, report_name, report_params)
104
- report["id"]
105
- end
106
- end
107
- end
108
- end
@@ -1,35 +0,0 @@
1
- require "open-uri"
2
-
3
- module CanvasSync
4
- module Jobs
5
- # ActiveJob class that wraps around a report processor. This job will
6
- # download the report, and then pass the file path and options into the
7
- # process method on the processor.
8
- class ReportProcessorJob < CanvasSync::Job
9
- # @param report_name [Hash] e.g., 'provisioning_csv'
10
- # @param report_url [String]
11
- # @param processor [String] a stringified report processor class name
12
- # @param options [Hash] hash of options that will be passed to the job processor
13
- # @return [nil]
14
- def perform(report_name, report_url, processor, options, report_id)
15
- @job_log.update(job_class: processor)
16
- download(report_name, report_url) do |file_path|
17
- options = batch_context.merge(options).merge({
18
- report_processor_job_id: @job_log.job_id
19
- })
20
- processor.constantize.process(file_path, options, report_id)
21
- end
22
- end
23
-
24
- private
25
-
26
- def download(report_name, report_url)
27
- Dir.mktmpdir do |dir|
28
- file_path = "#{dir}/#{report_name}"
29
- canvas_sync_client.download_report(report_url, file_path)
30
- yield file_path
31
- end
32
- end
33
- end
34
- end
35
- end
@@ -1,19 +0,0 @@
1
- require_relative "./report_processor"
2
-
3
- module CanvasSync
4
- module Processors
5
- # Processes a assignment_groups report using the bulk importer.
6
- #
7
- # @param report_file_path [String]
8
- # @param options [Hash]
9
- class AssignmentGroupsProcessor < ReportProcessor
10
- def self.process(report_file_path, _options, report_id)
11
- new(report_file_path, _options)
12
- end
13
-
14
- def initialize(report_file_path, options)
15
- do_bulk_import(report_file_path, AssignmentGroup, options: options)
16
- end
17
- end
18
- end
19
- end
@@ -1,41 +0,0 @@
1
- require_relative "./report_processor"
2
-
3
- module CanvasSync
4
- module Processors
5
- # Processes a assignment overrides report using the bulk importer.
6
- #
7
- # @param report_file_path [String]
8
- # @param options [Hash]
9
- class AssignmentOverridesProcessor < ReportProcessor
10
- # Class method that starts processing (for consistent interface with other processors).
11
- def self.process(report_file_path, options, report_id)
12
- new(report_file_path, options)
13
- end
14
-
15
- def initialize(report_file_path, options)
16
- do_bulk_import(report_file_path, AssignmentOverride, options: options) do |row|
17
- # Handle transforms here instead of in mappings
18
- row[:student_ids] = parse_student_ids(row[:student_ids])
19
-
20
- # Convert empty/null/'0' values to nil
21
- # For Ruby 2.7
22
- row[:group_id] = parse_nil_value(row[:group_id])
23
- row[:course_section_id] = parse_nil_value(row[:course_section_id])
24
- row
25
- end
26
- end
27
-
28
- private
29
-
30
- def parse_student_ids(value)
31
- value.present? ? JSON.parse(value) : nil
32
- end
33
-
34
- def parse_nil_value(value)
35
- # Convert "0", "null", or empty string to nil
36
- return nil if %w[0 null].include?(value) || value == ''
37
- value
38
- end
39
- end
40
- end
41
- end
@@ -1,19 +0,0 @@
1
- require_relative "./report_processor"
2
-
3
- module CanvasSync
4
- module Processors
5
- # Processes an assignments report using the bulk importer.
6
- #
7
- # @param report_file_path [String]
8
- # @param options [Hash]
9
- class AssignmentsProcessor < ReportProcessor
10
- def self.process(report_file_path, _options, report_id)
11
- new(report_file_path, _options)
12
- end
13
-
14
- def initialize(report_file_path, options)
15
- do_bulk_import(report_file_path, Assignment, options: options)
16
- end
17
- end
18
- end
19
- end
@@ -1,19 +0,0 @@
1
- require_relative "./report_processor"
2
-
3
- module CanvasSync
4
- module Processors
5
- # Processes a content migrations report using the bulk importer.
6
- #
7
- # @param report_file_path [String]
8
- # @param options [Hash]
9
- class ContentMigrationsProcessor < ReportProcessor
10
- def self.process(report_file_path, _options, report_id)
11
- new(report_file_path, _options)
12
- end
13
-
14
- def initialize(report_file_path, options)
15
- do_bulk_import(report_file_path, ContentMigration, options: options)
16
- end
17
- end
18
- end
19
- end
@@ -1,19 +0,0 @@
1
- require_relative "./report_processor"
2
-
3
- module CanvasSync
4
- module Processors
5
- # Processes a context modules report using the bulk importer.
6
- #
7
- # @param report_file_path [String]
8
- # @param options [Hash]
9
- class ContextModuleItemsProcessor < ReportProcessor
10
- def self.process(report_file_path, _options, report_id)
11
- new(report_file_path, _options)
12
- end
13
-
14
- def initialize(report_file_path, options)
15
- do_bulk_import(report_file_path, ContextModuleItem, options: options)
16
- end
17
- end
18
- end
19
- end
@@ -1,19 +0,0 @@
1
- require_relative "./report_processor"
2
-
3
- module CanvasSync
4
- module Processors
5
- # Processes a context modules report using the bulk importer.
6
- #
7
- # @param report_file_path [String]
8
- # @param options [Hash]
9
- class ContextModulesProcessor < ReportProcessor
10
- def self.process(report_file_path, _options, report_id)
11
- new(report_file_path, _options)
12
- end
13
-
14
- def initialize(report_file_path, options)
15
- do_bulk_import(report_file_path, ContextModule, options: options)
16
- end
17
- end
18
- end
19
- end