canvas_sync 0.22.6 → 0.22.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61d4f6b7e0c7f8201ee2dccdeea7e9f3149f112d35ea4ab72903ddbee892c079
4
- data.tar.gz: 72a6a5553aa892680ee6ce2dacba9ce98d200cc44bd17a40dc5648b028b63868
3
+ metadata.gz: '0882011929080b4e55e1798ae3639c4431a583dd2a31634b2b9c2ba5f450fcb4'
4
+ data.tar.gz: 7a339eef193de9b640b3d68d5474a7771d363f7dee723be49da33cf319afe610
5
5
  SHA512:
6
- metadata.gz: 5eb771935ecaa392a2fd6442136cadbe7972912381de6028c145de4e45419904de56a694a636dde1cabcbfda67fbeedfdcecd38993031194dab85f75ed529b98
7
- data.tar.gz: fd8a0c64457a2190783527dcbfff67d34ec17f6f9249b1e0f4147a0e3ef8d5b9ae66ad4e132982b341ace536db78f39b95dbd5c7447f6099d765b83c8ef897ce
6
+ metadata.gz: a54b1779112dce3d106a503cc720b74d5b54ed2688c95c9d2c3523024813a0ac34d144417a8959bc81561dc4f78a7cf9914dd124037c85376a8a35b455bd5be1
7
+ data.tar.gz: 74e8b3e7d9317bbc2bbd7f902cfbedeabfd826ddbfd70aa4c8bf57c6f05dc2f4176f7bf2c0cc0352adae4ecaa4978f57f02fc3dcbbed8d1d8130df58bbaea51d
@@ -40,14 +40,17 @@ module CanvasSync::Concerns
40
40
  options = { validate: false, on_duplicate_key_update: update_conditions }.merge(import_args)
41
41
 
42
42
  if all_pages
43
- batcher = CanvasSync::BatchProcessor.new(of: batch_size) do |batch|
44
- import(columns, batch, options)
43
+ enumer = api_array.all_pages_each.lazy
44
+
45
+ # Map the API response to instances of this model
46
+ enumer = enumer.map do |api_item|
47
+ new.assign_from_api_params(api_item)
45
48
  end
46
- api_array.all_pages_each do |api_item|
47
- item = new.assign_from_api_params(api_item)
48
- batcher << item
49
+
50
+ # Import in batches
51
+ enumer.each_slice(batch_size) do |batch|
52
+ import(columns, batch, options)
49
53
  end
50
- batcher.flush
51
54
  else
52
55
  items = api_array.map do |api_item|
53
56
  new.assign_from_api_params(api_item)
@@ -51,10 +51,11 @@ module CanvasSync::Concerns
51
51
  m = maps[mname] = {}
52
52
 
53
53
  m[:conflict_target] = Array(legacy[:conflict_target]).map(&:to_sym).map do |lct|
54
- legacy[:report_columns][lct][:database_column_name]
54
+ legacy[:report_columns]&.[](lct)&.[](:database_column_name)
55
55
  end
56
56
 
57
57
  m[:columns] = {}
58
+
58
59
  legacy[:report_columns].each do |rcol, opts|
59
60
  m[:columns][opts[:database_column_name]] = opts.except(:database_column_name).merge!(
60
61
  report_column: rcol,
@@ -68,6 +69,15 @@ module CanvasSync::Concerns
68
69
  def self.default_v1_mappings
69
70
  @legacy_mappings ||= begin
70
71
  mapping = YAML.load_file(File.join(__dir__, '../processors', "model_mappings.yml")).deep_symbolize_keys!
72
+ # Default columns can be excluded if the table has not been migrated to accept them
73
+ mapping.each do |mname, legacy|
74
+ legacy[:report_columns].select! do |rcol, opts|
75
+ model = mname.to_s&.classify&.safe_constantize
76
+ # we need to make sure this is a model otherwise they will be systematically removed - some mappings are not models (e.g xlists)
77
+ model.present? && !model.column_names.include?(opts[:database_column_name].to_s) ? false : true
78
+ end
79
+ end
80
+
71
81
  override_filepath = Rails.root.join("config/canvas_sync_provisioning_mapping.yml")
72
82
 
73
83
  if File.file?(override_filepath)
@@ -13,6 +13,7 @@ class CreateEnrollments < ActiveRecord::Migration[5.1]
13
13
  t.bigint :canvas_section_id
14
14
  t.string :workflow_state
15
15
  t.string :base_role_type
16
+ t.datetime :completed_at
16
17
 
17
18
  t.timestamps
18
19
  end
@@ -23,7 +23,7 @@ module CanvasSync
23
23
  end
24
24
  end
25
25
 
26
- def self.perform_in_batches(report_file_path, raw_mapping, klass, conflict_target, import_args: {})
26
+ def self.perform_in_batches(report_file_path, raw_mapping, klass, conflict_target, import_args: {}, &block)
27
27
  mapping = {}.with_indifferent_access
28
28
  raw_mapping.each do |db_col, opts|
29
29
  next if opts[:deprecated] && !klass.column_names.include?(db_col.to_s)
@@ -37,14 +37,27 @@ module CanvasSync
37
37
  conflict_target = Array(conflict_target).map(&:to_s)
38
38
  conflict_target_indices = conflict_target.map{|ct| database_column_names.index(ct) }
39
39
 
40
- row_ids = {}
41
- batcher = CanvasSync::BatchProcessor.new(of: batch_size) do |batch|
42
- row_ids = {}
43
- perform_import(klass, database_column_names, batch, conflict_target, import_args)
40
+ enumer = CSV.foreach(report_file_path, headers: true, header_converters: :symbol).lazy
41
+
42
+ # Optionally filter rows by a passed block
43
+ if block
44
+ enumer = enumer.filter_map do |row|
45
+ catch :skip do
46
+ block.call(row)
47
+ end
48
+ end
49
+ end
50
+
51
+ # Optionally chunk by a computed value. Mainly so we can group duplicate rows and choose one
52
+ chunker = nil
53
+ chunker = UserChunker.new if defined?(User) && klass == User && csv_column_names.include?('user_id')
54
+ if chunker
55
+ enumer = enumer.chunk{|row| chunker.key(row) }.flat_map{|key, rows| chunker.choose(key, rows) }
44
56
  end
45
57
 
46
- row_buffer_out = ->(row) {
47
- formatted_row = mapping.map do |db_col, col_def|
58
+ # Prepare the rows for import
59
+ enumer = enumer.map do |row|
60
+ mapping.map do |db_col, col_def|
48
61
  value = nil
49
62
  value = row[col_def[:report_column]] if col_def[:report_column]
50
63
 
@@ -63,33 +76,25 @@ module CanvasSync
63
76
 
64
77
  value
65
78
  end
79
+ end
66
80
 
67
- if conflict_target.present?
68
- key = conflict_target_indices.map{|ct| formatted_row[ct] }
69
- next if row_ids[key]
70
-
81
+ # Reject rows within a single batch that have the same ID
82
+ row_ids = nil
83
+ if conflict_target.present?
84
+ enumer = enumer.reject do |row|
85
+ key = conflict_target_indices.map{|ct| row[ct] }
86
+ skip = row_ids[key]
71
87
  row_ids[key] = true
88
+ skip
72
89
  end
73
-
74
- batcher << formatted_row
75
- }
76
-
77
- row_buffer = nil
78
- if defined?(User) && klass == User && csv_column_names.include?('user_id')
79
- row_buffer = UserRowBuffer.new(&row_buffer_out)
80
- else
81
- row_buffer = NullRowBuffer.new(&row_buffer_out)
82
90
  end
83
91
 
84
- CSV.foreach(report_file_path, headers: true, header_converters: :symbol) do |row|
85
- row = yield(row) if block_given?
86
- next if row.nil?
87
-
88
- row_buffer << row
92
+ # Start importing
93
+ row_ids = {}
94
+ enumer.each_slice(batch_size) do |batch|
95
+ perform_import(klass, database_column_names, batch, conflict_target, import_args)
96
+ row_ids = {}
89
97
  end
90
-
91
- row_buffer.flush
92
- batcher.flush
93
98
  end
94
99
 
95
100
  def self.perform_import(klass, columns, rows, conflict_target, import_args={})
@@ -157,52 +162,17 @@ module CanvasSync
157
162
  batch_size > 0 ? batch_size : DEFAULT_BATCH_SIZE
158
163
  end
159
164
 
160
- class RowBuffer
161
- def initialize(&block)
162
- @flush_out = block
163
- @buffered_rows = []
164
- end
165
-
166
- def <<(v)
167
- @buffered_rows << v
168
- end
169
-
170
- def flush(value = @buffered_rows)
171
- if value.is_a?(Array)
172
- value.each do |v|
173
- @flush_out.call(v)
174
- end
175
- else
176
- @flush_out.call(value)
177
- end
178
- @buffered_rows = []
179
- end
180
- end
181
-
182
- class NullRowBuffer
183
- def initialize(&block)
184
- @flush_out = block
185
- end
186
-
187
- def <<(v)
188
- @flush_out.call(v)
189
- end
190
-
191
- def flush; end
192
- end
193
-
194
165
  # Ensures that, if a User has multiple rows, one with a SIS ID is preferred.
195
166
  # This is mainly to fix issues in legacy apps - the suggested approach for new apps
196
167
  # is to sync and use the Pseudonymes table
197
- class UserRowBuffer < RowBuffer
198
- def <<(v)
199
- flush if @buffered_rows[0] && @buffered_rows[0][:canvas_user_id] != v[:canvas_user_id]
200
- super
168
+ class UserChunker
169
+ def key(row)
170
+ row[:canvas_user_id]
201
171
  end
202
172
 
203
- def flush
204
- row = @buffered_rows.find{|r| r[:user_id].present? } || @buffered_rows.last
205
- super(row.present? ? [row] : [])
173
+ def choose(key, rows)
174
+ row = rows.find{|r| r[:user_id].present? } || rows.last
175
+ row.present? ? [row] : []
206
176
  end
207
177
  end
208
178
  end
File without changes
@@ -337,7 +337,7 @@ module CanvasSync::JobBatches
337
337
  trigger_callback.call(:complete)
338
338
  end
339
339
 
340
- if all_successful # All Successfull
340
+ if all_successful # All Successful
341
341
  trigger_callback.call(:success)
342
342
  elsif pending_jobs == dead_jobs && pending_batches == stagnated_batches # Stagnated
343
343
  trigger_callback.call(:stagnated)
@@ -4,9 +4,7 @@ module CanvasSync::JobBatches
4
4
 
5
5
  attr_reader :base_job
6
6
 
7
- def initialize(base_type = SerialBatchJob, chain_id: nil)
8
- @chain_id = chain_id || SecureRandom.urlsafe_base64(10)
9
-
7
+ def initialize(base_type = SerialBatchJob)
10
8
  if base_type.is_a?(Hash)
11
9
  @base_job = base_type
12
10
  @base_job[:args] ||= @base_job[:parameters] || []
@@ -111,7 +109,7 @@ module CanvasSync::JobBatches
111
109
  return nil if matching_jobs.count == 0
112
110
 
113
111
  job = matching_jobs[0][0]
114
- job = self.class.new(job, chain_id: @chain_id) unless job.is_a?(ChainBuilder)
112
+ job = self.class.new(job) unless job.is_a?(ChainBuilder)
115
113
  job
116
114
  end
117
115
 
@@ -120,7 +118,6 @@ module CanvasSync::JobBatches
120
118
  job_def.normalize!
121
119
  else
122
120
  job_def[:job] = job_def[:job].to_s
123
- job_def[:chain_link] ||= "#{@chain_id}-#{SecureRandom.urlsafe_base64(10)}"
124
121
  if (chain = self.class.get_chain_parameter(job_def, raise_error: false)).present?
125
122
  chain.map! { |sub_job| normalize!(sub_job) }
126
123
  end
@@ -141,7 +138,7 @@ module CanvasSync::JobBatches
141
138
  args: args,
142
139
  kwargs: kwargs,
143
140
  }
144
- self.class.new(hsh, chain_id: @chain_id).apply_block(&blk) if blk.present?
141
+ self.class.new(hsh).apply_block(&blk) if blk.present?
145
142
  hsh
146
143
  end
147
144
 
@@ -242,24 +239,6 @@ module CanvasSync::JobBatches
242
239
  job_class.perform_later(*job_args, **job_kwargs)
243
240
  end
244
241
  end
245
-
246
- def link_to_batch!(chain_link, batch)
247
- # Or make chains a separate entity - Chains show batches, but batches don't show chain?
248
- # Or "Annotate" a Batch with chain data - could extract chain id from any job entry
249
- end
250
-
251
- def annotate_batch!(batch, chain)
252
-
253
- end
254
-
255
- def handle_step_complete(status, opts)
256
- chain_link = opts[:chain_link]
257
- chain_id, chain_step_id = chain_link.split('-')
258
-
259
- CanvasSync::JobBatches::Batch.redis.multi do |r|
260
- r.hset("CHAIN-#{chain_id}-steps", chain_step_id, "complete")
261
- end
262
- end
263
242
  end
264
243
  end
265
244
 
@@ -144,10 +144,6 @@ module CanvasSync::JobBatches
144
144
  if next_job[:chain_link].present?
145
145
  # Annotate Batch with chain-step info
146
146
  batch.context["csb:chain_link"] = next_job[:chain_link]
147
- # TODO Add Fiber Batch to chain-link
148
- # With the exception of the top of the Chain, all nested ManagedBatch Roots should be within a Fiber,
149
- # so we shouldn't really need to make the Root checkin with the chain
150
- # ...except to cleanup the chain
151
147
  batch.on(:complete, "#{ChainBuilder.to_s}.chain_step_complete", chain_link: next_job[:chain_link])
152
148
  end
153
149
 
@@ -49,7 +49,6 @@ module CanvasSync::JobBatches
49
49
  end
50
50
 
51
51
  def success?
52
- # TODO (Race Condition) This might not be valid if checked from a :complete callback
53
52
  'true' == Batch.redis { |r| r.hget("BID-#{bid}", 'success') }
54
53
  end
55
54
 
@@ -6,6 +6,8 @@ module CanvasSync::JobUniqueness
6
6
  context_class.new(data, **kwargs)
7
7
  end
8
8
 
9
+ attr_reader :lock_id
10
+
9
11
  # { job_clazz, jid, queue, args?, kwargs?, base_key? }
10
12
  def initialize(data, job_instance: nil, config: nil)
11
13
  @base_key = data[:base_key]
@@ -14,9 +16,7 @@ module CanvasSync::JobUniqueness
14
16
  @config = config || @context_data[:config]
15
17
 
16
18
  # TODO Consider (somewhere) updating the lock_id to the BID of the wrapping Batch (when applicable)
17
- @lock_id ||= data[:lid] || Thread.current[:unique_jobs_previous_context]&.lock_id
18
- @lock_id_locked = @lock_id.present?
19
- @lock_id ||= job_id
19
+ @lock_id ||= data[:lid] || Thread.current[:unique_jobs_previous_context]&.lock_id || job_id
20
20
  end
21
21
 
22
22
  # This is primarily for rehydrating in a Batch Callback, so it is unlikely that args and kwargs are needed.
@@ -84,18 +84,6 @@ module CanvasSync::JobUniqueness
84
84
  end
85
85
  end
86
86
 
87
- def lock_id
88
- @lock_id_locked = true
89
- @lock_id
90
- end
91
-
92
- def lock_id=(new_id)
93
- raise "Lock ID already set" if @lock_id_locked
94
- return unless new_id.present?
95
- @lock_id = new_id
96
- @lock_id_locked = true
97
- end
98
-
99
87
  def job_id
100
88
  @context_data[:jid]
101
89
  end
@@ -12,17 +12,14 @@ module CanvasSync
12
12
  # Override the delta-syncing date if:
13
13
  # 1. the Term hasn't been synced before or
14
14
  # 2. the Term underwent a period of not syncing
15
+ term_last_sync = CanvasSync.redis.get(self.class.last_sync_key(term_id))
15
16
  if batch_context[:updated_after]
16
- term_last_sync = CanvasSync.redis.get(self.class.last_sync_key(term_id))
17
17
  if !term_last_sync.present? || batch_context[:updated_after] > term_last_sync
18
18
  local_context[:updated_after] = term_last_sync.presence
19
19
  end
20
20
  end
21
21
 
22
22
  JobBatches::ManagedBatchJob.make_batch(jobs, ordered: false, concurrency: true) do |b|
23
- # TODO If we do a Chain UI, this will need to checkin somehow to indicate that the chain forked
24
- # Or chain steps just show a summary - eg "Started", "X Jobs Running", "Done" or "X Jobs Running, Y Jobs Done" - and not individual forks
25
- # For a step to be considered done, all previous sibling-level steps must be done and no batches pending
26
23
  b.description = "TermBatchJob(#{term_id}) Root"
27
24
  b.context = local_context
28
25
  b.on(:success, "#{self.class.to_s}.batch_finished") unless options[:mark_synced] == false
@@ -159,6 +159,9 @@ enrollments:
159
159
  base_role_type:
160
160
  database_column_name: base_role_type
161
161
  type: string
162
+ completed_at:
163
+ database_column_name: completed_at
164
+ type: datetime
162
165
 
163
166
  sections:
164
167
  conflict_target: canvas_section_id
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.22.6".freeze
2
+ VERSION = "0.22.8".freeze
3
3
  end
@@ -2,6 +2,18 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe CanvasSync do
4
4
  describe '.provisioning_sync' do
5
+ it 'invokes the first job in the queue and passes on the rest of the job chain' do
6
+ expected_job_chain = CanvasSync.default_provisioning_report_chain(['courses'], term_scope: nil).normalize![:args][0]
7
+
8
+ expect(CanvasSync::Jobs::BeginSyncChainJob).to receive(:perform_later)
9
+ .with(
10
+ expected_job_chain,
11
+ anything
12
+ )
13
+
14
+ CanvasSync.provisioning_sync(['courses'])
15
+ end
16
+
5
17
  context 'an invalid model is passed in' do
6
18
  it 'raises a helpful exception' do
7
19
  expect {
@@ -18,25 +30,22 @@ RSpec.describe CanvasSync do
18
30
  provisioning: { c: 3 },
19
31
  global: { d: 4 },
20
32
  })
21
- expect(chain.normalize!).to match({
33
+ expect(chain.normalize!).to eq({
22
34
  :job => "CanvasSync::Jobs::BeginSyncChainJob",
23
- :chain_link=>String,
24
35
  :args => [
25
36
  [
26
37
  {
27
38
  :job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
28
- :chain_link=>String,
29
39
  :args=>[
30
40
  [
31
- {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["users"], :b=>2}},
41
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users"], :b=>2}},
32
42
  {
33
43
  :job=>"CanvasSync::Jobs::SyncTermsJob",
34
- :chain_link=>String,
35
44
  :args=>[],
36
45
  :kwargs=>{
37
46
  :term_scope=>"active",
38
47
  :sub_jobs=>[
39
- {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["courses"], :c=>3}},
48
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"], :c=>3}},
40
49
  ],
41
50
  },
42
51
  },
@@ -53,23 +62,20 @@ RSpec.describe CanvasSync do
53
62
  context 'we are syncing users with a term scope' do
54
63
  it 'syncs the users in a separate job that runs first' do
55
64
  chain = CanvasSync.default_provisioning_report_chain(['users', 'courses'], term_scope: :active)
56
- expect(chain.normalize!).to match({
65
+ expect(chain.normalize!).to eq({
57
66
  :job => "CanvasSync::Jobs::BeginSyncChainJob",
58
- :chain_link=>String,
59
67
  :args => [[
60
68
  {
61
69
  :job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
62
- :chain_link=>String,
63
70
  :args=>[
64
71
  [
65
- {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["users"]}},
72
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users"]}},
66
73
  {
67
74
  :job=>"CanvasSync::Jobs::SyncTermsJob",
68
- :chain_link=>String,
69
75
  :args=>[],
70
76
  :kwargs=>{
71
77
  :sub_jobs=>[
72
- {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["courses"]}}
78
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}
73
79
  ],
74
80
  :term_scope=>"active",
75
81
  }
@@ -87,20 +93,17 @@ RSpec.describe CanvasSync do
87
93
  context 'we are syncing users without a term scope' do
88
94
  it 'syncs users along with the rest of the provisioning report' do
89
95
  chain = CanvasSync.default_provisioning_report_chain(['users', 'courses'])
90
- expect(chain.normalize!).to match({
96
+ expect(chain.normalize!).to eq({
91
97
  :job => "CanvasSync::Jobs::BeginSyncChainJob",
92
- :chain_link=>String,
93
98
  :args => [[
94
99
  {
95
100
  :job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
96
- :chain_link=>String,
97
101
  :args=>[[
98
102
  {
99
103
  :job=>"CanvasSync::Jobs::SyncTermsJob",
100
- :chain_link=>String,
101
104
  :args=>[],
102
105
  :kwargs=>{
103
- :sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["users", "courses"]}}],
106
+ :sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "courses"]}}],
104
107
  :term_scope=>nil,
105
108
  }
106
109
  }
@@ -116,21 +119,18 @@ RSpec.describe CanvasSync do
116
119
  context 'we are syncing roles with a term scope' do
117
120
  it 'syncs the roles in a separate job that runs first' do
118
121
  chain = CanvasSync.default_provisioning_report_chain(['roles', 'courses'], term_scope: :active)
119
- expect(chain.normalize!).to match({
122
+ expect(chain.normalize!).to eq({
120
123
  :job => "CanvasSync::Jobs::BeginSyncChainJob",
121
- :chain_link=>String,
122
124
  :args => [[
123
125
  {
124
126
  :job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
125
- :chain_link=>String,
126
127
  :args=>[[
127
- {:job=>"CanvasSync::Jobs::SyncRolesJob", :chain_link=>String, :options=>{}},
128
+ {:job=>"CanvasSync::Jobs::SyncRolesJob", :options=>{}},
128
129
  {
129
130
  :job=>"CanvasSync::Jobs::SyncTermsJob",
130
- :chain_link=>String,
131
131
  :args=>[],
132
132
  :kwargs=>{
133
- :sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["courses"]}}],
133
+ :sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}],
134
134
  :term_scope=>"active",
135
135
  }
136
136
  },
@@ -146,21 +146,18 @@ RSpec.describe CanvasSync do
146
146
  context 'we are syncing roles without a term scope' do
147
147
  it 'syncs roles separately even with no term scope' do
148
148
  chain = CanvasSync.default_provisioning_report_chain(['roles', 'courses'])
149
- expect(chain.normalize!).to match({
149
+ expect(chain.normalize!).to eq({
150
150
  :job => "CanvasSync::Jobs::BeginSyncChainJob",
151
- :chain_link=>String,
152
151
  :args => [[
153
152
  {
154
153
  :job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
155
- :chain_link=>String,
156
154
  :args=>[[
157
- {:job=>"CanvasSync::Jobs::SyncRolesJob", :chain_link=>String, :options=>{}},
155
+ {:job=>"CanvasSync::Jobs::SyncRolesJob", :options=>{}},
158
156
  {
159
157
  :job=>"CanvasSync::Jobs::SyncTermsJob",
160
- :chain_link=>String,
161
158
  :args=>[],
162
159
  :kwargs=>{
163
- :sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["courses"]}}],
160
+ :sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}],
164
161
  :term_scope=>nil,
165
162
  }
166
163
  }
@@ -176,21 +173,18 @@ RSpec.describe CanvasSync do
176
173
  context 'we are syncing admins with a term scope' do
177
174
  it 'syncs the admins in a separate job that runs first' do
178
175
  chain = CanvasSync.default_provisioning_report_chain(['admins', 'courses'], term_scope: :active)
179
- expect(chain.normalize!).to match({
176
+ expect(chain.normalize!).to eq({
180
177
  :job => "CanvasSync::Jobs::BeginSyncChainJob",
181
- :chain_link=>String,
182
178
  :args => [[
183
179
  {
184
180
  :job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
185
- :chain_link=>String,
186
181
  :args=>[[
187
- {:job=>"CanvasSync::Jobs::SyncAdminsJob", :chain_link=>String, :options=>{}},
182
+ {:job=>"CanvasSync::Jobs::SyncAdminsJob", :options=>{}},
188
183
  {
189
184
  :job=>"CanvasSync::Jobs::SyncTermsJob",
190
- :chain_link=>String,
191
185
  :args=>[],
192
186
  :kwargs=>{
193
- :sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["courses"]}}],
187
+ :sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}],
194
188
  :term_scope=>"active"
195
189
  }
196
190
  }
@@ -206,21 +200,18 @@ RSpec.describe CanvasSync do
206
200
  context 'we are syncing admins without a term scope' do
207
201
  it 'syncs admins separately even with no term scope' do
208
202
  chain = CanvasSync.default_provisioning_report_chain(['admins', 'courses'])
209
- expect(chain.normalize!).to match({
203
+ expect(chain.normalize!).to eq({
210
204
  :job => "CanvasSync::Jobs::BeginSyncChainJob",
211
- :chain_link=>String,
212
205
  :args => [[
213
206
  {
214
207
  :job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
215
- :chain_link=>String,
216
208
  :args=>[[
217
- {:job=>"CanvasSync::Jobs::SyncAdminsJob", :chain_link=>String, :options=>{}},
209
+ {:job=>"CanvasSync::Jobs::SyncAdminsJob", :options=>{}},
218
210
  {
219
211
  :job=>"CanvasSync::Jobs::SyncTermsJob",
220
- :chain_link=>String,
221
212
  :args=>[],
222
213
  :kwargs=>{
223
- :sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["courses"]}}],
214
+ :sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}],
224
215
  :term_scope=>nil
225
216
  }
226
217
  }
@@ -237,22 +228,19 @@ RSpec.describe CanvasSync do
237
228
  it "appends the SyncAssignmentsJob" do
238
229
  chain = CanvasSync.default_provisioning_report_chain(%w[users enrollments assignments])
239
230
 
240
- expect(chain.normalize!).to match({
231
+ expect(chain.normalize!).to eq({
241
232
  :job => "CanvasSync::Jobs::BeginSyncChainJob",
242
- :chain_link=>String,
243
233
  :args => [[
244
234
  {
245
235
  :job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
246
- :chain_link=>String,
247
236
  :args=>[[
248
237
  {
249
238
  :job=>"CanvasSync::Jobs::SyncTermsJob",
250
- :chain_link=>String,
251
239
  :args=>[],
252
240
  :kwargs=>{
253
241
  :sub_jobs=>[
254
- {:job=>"CanvasSync::Jobs::SyncAssignmentsJob", :chain_link=>String, :options=>{}},
255
- {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["users", "enrollments"]}}
242
+ {:job=>"CanvasSync::Jobs::SyncAssignmentsJob", :options=>{}},
243
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "enrollments"]}}
256
244
  ],
257
245
  :term_scope=>nil
258
246
  }
@@ -270,22 +258,19 @@ RSpec.describe CanvasSync do
270
258
  it "appends the SyncSubmissionsJob" do
271
259
  chain = CanvasSync.default_provisioning_report_chain(%w[users enrollments submissions])
272
260
 
273
- expect(chain.normalize!).to match({
261
+ expect(chain.normalize!).to eq({
274
262
  :job => "CanvasSync::Jobs::BeginSyncChainJob",
275
- :chain_link=>String,
276
263
  :args => [[
277
264
  {
278
265
  :job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
279
- :chain_link=>String,
280
266
  :args=>[[
281
267
  {
282
268
  :job=>"CanvasSync::Jobs::SyncTermsJob",
283
- :chain_link=>String,
284
269
  :args=>[],
285
270
  :kwargs=>{
286
271
  :sub_jobs=>[
287
- {:job=>"CanvasSync::Jobs::SyncSubmissionsJob", :chain_link=>String, :options=>{}},
288
- {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["users", "enrollments"]}}
272
+ {:job=>"CanvasSync::Jobs::SyncSubmissionsJob", :options=>{}},
273
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "enrollments"]}}
289
274
  ],
290
275
  :term_scope=>nil
291
276
  }
@@ -303,22 +288,19 @@ RSpec.describe CanvasSync do
303
288
  it "appends the SyncAssignmentGroupsJob" do
304
289
  chain = CanvasSync.default_provisioning_report_chain(%w[users enrollments assignment_groups])
305
290
 
306
- expect(chain.normalize!).to match({
291
+ expect(chain.normalize!).to eq({
307
292
  :job => "CanvasSync::Jobs::BeginSyncChainJob",
308
- :chain_link=>String,
309
293
  :args => [[
310
294
  {
311
295
  :job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
312
- :chain_link=>String,
313
296
  :args=>[[
314
297
  {
315
298
  :job=>"CanvasSync::Jobs::SyncTermsJob",
316
- :chain_link=>String,
317
299
  :args=>[],
318
300
  :kwargs=>{
319
301
  :sub_jobs=>[
320
- {:job=>"CanvasSync::Jobs::SyncAssignmentGroupsJob", :chain_link=>String, :options=>{}},
321
- {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :chain_link=>String, :options=>{:models=>["users", "enrollments"]}}
302
+ {:job=>"CanvasSync::Jobs::SyncAssignmentGroupsJob", :options=>{}},
303
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "enrollments"]}}
322
304
  ],
323
305
  :term_scope=>nil
324
306
  }
@@ -12,6 +12,10 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
12
12
 
13
13
  context "with User#sis_id column" do
14
14
  before do
15
+ # this could be refactored into a method that prevents caching the variables unless the environment is prod
16
+ CanvasSync::Concerns::SyncMapping::Mapping.instance_variable_set(:@mappings, nil)
17
+ CanvasSync::Concerns::SyncMapping::Mapping.instance_variable_set(:@legacy_mappings, nil)
18
+
15
19
  self.use_transactional_tests = false
16
20
  ActiveRecord::Migration.add_column :users, :sis_id, :string
17
21
  User.reset_column_information
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -19,6 +19,7 @@ class CreateEnrollments < ActiveRecord::Migration[5.1]
19
19
  t.bigint :canvas_section_id
20
20
  t.string :workflow_state
21
21
  t.string :base_role_type
22
+ t.datetime :completed_at
22
23
 
23
24
  t.timestamps
24
25
  end
@@ -210,6 +210,7 @@ ActiveRecord::Schema.define(version: 2024_05_23_101010) do
210
210
  t.bigint "canvas_section_id"
211
211
  t.string "workflow_state"
212
212
  t.string "base_role_type"
213
+ t.datetime "completed_at"
213
214
  t.datetime "created_at", null: false
214
215
  t.datetime "updated_at", null: false
215
216
  t.index ["canvas_course_id"], name: "index_enrollments_on_canvas_course_id"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canvas_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.6
4
+ version: 0.22.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Instructure CustomDev
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-19 00:00:00.000000000 Z
11
+ date: 2024-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '5.2'
19
+ version: 7.1.0
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '5.2'
26
+ version: 7.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -220,20 +220,6 @@ dependencies:
220
220
  - - ">="
221
221
  - !ruby/object:Gem::Version
222
222
  version: '0'
223
- - !ruby/object:Gem::Dependency
224
- name: apartment
225
- requirement: !ruby/object:Gem::Requirement
226
- requirements:
227
- - - ">="
228
- - !ruby/object:Gem::Version
229
- version: '0'
230
- type: :development
231
- prerelease: false
232
- version_requirements: !ruby/object:Gem::Requirement
233
- requirements:
234
- - - ">="
235
- - !ruby/object:Gem::Version
236
- version: '0'
237
223
  - !ruby/object:Gem::Dependency
238
224
  name: with_model
239
225
  requirement: !ruby/object:Gem::Requirement
@@ -266,14 +252,14 @@ dependencies:
266
252
  name: sidekiq
267
253
  requirement: !ruby/object:Gem::Requirement
268
254
  requirements:
269
- - - "<"
255
+ - - "~>"
270
256
  - !ruby/object:Gem::Version
271
257
  version: '7.0'
272
258
  type: :development
273
259
  prerelease: false
274
260
  version_requirements: !ruby/object:Gem::Requirement
275
261
  requirements:
276
- - - "<"
262
+ - - "~>"
277
263
  - !ruby/object:Gem::Version
278
264
  version: '7.0'
279
265
  - !ruby/object:Gem::Dependency
@@ -430,7 +416,7 @@ dependencies:
430
416
  - - ">="
431
417
  - !ruby/object:Gem::Version
432
418
  version: '0'
433
- description:
419
+ description:
434
420
  email:
435
421
  - pseng@instructure.com
436
422
  executables: []
@@ -458,7 +444,6 @@ files:
458
444
  - lib/canvas_sync/concerns/account/ancestry.rb
459
445
  - lib/canvas_sync/concerns/account/base.rb
460
446
  - lib/canvas_sync/concerns/api_syncable.rb
461
- - lib/canvas_sync/concerns/auto_relations.rb
462
447
  - lib/canvas_sync/concerns/legacy_columns.rb
463
448
  - lib/canvas_sync/concerns/live_event_sync.rb
464
449
  - lib/canvas_sync/concerns/role/base.rb
@@ -868,7 +853,7 @@ files:
868
853
  homepage: https://instructure.com
869
854
  licenses: []
870
855
  metadata: {}
871
- post_install_message:
856
+ post_install_message:
872
857
  rdoc_options: []
873
858
  require_paths:
874
859
  - lib
@@ -883,241 +868,241 @@ required_rubygems_version: !ruby/object:Gem::Requirement
883
868
  - !ruby/object:Gem::Version
884
869
  version: '0'
885
870
  requirements: []
886
- rubygems_version: 3.0.3.1
887
- signing_key:
871
+ rubygems_version: 3.5.16
872
+ signing_key:
888
873
  specification_version: 4
889
874
  summary: Gem for generating Canvas models and migrations and syncing data from Canvas
890
875
  test_files:
891
- - spec/spec_helper.rb
876
+ - spec/canvas_sync/canvas_sync_spec.rb
877
+ - spec/canvas_sync/jobs/canvas_process_waiter_spec.rb
878
+ - spec/canvas_sync/jobs/job_spec.rb
879
+ - spec/canvas_sync/jobs/report_checker_spec.rb
880
+ - spec/canvas_sync/jobs/report_processor_job_spec.rb
881
+ - spec/canvas_sync/jobs/report_starter_spec.rb
882
+ - spec/canvas_sync/jobs/sync_admins_job_spec.rb
883
+ - spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb
884
+ - spec/canvas_sync/jobs/sync_assignments_job_spec.rb
885
+ - spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb
886
+ - spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb
887
+ - spec/canvas_sync/jobs/sync_context_modules_job_spec.rb
888
+ - spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb
889
+ - spec/canvas_sync/jobs/sync_roles_job_spec.rb
890
+ - spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
891
+ - spec/canvas_sync/jobs/sync_submissions_job_spec.rb
892
+ - spec/canvas_sync/jobs/sync_terms_job_spec.rb
893
+ - spec/canvas_sync/live_events/live_event_sync_spec.rb
894
+ - spec/canvas_sync/live_events/live_events_controller_spec.rb
895
+ - spec/canvas_sync/live_events/process_event_job_spec.rb
896
+ - spec/canvas_sync/misc_helper_spec.rb
897
+ - spec/canvas_sync/models/accounts_spec.rb
898
+ - spec/canvas_sync/models/admins_spec.rb
899
+ - spec/canvas_sync/models/assignment_group_spec.rb
900
+ - spec/canvas_sync/models/assignment_spec.rb
901
+ - spec/canvas_sync/models/context_module_item_spec.rb
902
+ - spec/canvas_sync/models/context_module_spec.rb
903
+ - spec/canvas_sync/models/course_spec.rb
904
+ - spec/canvas_sync/models/enrollment_spec.rb
905
+ - spec/canvas_sync/models/group_membership_spec.rb
906
+ - spec/canvas_sync/models/group_spec.rb
907
+ - spec/canvas_sync/models/roles_spec.rb
908
+ - spec/canvas_sync/models/section_spec.rb
909
+ - spec/canvas_sync/models/submission_spec.rb
910
+ - spec/canvas_sync/models/term_spec.rb
911
+ - spec/canvas_sync/models/user_spec.rb
912
+ - spec/canvas_sync/processors/assignment_groups_processor_spec.rb
913
+ - spec/canvas_sync/processors/assignments_processor_spec.rb
914
+ - spec/canvas_sync/processors/content_migrations_processor_spec.rb
915
+ - spec/canvas_sync/processors/context_module_items_processor_spec.rb
916
+ - spec/canvas_sync/processors/context_modules_processor_spec.rb
917
+ - spec/canvas_sync/processors/course_completion_report_processor_spec.rb
918
+ - spec/canvas_sync/processors/normal_processor_spec.rb
919
+ - spec/canvas_sync/processors/provisioning_report_processor_spec.rb
920
+ - spec/canvas_sync/processors/rubric_assessments_spec.rb
921
+ - spec/canvas_sync/processors/rubric_associations_spec.rb
922
+ - spec/canvas_sync/processors/rubrics_processor_spec.rb
923
+ - spec/canvas_sync/processors/submissions_processor_spec.rb
924
+ - spec/canvas_sync/services/module_event_spec.rb
925
+ - spec/canvas_sync/services/module_item_event_spec.rb
926
+ - spec/dummy/README.rdoc
927
+ - spec/dummy/Rakefile
928
+ - spec/dummy/app/models/account.rb
929
+ - spec/dummy/app/models/admin.rb
930
+ - spec/dummy/app/models/application_record.rb
931
+ - spec/dummy/app/models/assignment.rb
892
932
  - spec/dummy/app/models/assignment_group.rb
893
- - spec/dummy/app/models/learning_outcome_result.rb
933
+ - spec/dummy/app/models/content_migration.rb
894
934
  - spec/dummy/app/models/context_module.rb
895
- - spec/dummy/app/models/account.rb
896
- - spec/dummy/app/models/pseudonym.rb
897
- - spec/dummy/app/models/group_membership.rb
898
- - spec/dummy/app/models/grading_period.rb
935
+ - spec/dummy/app/models/context_module_item.rb
936
+ - spec/dummy/app/models/course.rb
937
+ - spec/dummy/app/models/course_nickname.rb
899
938
  - spec/dummy/app/models/course_progress.rb
900
- - spec/dummy/app/models/rubric_association.rb
901
- - spec/dummy/app/models/content_migration.rb
902
939
  - spec/dummy/app/models/enrollment.rb
903
- - spec/dummy/app/models/assignment.rb
940
+ - spec/dummy/app/models/grading_period.rb
941
+ - spec/dummy/app/models/grading_period_group.rb
904
942
  - spec/dummy/app/models/group.rb
905
- - spec/dummy/app/models/user_observer.rb
906
- - spec/dummy/app/models/admin.rb
907
- - spec/dummy/app/models/course_nickname.rb
908
- - spec/dummy/app/models/section.rb
943
+ - spec/dummy/app/models/group_membership.rb
909
944
  - spec/dummy/app/models/learning_outcome.rb
945
+ - spec/dummy/app/models/learning_outcome_result.rb
946
+ - spec/dummy/app/models/pseudonym.rb
910
947
  - spec/dummy/app/models/role.rb
911
- - spec/dummy/app/models/grading_period_group.rb
912
- - spec/dummy/app/models/term.rb
913
- - spec/dummy/app/models/submission.rb
914
- - spec/dummy/app/models/context_module_item.rb
915
- - spec/dummy/app/models/rubric_assessment.rb
916
- - spec/dummy/app/models/course.rb
917
- - spec/dummy/app/models/application_record.rb
918
948
  - spec/dummy/app/models/rubric.rb
949
+ - spec/dummy/app/models/rubric_assessment.rb
950
+ - spec/dummy/app/models/rubric_association.rb
951
+ - spec/dummy/app/models/section.rb
952
+ - spec/dummy/app/models/submission.rb
953
+ - spec/dummy/app/models/term.rb
919
954
  - spec/dummy/app/models/user.rb
920
- - spec/dummy/app/services/live_events/course_section_updated_event.rb
921
- - spec/dummy/app/services/live_events/submission_event.rb
922
- - spec/dummy/app/services/live_events/grade_event.rb
923
- - spec/dummy/app/services/live_events/module_item_event.rb
955
+ - spec/dummy/app/models/user_observer.rb
956
+ - spec/dummy/app/services/live_events/assignment_created_event.rb
957
+ - spec/dummy/app/services/live_events/assignment_event.rb
958
+ - spec/dummy/app/services/live_events/assignment_updated_event.rb
924
959
  - spec/dummy/app/services/live_events/base_event.rb
925
- - spec/dummy/app/services/live_events/grade_changed_event.rb
926
- - spec/dummy/app/services/live_events/user_updated_event.rb
927
- - spec/dummy/app/services/live_events/enrollment_event.rb
928
- - spec/dummy/app/services/live_events/module_item_updated_event.rb
929
960
  - spec/dummy/app/services/live_events/course_created_event.rb
930
- - spec/dummy/app/services/live_events/syllabus_updated_event.rb
931
961
  - spec/dummy/app/services/live_events/course_event.rb
932
- - spec/dummy/app/services/live_events/user_event.rb
933
- - spec/dummy/app/services/live_events/user_created_event.rb
934
- - spec/dummy/app/services/live_events/course_updated_event.rb
935
- - spec/dummy/app/services/live_events/module_item_created_event.rb
936
962
  - spec/dummy/app/services/live_events/course_section_created_event.rb
937
- - spec/dummy/app/services/live_events/syllabus_event.rb
938
- - spec/dummy/app/services/live_events/submission_updated_event.rb
939
963
  - spec/dummy/app/services/live_events/course_section_event.rb
940
- - spec/dummy/app/services/live_events/module_updated_event.rb
964
+ - spec/dummy/app/services/live_events/course_section_updated_event.rb
965
+ - spec/dummy/app/services/live_events/course_updated_event.rb
941
966
  - spec/dummy/app/services/live_events/enrollment_created_event.rb
942
- - spec/dummy/app/services/live_events/assignment_created_event.rb
943
- - spec/dummy/app/services/live_events/assignment_event.rb
944
- - spec/dummy/app/services/live_events/module_event.rb
967
+ - spec/dummy/app/services/live_events/enrollment_event.rb
945
968
  - spec/dummy/app/services/live_events/enrollment_updated_event.rb
946
- - spec/dummy/app/services/live_events/assignment_updated_event.rb
947
- - spec/dummy/app/services/live_events/submission_created_event.rb
969
+ - spec/dummy/app/services/live_events/grade_changed_event.rb
970
+ - spec/dummy/app/services/live_events/grade_event.rb
948
971
  - spec/dummy/app/services/live_events/module_created_event.rb
972
+ - spec/dummy/app/services/live_events/module_event.rb
973
+ - spec/dummy/app/services/live_events/module_item_created_event.rb
974
+ - spec/dummy/app/services/live_events/module_item_event.rb
975
+ - spec/dummy/app/services/live_events/module_item_updated_event.rb
976
+ - spec/dummy/app/services/live_events/module_updated_event.rb
977
+ - spec/dummy/app/services/live_events/submission_created_event.rb
978
+ - spec/dummy/app/services/live_events/submission_event.rb
979
+ - spec/dummy/app/services/live_events/submission_updated_event.rb
980
+ - spec/dummy/app/services/live_events/syllabus_event.rb
981
+ - spec/dummy/app/services/live_events/syllabus_updated_event.rb
982
+ - spec/dummy/app/services/live_events/user_created_event.rb
983
+ - spec/dummy/app/services/live_events/user_event.rb
984
+ - spec/dummy/app/services/live_events/user_updated_event.rb
949
985
  - spec/dummy/bin/rails
950
- - spec/dummy/config/secrets.yml
951
- - spec/dummy/config/routes.rb
952
- - spec/dummy/config/environments/development.rb
953
- - spec/dummy/config/environments/test.rb
954
- - spec/dummy/config/environment.rb
955
986
  - spec/dummy/config/application.rb
956
- - spec/dummy/config/database.yml
957
987
  - spec/dummy/config/boot.rb
988
+ - spec/dummy/config/database.yml
989
+ - spec/dummy/config/environment.rb
990
+ - spec/dummy/config/environments/development.rb
991
+ - spec/dummy/config/environments/test.rb
992
+ - spec/dummy/config/initializers/assets.rb
958
993
  - spec/dummy/config/initializers/session_store.rb
959
994
  - spec/dummy/config/initializers/wrap_parameters.rb
960
- - spec/dummy/config/initializers/assets.rb
995
+ - spec/dummy/config/routes.rb
996
+ - spec/dummy/config/secrets.yml
961
997
  - spec/dummy/config.ru
962
- - spec/dummy/Rakefile
963
- - spec/dummy/db/schema.rb
964
- - spec/dummy/db/migrate/20200416214248_create_group_memberships.rb
965
- - spec/dummy/db/migrate/20190702203627_create_submissions.rb
998
+ - spec/dummy/db/migrate/20190702203621_create_courses.rb
999
+ - spec/dummy/db/migrate/20190702203622_create_accounts.rb
1000
+ - spec/dummy/db/migrate/20190702203623_create_terms.rb
966
1001
  - spec/dummy/db/migrate/20190702203624_create_enrollments.rb
1002
+ - spec/dummy/db/migrate/20190702203625_create_sections.rb
1003
+ - spec/dummy/db/migrate/20190702203626_create_assignments.rb
1004
+ - spec/dummy/db/migrate/20190702203627_create_submissions.rb
967
1005
  - spec/dummy/db/migrate/20190702203630_create_assignment_groups.rb
968
- - spec/dummy/db/migrate/20240828161300_create_course_progresses.rb
1006
+ - spec/dummy/db/migrate/20190702203631_create_context_modules.rb
969
1007
  - spec/dummy/db/migrate/20190702203632_create_context_module_items.rb
970
- - spec/dummy/db/migrate/20240408223326_create_course_nicknames.rb
971
- - spec/dummy/db/migrate/20190702203622_create_accounts.rb
1008
+ - spec/dummy/db/migrate/20190927204545_create_roles.rb
1009
+ - spec/dummy/db/migrate/20190927204546_create_admins.rb
1010
+ - spec/dummy/db/migrate/20200415171620_create_groups.rb
1011
+ - spec/dummy/db/migrate/20200416214248_create_group_memberships.rb
1012
+ - spec/dummy/db/migrate/20201016181346_create_pseudonyms.rb
972
1013
  - spec/dummy/db/migrate/20210907233329_create_user_observers.rb
973
- - spec/dummy/db/migrate/20220712210559_create_learning_outcomes.rb
974
1014
  - spec/dummy/db/migrate/20210907233330_create_grading_periods.rb
975
- - spec/dummy/db/migrate/20240509105100_create_rubrics.rb
976
- - spec/dummy/db/migrate/20240523101010_create_learning_outcome_results.rb
977
- - spec/dummy/db/migrate/20240510094100_create_rubric_associations.rb
1015
+ - spec/dummy/db/migrate/20211001184920_create_grading_period_groups.rb
978
1016
  - spec/dummy/db/migrate/20220308072643_create_content_migrations.rb
979
- - spec/dummy/db/migrate/20190702203621_create_courses.rb
980
- - spec/dummy/db/migrate/20190927204546_create_admins.rb
981
- - spec/dummy/db/migrate/20190702203623_create_terms.rb
982
- - spec/dummy/db/migrate/20190927204545_create_roles.rb
1017
+ - spec/dummy/db/migrate/20220712210559_create_learning_outcomes.rb
983
1018
  - spec/dummy/db/migrate/20220926221926_create_users.rb
984
- - spec/dummy/db/migrate/20190702203625_create_sections.rb
985
- - spec/dummy/db/migrate/20201016181346_create_pseudonyms.rb
986
- - spec/dummy/db/migrate/20190702203626_create_assignments.rb
1019
+ - spec/dummy/db/migrate/20240408223326_create_course_nicknames.rb
1020
+ - spec/dummy/db/migrate/20240509105100_create_rubrics.rb
1021
+ - spec/dummy/db/migrate/20240510094100_create_rubric_associations.rb
987
1022
  - spec/dummy/db/migrate/20240510101100_create_rubric_assessments.rb
988
- - spec/dummy/db/migrate/20190702203631_create_context_modules.rb
989
- - spec/dummy/db/migrate/20211001184920_create_grading_period_groups.rb
990
- - spec/dummy/db/migrate/20200415171620_create_groups.rb
991
- - spec/dummy/README.rdoc
992
- - spec/canvas_sync/models/enrollment_spec.rb
993
- - spec/canvas_sync/models/admins_spec.rb
994
- - spec/canvas_sync/models/section_spec.rb
995
- - spec/canvas_sync/models/context_module_spec.rb
996
- - spec/canvas_sync/models/roles_spec.rb
997
- - spec/canvas_sync/models/term_spec.rb
998
- - spec/canvas_sync/models/assignment_spec.rb
999
- - spec/canvas_sync/models/submission_spec.rb
1000
- - spec/canvas_sync/models/context_module_item_spec.rb
1001
- - spec/canvas_sync/models/accounts_spec.rb
1002
- - spec/canvas_sync/models/assignment_group_spec.rb
1003
- - spec/canvas_sync/models/group_spec.rb
1004
- - spec/canvas_sync/models/group_membership_spec.rb
1005
- - spec/canvas_sync/models/user_spec.rb
1006
- - spec/canvas_sync/models/course_spec.rb
1007
- - spec/canvas_sync/misc_helper_spec.rb
1008
- - spec/canvas_sync/processors/context_module_items_processor_spec.rb
1009
- - spec/canvas_sync/processors/context_modules_processor_spec.rb
1010
- - spec/canvas_sync/processors/rubric_assessments_spec.rb
1011
- - spec/canvas_sync/processors/rubric_associations_spec.rb
1012
- - spec/canvas_sync/processors/normal_processor_spec.rb
1013
- - spec/canvas_sync/processors/provisioning_report_processor_spec.rb
1014
- - spec/canvas_sync/processors/course_completion_report_processor_spec.rb
1015
- - spec/canvas_sync/processors/content_migrations_processor_spec.rb
1016
- - spec/canvas_sync/processors/submissions_processor_spec.rb
1017
- - spec/canvas_sync/processors/assignments_processor_spec.rb
1018
- - spec/canvas_sync/processors/rubrics_processor_spec.rb
1019
- - spec/canvas_sync/processors/assignment_groups_processor_spec.rb
1020
- - spec/canvas_sync/jobs/report_checker_spec.rb
1021
- - spec/canvas_sync/jobs/canvas_process_waiter_spec.rb
1022
- - spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
1023
- - spec/canvas_sync/jobs/job_spec.rb
1024
- - spec/canvas_sync/jobs/sync_context_modules_job_spec.rb
1025
- - spec/canvas_sync/jobs/report_starter_spec.rb
1026
- - spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb
1027
- - spec/canvas_sync/jobs/sync_assignments_job_spec.rb
1028
- - spec/canvas_sync/jobs/sync_submissions_job_spec.rb
1029
- - spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb
1030
- - spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb
1031
- - spec/canvas_sync/jobs/sync_admins_job_spec.rb
1032
- - spec/canvas_sync/jobs/sync_roles_job_spec.rb
1033
- - spec/canvas_sync/jobs/sync_terms_job_spec.rb
1034
- - spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb
1035
- - spec/canvas_sync/jobs/report_processor_job_spec.rb
1036
- - spec/canvas_sync/canvas_sync_spec.rb
1037
- - spec/canvas_sync/services/module_item_event_spec.rb
1038
- - spec/canvas_sync/services/module_event_spec.rb
1039
- - spec/canvas_sync/live_events/live_event_sync_spec.rb
1040
- - spec/canvas_sync/live_events/live_events_controller_spec.rb
1041
- - spec/canvas_sync/live_events/process_event_job_spec.rb
1042
- - spec/job_uniqueness/spec_helper.rb
1043
- - spec/job_uniqueness/lock_context_spec.rb
1044
- - spec/job_uniqueness/on_conflict_spec.rb
1045
- - spec/job_uniqueness/compat/sidekiq_spec.rb
1046
- - spec/job_uniqueness/compat/active_job_spec.rb
1047
- - spec/job_uniqueness/on_conflict/reschedule_spec.rb
1048
- - spec/job_uniqueness/on_conflict/raise_spec.rb
1049
- - spec/job_uniqueness/on_conflict/log_spec.rb
1050
- - spec/job_uniqueness/unique_job_common_spec.rb
1051
- - spec/job_uniqueness/support/test_worker.rb
1052
- - spec/job_uniqueness/support/lock_strategy.rb
1053
- - spec/job_uniqueness/support/on_conflict.rb
1054
- - spec/job_uniqueness/strategy/until_executed_spec.rb
1055
- - spec/job_uniqueness/strategy/until_and_while_executing_spec.rb
1056
- - spec/job_uniqueness/strategy/until_executing_spec.rb
1057
- - spec/job_uniqueness/strategy/until_expired_spec.rb
1058
- - spec/job_uniqueness/strategy/while_executing_spec.rb
1059
- - spec/job_uniqueness/strategy/base_spec.rb
1023
+ - spec/dummy/db/migrate/20240523101010_create_learning_outcome_results.rb
1024
+ - spec/dummy/db/migrate/20240828161300_create_course_progresses.rb
1025
+ - spec/dummy/db/schema.rb
1026
+ - spec/factories/account_factory.rb
1027
+ - spec/factories/admin_factory.rb
1028
+ - spec/factories/assignment_factory.rb
1029
+ - spec/factories/assignment_group_factory.rb
1030
+ - spec/factories/context_module_factory.rb
1031
+ - spec/factories/context_module_item_factory.rb
1032
+ - spec/factories/course_factory.rb
1033
+ - spec/factories/enrollment_factory.rb
1034
+ - spec/factories/group_factory.rb
1035
+ - spec/factories/group_membership_factory.rb
1036
+ - spec/factories/role_factory.rb
1037
+ - spec/factories/section_factory.rb
1038
+ - spec/factories/submission_factory.rb
1039
+ - spec/factories/term_factory.rb
1040
+ - spec/factories/user_factory.rb
1060
1041
  - spec/job_batching/batch_spec.rb
1061
- - spec/job_batching/pool_spec.rb
1062
- - spec/job_batching/context_hash_spec.rb
1063
- - spec/job_batching/compat/sidekiq_spec.rb
1042
+ - spec/job_batching/callback_spec.rb
1064
1043
  - spec/job_batching/compat/active_job_spec.rb
1044
+ - spec/job_batching/compat/sidekiq_spec.rb
1045
+ - spec/job_batching/context_hash_spec.rb
1046
+ - spec/job_batching/flow_spec.rb
1047
+ - spec/job_batching/integration/fail_then_succeed.rb
1048
+ - spec/job_batching/integration/integration.rb
1065
1049
  - spec/job_batching/integration/nested.rb
1066
- - spec/job_batching/integration/workflow.rb
1067
1050
  - spec/job_batching/integration/simple.rb
1068
- - spec/job_batching/integration/integration.rb
1069
- - spec/job_batching/integration/fail_then_succeed.rb
1051
+ - spec/job_batching/integration/workflow.rb
1070
1052
  - spec/job_batching/integration_helper.rb
1071
- - spec/job_batching/flow_spec.rb
1053
+ - spec/job_batching/pool_spec.rb
1072
1054
  - spec/job_batching/status_spec.rb
1073
1055
  - spec/job_batching/support/base_job.rb
1074
1056
  - spec/job_batching/support/sample_callback.rb
1075
- - spec/job_batching/callback_spec.rb
1057
+ - spec/job_uniqueness/compat/active_job_spec.rb
1058
+ - spec/job_uniqueness/compat/sidekiq_spec.rb
1059
+ - spec/job_uniqueness/lock_context_spec.rb
1060
+ - spec/job_uniqueness/on_conflict/log_spec.rb
1061
+ - spec/job_uniqueness/on_conflict/raise_spec.rb
1062
+ - spec/job_uniqueness/on_conflict/reschedule_spec.rb
1063
+ - spec/job_uniqueness/on_conflict_spec.rb
1064
+ - spec/job_uniqueness/spec_helper.rb
1065
+ - spec/job_uniqueness/strategy/base_spec.rb
1066
+ - spec/job_uniqueness/strategy/until_and_while_executing_spec.rb
1067
+ - spec/job_uniqueness/strategy/until_executed_spec.rb
1068
+ - spec/job_uniqueness/strategy/until_executing_spec.rb
1069
+ - spec/job_uniqueness/strategy/until_expired_spec.rb
1070
+ - spec/job_uniqueness/strategy/while_executing_spec.rb
1071
+ - spec/job_uniqueness/support/lock_strategy.rb
1072
+ - spec/job_uniqueness/support/on_conflict.rb
1073
+ - spec/job_uniqueness/support/test_worker.rb
1074
+ - spec/job_uniqueness/unique_job_common_spec.rb
1075
+ - spec/spec_helper.rb
1076
1076
  - spec/support/fake_canvas.rb
1077
- - spec/support/fixtures/canvas_responses/roles.json
1078
1077
  - spec/support/fixtures/canvas_responses/admins.json
1078
+ - spec/support/fixtures/canvas_responses/module.json
1079
1079
  - spec/support/fixtures/canvas_responses/module_item.json
1080
+ - spec/support/fixtures/canvas_responses/roles.json
1080
1081
  - spec/support/fixtures/canvas_responses/terms.json
1081
- - spec/support/fixtures/canvas_responses/module.json
1082
- - spec/support/fixtures/reports/groups.csv
1083
- - spec/support/fixtures/reports/grading_period_groups.csv
1084
- - spec/support/fixtures/reports/learning_outcomes.csv
1082
+ - spec/support/fixtures/reports/assignment_groups.csv
1083
+ - spec/support/fixtures/reports/assignments.csv
1084
+ - spec/support/fixtures/reports/content_migrations.csv
1085
1085
  - spec/support/fixtures/reports/context_module_items.csv
1086
1086
  - spec/support/fixtures/reports/context_modules.csv
1087
- - spec/support/fixtures/reports/group_memberships.csv
1088
- - spec/support/fixtures/reports/content_migrations.csv
1089
- - spec/support/fixtures/reports/users.csv
1090
- - spec/support/fixtures/reports/submissions.csv
1091
- - spec/support/fixtures/reports/course_progresses_conflict.csv
1092
1087
  - spec/support/fixtures/reports/course_nicknames.csv
1088
+ - spec/support/fixtures/reports/course_progresses.csv
1089
+ - spec/support/fixtures/reports/course_progresses_conflict.csv
1090
+ - spec/support/fixtures/reports/courses.csv
1093
1091
  - spec/support/fixtures/reports/enrollments.csv
1094
- - spec/support/fixtures/reports/sections.csv
1095
- - spec/support/fixtures/reports/assignments.csv
1092
+ - spec/support/fixtures/reports/grading_period_groups.csv
1096
1093
  - spec/support/fixtures/reports/grading_periods.csv
1097
- - spec/support/fixtures/reports/courses.csv
1098
- - spec/support/fixtures/reports/rubric_associations.csv
1099
- - spec/support/fixtures/reports/xlist.csv
1094
+ - spec/support/fixtures/reports/group_memberships.csv
1095
+ - spec/support/fixtures/reports/groups.csv
1096
+ - spec/support/fixtures/reports/learning_outcome_results.csv
1097
+ - spec/support/fixtures/reports/learning_outcomes.csv
1100
1098
  - spec/support/fixtures/reports/provisioning_csv
1101
- - spec/support/fixtures/reports/user_observers.csv
1102
- - spec/support/fixtures/reports/rubrics.csv
1103
- - spec/support/fixtures/reports/assignment_groups.csv
1104
- - spec/support/fixtures/reports/course_progresses.csv
1105
- - spec/support/fixtures/reports/rubric_assessments.csv
1106
- - spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
1107
1099
  - spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv
1108
- - spec/support/fixtures/reports/learning_outcome_results.csv
1109
- - spec/factories/course_factory.rb
1110
- - spec/factories/admin_factory.rb
1111
- - spec/factories/group_membership_factory.rb
1112
- - spec/factories/user_factory.rb
1113
- - spec/factories/role_factory.rb
1114
- - spec/factories/assignment_factory.rb
1115
- - spec/factories/term_factory.rb
1116
- - spec/factories/group_factory.rb
1117
- - spec/factories/section_factory.rb
1118
- - spec/factories/enrollment_factory.rb
1119
- - spec/factories/context_module_factory.rb
1120
- - spec/factories/context_module_item_factory.rb
1121
- - spec/factories/submission_factory.rb
1122
- - spec/factories/assignment_group_factory.rb
1123
- - spec/factories/account_factory.rb
1100
+ - spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
1101
+ - spec/support/fixtures/reports/rubric_assessments.csv
1102
+ - spec/support/fixtures/reports/rubric_associations.csv
1103
+ - spec/support/fixtures/reports/rubrics.csv
1104
+ - spec/support/fixtures/reports/sections.csv
1105
+ - spec/support/fixtures/reports/submissions.csv
1106
+ - spec/support/fixtures/reports/user_observers.csv
1107
+ - spec/support/fixtures/reports/users.csv
1108
+ - spec/support/fixtures/reports/xlist.csv
@@ -1,11 +0,0 @@
1
- module CanvasSync::Concerns
2
- module AutoRelations
3
- extend ActiveSupport::Concern
4
-
5
- # CanvasSync::Record.define_feature self, default: true
6
-
7
- included do
8
-
9
- end
10
- end
11
- end