canvas_sync 0.16.4 → 0.17.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) 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/20170915210836_create_canvas_sync_job_log.rb +12 -31
  5. data/db/migrate/20180725155729_add_job_id_to_canvas_sync_job_logs.rb +4 -13
  6. data/db/migrate/20190916154829_add_fork_count_to_canvas_sync_job_logs.rb +3 -11
  7. data/db/migrate/20201018210836_create_canvas_sync_sync_batches.rb +11 -0
  8. data/lib/canvas_sync.rb +35 -118
  9. data/lib/canvas_sync/job.rb +5 -5
  10. data/lib/canvas_sync/job_batches/batch.rb +399 -0
  11. data/lib/canvas_sync/job_batches/batch_aware_job.rb +62 -0
  12. data/lib/canvas_sync/job_batches/callback.rb +153 -0
  13. data/lib/canvas_sync/job_batches/chain_builder.rb +203 -0
  14. data/lib/canvas_sync/job_batches/context_hash.rb +147 -0
  15. data/lib/canvas_sync/job_batches/jobs/base_job.rb +7 -0
  16. data/lib/canvas_sync/job_batches/jobs/concurrent_batch_job.rb +18 -0
  17. data/lib/canvas_sync/job_batches/jobs/serial_batch_job.rb +73 -0
  18. data/lib/canvas_sync/job_batches/sidekiq.rb +91 -0
  19. data/lib/canvas_sync/job_batches/status.rb +63 -0
  20. data/lib/canvas_sync/jobs/begin_sync_chain_job.rb +34 -0
  21. data/lib/canvas_sync/jobs/report_checker.rb +3 -6
  22. data/lib/canvas_sync/jobs/report_processor_job.rb +2 -5
  23. data/lib/canvas_sync/jobs/report_starter.rb +27 -19
  24. data/lib/canvas_sync/jobs/sync_accounts_job.rb +3 -5
  25. data/lib/canvas_sync/jobs/sync_admins_job.rb +2 -4
  26. data/lib/canvas_sync/jobs/sync_assignment_groups_job.rb +2 -4
  27. data/lib/canvas_sync/jobs/sync_assignments_job.rb +2 -4
  28. data/lib/canvas_sync/jobs/sync_context_module_items_job.rb +2 -4
  29. data/lib/canvas_sync/jobs/sync_context_modules_job.rb +2 -4
  30. data/lib/canvas_sync/jobs/sync_provisioning_report_job.rb +4 -31
  31. data/lib/canvas_sync/jobs/sync_roles_job.rb +2 -5
  32. data/lib/canvas_sync/jobs/sync_simple_table_job.rb +11 -32
  33. data/lib/canvas_sync/jobs/sync_submissions_job.rb +2 -4
  34. data/lib/canvas_sync/jobs/sync_terms_job.rb +22 -7
  35. data/lib/canvas_sync/misc_helper.rb +15 -0
  36. data/lib/canvas_sync/version.rb +1 -1
  37. data/spec/canvas_sync/canvas_sync_spec.rb +126 -153
  38. data/spec/canvas_sync/jobs/job_spec.rb +9 -17
  39. data/spec/canvas_sync/jobs/report_checker_spec.rb +1 -3
  40. data/spec/canvas_sync/jobs/report_processor_job_spec.rb +0 -3
  41. data/spec/canvas_sync/jobs/report_starter_spec.rb +19 -28
  42. data/spec/canvas_sync/jobs/sync_admins_job_spec.rb +1 -4
  43. data/spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb +2 -1
  44. data/spec/canvas_sync/jobs/sync_assignments_job_spec.rb +3 -2
  45. data/spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb +3 -2
  46. data/spec/canvas_sync/jobs/sync_context_modules_job_spec.rb +3 -2
  47. data/spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb +3 -35
  48. data/spec/canvas_sync/jobs/sync_roles_job_spec.rb +1 -4
  49. data/spec/canvas_sync/jobs/sync_simple_table_job_spec.rb +5 -12
  50. data/spec/canvas_sync/jobs/sync_submissions_job_spec.rb +2 -1
  51. data/spec/canvas_sync/jobs/sync_terms_job_spec.rb +1 -4
  52. data/spec/dummy/app/models/account.rb +3 -0
  53. data/spec/dummy/app/models/pseudonym.rb +14 -0
  54. data/spec/dummy/app/models/submission.rb +1 -0
  55. data/spec/dummy/app/models/user.rb +1 -0
  56. data/spec/dummy/config/environments/test.rb +2 -0
  57. data/spec/dummy/db/migrate/20201016181346_create_pseudonyms.rb +24 -0
  58. data/spec/dummy/db/schema.rb +24 -4
  59. data/spec/job_batching/batch_aware_job_spec.rb +100 -0
  60. data/spec/job_batching/batch_spec.rb +363 -0
  61. data/spec/job_batching/callback_spec.rb +38 -0
  62. data/spec/job_batching/flow_spec.rb +91 -0
  63. data/spec/job_batching/integration/integration.rb +57 -0
  64. data/spec/job_batching/integration/nested.rb +88 -0
  65. data/spec/job_batching/integration/simple.rb +47 -0
  66. data/spec/job_batching/integration/workflow.rb +134 -0
  67. data/spec/job_batching/integration_helper.rb +48 -0
  68. data/spec/job_batching/sidekiq_spec.rb +124 -0
  69. data/spec/job_batching/status_spec.rb +92 -0
  70. data/spec/job_batching/support/base_job.rb +14 -0
  71. data/spec/job_batching/support/sample_callback.rb +2 -0
  72. data/spec/spec_helper.rb +10 -0
  73. metadata +90 -8
  74. data/lib/canvas_sync/job_chain.rb +0 -57
  75. data/lib/canvas_sync/jobs/fork_gather.rb +0 -59
  76. data/spec/canvas_sync/jobs/fork_gather_spec.rb +0 -73
@@ -4,11 +4,10 @@ module CanvasSync
4
4
  # Syncs Admins using the Canvas API
5
5
  #
6
6
  #
7
- # @param job_chain [Hash]
8
7
  # @param options [Hash]
9
- def perform(job_chain, _options)
8
+ def perform(options)
10
9
  updated_admin_ids = []
11
- api_client = CanvasSync.get_canvas_sync_client(job_chain[:global_options])
10
+ api_client = CanvasSync.get_canvas_sync_client(batch_context)
12
11
  CanvasSync.sync_scope(Account).find_each do |acc|
13
12
  api_client.account_admins(acc.canvas_id).all_pages_each do |admin_params|
14
13
  admin_params[:account_id] = acc.canvas_id
@@ -17,7 +16,6 @@ module CanvasSync
17
16
  end
18
17
  end
19
18
  Admin.where.not(id: updated_admin_ids).update_all(workflow_state: 'inactive')
20
- CanvasSync.invoke_next(job_chain)
21
19
  end
22
20
  end
23
21
  end
@@ -6,13 +6,11 @@ module CanvasSync
6
6
  # Starts a report processor for the assignment_groups report
7
7
  # (the proserv_assignment_group_export_csv report must be enabled)
8
8
  #
9
- # @param job_chain [Hash]
10
9
  # @param options [Hash]
11
- def perform(job_chain, options)
10
+ def perform(options)
12
11
  super(
13
- job_chain,
14
12
  "proserv_assignment_group_export_csv",
15
- merge_report_params(job_chain, options),
13
+ merge_report_params(options),
16
14
  CanvasSync::Processors::AssignmentGroupsProcessor.to_s,
17
15
  {},
18
16
  )
@@ -6,13 +6,11 @@ module CanvasSync
6
6
  # Starts a report processor for the assignment report
7
7
  # (the proserv_assignment_export_csv report must be enabled)
8
8
  #
9
- # @param job_chain [Hash]
10
9
  # @param options [Hash]
11
- def perform(job_chain, options)
10
+ def perform(options)
12
11
  super(
13
- job_chain,
14
12
  "proserv_assignment_export_csv",
15
- merge_report_params(job_chain, options),
13
+ merge_report_params(options),
16
14
  CanvasSync::Processors::AssignmentsProcessor.to_s,
17
15
  {},
18
16
  )
@@ -6,13 +6,11 @@ module CanvasSync
6
6
  # Starts a report processor for the context modules report
7
7
  # (the proserv_context_module_items_csv report must be enabled)
8
8
  #
9
- # @param job_chain [Hash]
10
9
  # @param options [Hash]
11
- def perform(job_chain, options)
10
+ def perform(options)
12
11
  super(
13
- job_chain,
14
12
  "proserv_context_module_items_csv",
15
- merge_report_params(job_chain, options),
13
+ merge_report_params(options),
16
14
  CanvasSync::Processors::ContextModuleItemsProcessor.to_s,
17
15
  {},
18
16
  )
@@ -6,13 +6,11 @@ module CanvasSync
6
6
  # Starts a report processor for the context modules report
7
7
  # (the proserv_context_modules_csv report must be enabled)
8
8
  #
9
- # @param job_chain [Hash]
10
9
  # @param options [Hash]
11
- def perform(job_chain, options)
10
+ def perform(options)
12
11
  super(
13
- job_chain,
14
12
  "proserv_context_modules_csv",
15
- merge_report_params(job_chain, options),
13
+ merge_report_params(options),
16
14
  CanvasSync::Processors::ContextModulesProcessor.to_s,
17
15
  {},
18
16
  )
@@ -2,40 +2,17 @@ module CanvasSync
2
2
  module Jobs
3
3
  # ActiveJob class that starts a Canvas provisioning report
4
4
  class SyncProvisioningReportJob < CanvasSync::Job
5
- # @param job_chain [Hash]
6
5
  # @param options [Hash] If options contains a :term_scope a seperate provisioning report
7
6
  # will be started for each term in that scope. :models should be an array of
8
7
  # models to sync.
9
- def perform(job_chain, options)
10
- if options[:term_scope]
11
- sub_reports = CanvasSync.fork(@job_log, job_chain, keys: [:canvas_term_id]) do |job_chain|
12
- Term.send(options[:term_scope]).find_each.map do |term|
13
- # Deep copy the job_chain so each report gets the correct term id passed into
14
- # its options with no side effects
15
- term_id = get_term_id(term)
16
- duped_job_chain = Marshal.load(Marshal.dump(job_chain))
17
- duped_job_chain[:global_options][:canvas_term_id] = term_id
18
- {
19
- job_chain: duped_job_chain,
20
- params: report_params(options, term_id),
21
- options: options,
22
- }
23
- end
24
- end
25
-
26
- sub_reports.each do |r|
27
- start_report(r[:params], r[:job_chain], r[:options])
28
- end
29
- else
30
- start_report(report_params(options), job_chain, options)
31
- end
8
+ def perform(options)
9
+ start_report(report_params(options), options)
32
10
  end
33
11
 
34
12
  protected
35
13
 
36
- def start_report(report_params, job_chain, options)
14
+ def start_report(report_params, options)
37
15
  CanvasSync::Jobs::ReportStarter.perform_later(
38
- job_chain,
39
16
  "proservices_provisioning_csv",
40
17
  report_params,
41
18
  CanvasSync::Processors::ProvisioningReportProcessor.to_s,
@@ -43,7 +20,7 @@ module CanvasSync
43
20
  )
44
21
  end
45
22
 
46
- def report_params(options, canvas_term_id=nil)
23
+ def report_params(options, canvas_term_id = options[:canvas_term_id] || batch_context[:canvas_term_id])
47
24
  params = {
48
25
  include_deleted: true,
49
26
  }
@@ -60,10 +37,6 @@ module CanvasSync
60
37
 
61
38
  { parameters: params }
62
39
  end
63
-
64
- def get_term_id(term)
65
- term.try(:canvas_id) || term.canvas_term_id
66
- end
67
40
  end
68
41
  end
69
42
  end
@@ -3,12 +3,10 @@ module CanvasSync
3
3
  class SyncRolesJob < CanvasSync::Job
4
4
  # Syncs Roles using the Canvas API
5
5
  #
6
- #
7
- # @param job_chain [Hash]
8
6
  # @param options [Hash]
9
- def perform(job_chain, _options)
7
+ def perform(options)
10
8
  updated_role_ids = []
11
- api_client = CanvasSync.get_canvas_sync_client(job_chain[:global_options])
9
+ api_client = CanvasSync.get_canvas_sync_client(batch_context)
12
10
  CanvasSync.sync_scope(Account).find_each do |acc|
13
11
  api_client.list_roles(acc.canvas_id, state: %w[active inactive]).all_pages_each do |role_params|
14
12
  role = update_or_create_model(Role, role_params)
@@ -16,7 +14,6 @@ module CanvasSync
16
14
  end
17
15
  end
18
16
  Role.where.not(id: updated_role_ids).update_all(workflow_state: 'inactive')
19
- CanvasSync.invoke_next(job_chain)
20
17
  end
21
18
  end
22
19
  end
@@ -5,36 +5,19 @@ module CanvasSync
5
5
  # Starts a report processor for the specified report
6
6
  # (the specified report must be enabled)
7
7
  #
8
- # @param job_chain [Hash]
9
- # @param options [Hash]
10
- def perform(job_chain, options)
11
- if options[:term_scope]
12
- sub_reports = CanvasSync.fork(@job_log, job_chain, keys: [:canvas_term_id]) do |job_chain|
13
- Term.send(options[:term_scope]).find_each.map do |term|
14
- # Deep copy the job_chain so each report gets the correct term id passed into
15
- # its options with no side effects
16
- term_id = get_term_id(term)
17
- duped_job_chain = Marshal.load(Marshal.dump(job_chain))
18
- duped_job_chain[:global_options][:canvas_term_id] = term_id
19
- {
20
- job_chain: duped_job_chain,
21
- params: report_params(options, term_id),
22
- options: options,
23
- }
24
- end
25
- end
26
-
27
- sub_reports.each do |r|
28
- start_report(r[:params], r[:job_chain], r[:options])
29
- end
30
- else
31
- start_report(report_params(options), job_chain, options)
32
- end
8
+ # @param options [Hash] {
9
+ # report_name: "", # Name of the report in the Canvas API
10
+ # model: , # Model to map the report results as
11
+ # mapping: {} # Mapping to describe how to convert the report to the Model,
12
+ # klass: ,
13
+ # params: {}, # List of params to pass to the report
14
+ # }
15
+ def perform(options)
16
+ start_report(report_params(options), options)
33
17
  end
34
18
 
35
- def start_report(params, job_chain, options)
19
+ def start_report(params, options)
36
20
  CanvasSync::Jobs::ReportStarter.perform_later(
37
- job_chain,
38
21
  options[:report_name],
39
22
  params,
40
23
  CanvasSync::Processors::NormalProcessor.to_s,
@@ -42,15 +25,11 @@ module CanvasSync
42
25
  )
43
26
  end
44
27
 
45
- def report_params(options, canvas_term_id=nil)
28
+ def report_params(options, canvas_term_id = options[:canvas_term_id] || batch_context[:canvas_term_id])
46
29
  params = options[:params] || {}
47
30
  params["parameters[enrollment_term_id]"] = canvas_term_id if canvas_term_id
48
31
  params
49
32
  end
50
-
51
- def get_term_id(term)
52
- term.try(:canvas_id) || term.canvas_term_id
53
- end
54
33
  end
55
34
  end
56
35
  end
@@ -6,13 +6,11 @@ module CanvasSync
6
6
  # Starts a report processor for the submission report
7
7
  # (the proserv_student_submissions_csv report must be enabled)
8
8
  #
9
- # @param job_chain [Hash]
10
9
  # @param options [Hash]
11
- def perform(job_chain, options)
10
+ def perform(options)
12
11
  super(
13
- job_chain,
14
12
  "proserv_student_submissions_csv",
15
- merge_report_params(job_chain, options, { include_all: options[:include_all] }, {}),
13
+ merge_report_params(options, { include_all: options[:include_all] }, {}),
16
14
  CanvasSync::Processors::SubmissionsProcessor.to_s,
17
15
  {},
18
16
  )
@@ -5,16 +5,15 @@ module CanvasSync
5
5
  #
6
6
  # Terms are pre-synced so that provisioning reports can be scoped to term.
7
7
  #
8
- # @param job_chain [Hash]
9
8
  # @param options [Hash]
10
- def perform(job_chain, _options)
11
- CanvasSync.get_canvas_sync_client(job_chain[:global_options]).terms("self").all_pages!.each do |term_params|
12
- if job_chain[:global_options][:account_id]
9
+ def perform(options)
10
+ CanvasSync.get_canvas_sync_client(batch_context).terms("self").all_pages!.each do |term_params|
11
+ if account_id = batch_context[:account_id]
13
12
  # These branches are primarily to support Legacy apps
14
13
  if Term.respond_to?(:create_or_update) && Term.method(:create_or_update).arity.abs == 2
15
- Term.create_or_update(term_params, job_chain[:global_options][:account_id])
14
+ Term.create_or_update(term_params, account_id)
16
15
  else
17
- term_params[:account_id] |= job_chain[:global_options][:account_id]
16
+ term_params[:account_id] |= account_id
18
17
  update_or_create_model(Term, term_params)
19
18
  end
20
19
  else
@@ -22,7 +21,23 @@ module CanvasSync
22
21
  end
23
22
  end
24
23
 
25
- CanvasSync.invoke_next(job_chain)
24
+ if (jobs = options[:sub_jobs]).present?
25
+ context = options[:context] || {}
26
+ if options[:term_scope]
27
+ Term.send(options[:term_scope]).find_each.map do |term|
28
+ local_context = context.merge(canvas_term_id: get_term_id(term))
29
+ JobBatches::ConcurrentBatchJob.perform_now(jobs, context: local_context)
30
+ end
31
+ else
32
+ JobBatches::ConcurrentBatchJob.perform_now(jobs, context: context)
33
+ end
34
+ end
35
+ end
36
+
37
+ protected
38
+
39
+ def get_term_id(term)
40
+ term.try(:canvas_id) || term.canvas_term_id
26
41
  end
27
42
  end
28
43
  end
@@ -0,0 +1,15 @@
1
+ require 'active_record'
2
+
3
+ module CanvasSync
4
+ module MiscHelper
5
+ MigrationClass = Rails.version < '5.0' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
6
+
7
+ def self.to_boolean(v)
8
+ if Rails.version < '5.0'
9
+ ActiveRecord::Type::Boolean.new.type_cast_from_user(v)
10
+ else
11
+ ActiveRecord::Type::Boolean.new.deserialize(v)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.16.4".freeze
2
+ VERSION = "0.17.0.beta1".freeze
3
3
  end
@@ -3,13 +3,12 @@ require 'spec_helper'
3
3
  RSpec.describe CanvasSync do
4
4
  describe '.provisioning_sync' do
5
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'], nil).chain_data
7
- first_job = expected_job_chain[:jobs].shift
6
+ expected_job_chain = CanvasSync.default_provisioning_report_chain(['courses'], term_scope: nil).normalize![:parameters][0]
8
7
 
9
- expect(CanvasSync::Jobs::SyncTermsJob).to receive(:perform_later)
8
+ expect(CanvasSync::Jobs::BeginSyncChainJob).to receive(:perform_later)
10
9
  .with(
11
10
  expected_job_chain,
12
- first_job[:options]
11
+ anything
13
12
  )
14
13
 
15
14
  CanvasSync.provisioning_sync(['courses'])
@@ -25,32 +24,42 @@ RSpec.describe CanvasSync do
25
24
 
26
25
  describe '.default_provisioning_report_chain' do
27
26
  it 'splits an options: Hash into options for separate models' do
28
- chain = CanvasSync.default_provisioning_report_chain(['users', 'courses'], :active, options: {
27
+ chain = CanvasSync.default_provisioning_report_chain(['users', 'courses'], term_scope: :active, options: {
29
28
  terms: { a: 1 },
30
29
  users: { b: 2 },
31
30
  provisioning: { c: 3 },
32
31
  global: { d: 4 },
33
32
  })
34
- expect(chain.chain_data).to eq({
35
- jobs: [
36
- { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: { a: 1 } },
37
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { models: ['users'], b: 2 } },
38
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: 'active', models: ['courses'], c: 3 } }
39
- ],
40
- global_options: { legacy_support: false, d: 4 }
33
+ expect(chain.normalize!).to eq({
34
+ :job => "CanvasSync::Jobs::BeginSyncChainJob",
35
+ :parameters => [[
36
+ {:job=>"CanvasSync::JobBatches::ConcurrentBatchJob", :parameters=>[[
37
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users"], :b=>2}},
38
+ {:job=>"CanvasSync::Jobs::SyncTermsJob", :parameters=>[{
39
+ :sub_jobs=>[
40
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"], :term_scope=>"active", :c=>3}}
41
+ ]
42
+ }]}
43
+ ]]}
44
+ ], {:legacy_support=>false, :updated_after=>nil, :d=>4}],
41
45
  })
42
46
  end
43
47
 
44
48
  context 'we are syncing users with a term scope' do
45
49
  it 'syncs the users in a separate job that runs first' do
46
- chain = CanvasSync.default_provisioning_report_chain(['users', 'courses'], :active)
47
- expect(chain.chain_data).to eq({
48
- jobs: [
49
- { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
50
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { models: ['users'] } },
51
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: 'active', models: ['courses'] } }
52
- ],
53
- global_options: { legacy_support: false }
50
+ chain = CanvasSync.default_provisioning_report_chain(['users', 'courses'], term_scope: :active)
51
+ expect(chain.normalize!).to eq({
52
+ :job => "CanvasSync::Jobs::BeginSyncChainJob",
53
+ :parameters => [[
54
+ {:job=>"CanvasSync::JobBatches::ConcurrentBatchJob", :parameters=>[[
55
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users"]}},
56
+ {:job=>"CanvasSync::Jobs::SyncTermsJob", :parameters=>[{
57
+ :sub_jobs=>[
58
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"], :term_scope=>"active"}}
59
+ ]
60
+ }]}
61
+ ]]}
62
+ ], {:legacy_support=>false, :updated_after=>nil}]
54
63
  })
55
64
  end
56
65
  end
@@ -58,26 +67,36 @@ RSpec.describe CanvasSync do
58
67
  context 'we are syncing users without a term scope' do
59
68
  it 'syncs users along with the rest of the provisioning report' do
60
69
  chain = CanvasSync.default_provisioning_report_chain(['users', 'courses'])
61
- expect(chain.chain_data).to eq({
62
- jobs: [
63
- { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
64
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: nil, models: ['users', 'courses'] } }
65
- ],
66
- global_options: { legacy_support: false }
70
+ expect(chain.normalize!).to eq({
71
+ :job => "CanvasSync::Jobs::BeginSyncChainJob",
72
+ :parameters => [[
73
+ {:job=>"CanvasSync::JobBatches::ConcurrentBatchJob", :parameters=>[[
74
+ {:job=>"CanvasSync::Jobs::SyncTermsJob", :parameters=>[{
75
+ :sub_jobs=>[
76
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "courses"], :term_scope=>nil}}
77
+ ]
78
+ }]}
79
+ ]]}
80
+ ], {:legacy_support=>false, :updated_after=>nil}],
67
81
  })
68
82
  end
69
83
  end
70
84
 
71
85
  context 'we are syncing roles with a term scope' do
72
86
  it 'syncs the roles in a separate job that runs first' do
73
- chain = CanvasSync.default_provisioning_report_chain(['roles', 'courses'], :active)
74
- expect(chain.chain_data).to eq({
75
- jobs: [
76
- { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
77
- { job: CanvasSync::Jobs::SyncRolesJob.to_s, options: {} },
78
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: 'active', models: ['courses'] } }
79
- ],
80
- global_options: { legacy_support: false }
87
+ chain = CanvasSync.default_provisioning_report_chain(['roles', 'courses'], term_scope: :active)
88
+ expect(chain.normalize!).to eq({
89
+ :job => "CanvasSync::Jobs::BeginSyncChainJob",
90
+ :parameters => [[
91
+ {:job=>"CanvasSync::JobBatches::ConcurrentBatchJob", :parameters=>[[
92
+ {:job=>"CanvasSync::Jobs::SyncRolesJob", :options=>{}},
93
+ {:job=>"CanvasSync::Jobs::SyncTermsJob", :parameters=>[{
94
+ :sub_jobs=>[
95
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"], :term_scope=>"active"}}
96
+ ]
97
+ }]}
98
+ ]]}
99
+ ], {:legacy_support=>false, :updated_after=>nil}],
81
100
  })
82
101
  end
83
102
  end
@@ -85,27 +104,37 @@ RSpec.describe CanvasSync do
85
104
  context 'we are syncing roles without a term scope' do
86
105
  it 'syncs roles separately even with no term scope' do
87
106
  chain = CanvasSync.default_provisioning_report_chain(['roles', 'courses'])
88
- expect(chain.chain_data).to eq({
89
- jobs: [
90
- { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
91
- { job: CanvasSync::Jobs::SyncRolesJob.to_s, options: {} },
92
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: nil, models: ['courses'] } }
93
- ],
94
- global_options: { legacy_support: false }
107
+ expect(chain.normalize!).to eq({
108
+ :job => "CanvasSync::Jobs::BeginSyncChainJob",
109
+ :parameters => [[
110
+ {:job=>"CanvasSync::JobBatches::ConcurrentBatchJob", :parameters=>[[
111
+ {:job=>"CanvasSync::Jobs::SyncRolesJob", :options=>{}},
112
+ {:job=>"CanvasSync::Jobs::SyncTermsJob", :parameters=>[{
113
+ :sub_jobs=>[
114
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"], :term_scope=>nil}}
115
+ ]
116
+ }]}
117
+ ]]}
118
+ ], {:legacy_support=>false, :updated_after=>nil}],
95
119
  })
96
120
  end
97
121
  end
98
122
 
99
123
  context 'we are syncing admins with a term scope' do
100
124
  it 'syncs the admins in a separate job that runs first' do
101
- chain = CanvasSync.default_provisioning_report_chain(['admins', 'courses'], :active)
102
- expect(chain.chain_data).to eq({
103
- jobs: [
104
- { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
105
- { job: CanvasSync::Jobs::SyncAdminsJob.to_s, options: {} },
106
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: 'active', models: ['courses'] } }
107
- ],
108
- global_options: { legacy_support: false }
125
+ chain = CanvasSync.default_provisioning_report_chain(['admins', 'courses'], term_scope: :active)
126
+ expect(chain.normalize!).to eq({
127
+ :job => "CanvasSync::Jobs::BeginSyncChainJob",
128
+ :parameters => [[
129
+ {:job=>"CanvasSync::JobBatches::ConcurrentBatchJob", :parameters=>[[
130
+ {:job=>"CanvasSync::Jobs::SyncAdminsJob", :options=>{}},
131
+ {:job=>"CanvasSync::Jobs::SyncTermsJob", :parameters=>[{
132
+ :sub_jobs=>[
133
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"], :term_scope=>"active"}}
134
+ ]
135
+ }]}
136
+ ]]}
137
+ ], {:legacy_support=>false, :updated_after=>nil}],
109
138
  })
110
139
  end
111
140
  end
@@ -113,13 +142,18 @@ RSpec.describe CanvasSync do
113
142
  context 'we are syncing admins without a term scope' do
114
143
  it 'syncs admins separately even with no term scope' do
115
144
  chain = CanvasSync.default_provisioning_report_chain(['admins', 'courses'])
116
- expect(chain.chain_data).to eq({
117
- jobs: [
118
- { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
119
- { job: CanvasSync::Jobs::SyncAdminsJob.to_s, options: {} },
120
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: nil, models: ['courses'] } }
121
- ],
122
- global_options: { legacy_support: false }
145
+ expect(chain.normalize!).to eq({
146
+ :job => "CanvasSync::Jobs::BeginSyncChainJob",
147
+ :parameters => [[
148
+ {:job=>"CanvasSync::JobBatches::ConcurrentBatchJob", :parameters=>[[
149
+ {:job=>"CanvasSync::Jobs::SyncAdminsJob", :options=>{}},
150
+ {:job=>"CanvasSync::Jobs::SyncTermsJob", :parameters=>[{
151
+ :sub_jobs=>[
152
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"], :term_scope=>nil}}
153
+ ]
154
+ }]}
155
+ ]]}
156
+ ], {:legacy_support=>false, :updated_after=>nil}],
123
157
  })
124
158
  end
125
159
  end
@@ -128,13 +162,18 @@ RSpec.describe CanvasSync do
128
162
  it "appends the SyncAssignmentsJob" do
129
163
  chain = CanvasSync.default_provisioning_report_chain(%w[users enrollments assignments])
130
164
 
131
- expect(chain.chain_data).to eq(
132
- jobs: [
133
- { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
134
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: nil, models: %w[users enrollments] } },
135
- { job: CanvasSync::Jobs::SyncAssignmentsJob.to_s, options: {} },
136
- ],
137
- global_options: { legacy_support: false },
165
+ expect(chain.normalize!).to eq(
166
+ :job => "CanvasSync::Jobs::BeginSyncChainJob",
167
+ :parameters => [[
168
+ {:job=>"CanvasSync::JobBatches::ConcurrentBatchJob", :parameters=>[[
169
+ {:job=>"CanvasSync::Jobs::SyncTermsJob", :parameters=>[{
170
+ :sub_jobs=>[
171
+ {:job=>"CanvasSync::Jobs::SyncAssignmentsJob", :options=>{}},
172
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "enrollments"], :term_scope=>nil}}
173
+ ]
174
+ }]}
175
+ ]]}
176
+ ], {:legacy_support=>false, :updated_after=>nil}],
138
177
  )
139
178
  end
140
179
  end
@@ -143,13 +182,18 @@ RSpec.describe CanvasSync do
143
182
  it "appends the SyncSubmissionsJob" do
144
183
  chain = CanvasSync.default_provisioning_report_chain(%w[users enrollments submissions])
145
184
 
146
- expect(chain.chain_data).to eq(
147
- jobs: [
148
- { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
149
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: nil, models: %w[users enrollments] } },
150
- { job: CanvasSync::Jobs::SyncSubmissionsJob.to_s, options: {} },
151
- ],
152
- global_options: { legacy_support: false },
185
+ expect(chain.normalize!).to eq(
186
+ :job => "CanvasSync::Jobs::BeginSyncChainJob",
187
+ :parameters => [[
188
+ {:job=>"CanvasSync::JobBatches::ConcurrentBatchJob", :parameters=>[[
189
+ {:job=>"CanvasSync::Jobs::SyncTermsJob", :parameters=>[{
190
+ :sub_jobs=>[
191
+ {:job=>"CanvasSync::Jobs::SyncSubmissionsJob", :options=>{}},
192
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "enrollments"], :term_scope=>nil}}
193
+ ]
194
+ }]}
195
+ ]]}
196
+ ], {:legacy_support=>false, :updated_after=>nil}],
153
197
  )
154
198
  end
155
199
  end
@@ -158,95 +202,24 @@ RSpec.describe CanvasSync do
158
202
  it "appends the SyncAssignmentGroupsJob" do
159
203
  chain = CanvasSync.default_provisioning_report_chain(%w[users enrollments assignment_groups])
160
204
 
161
- expect(chain.chain_data).to eq(
162
- jobs: [
163
- { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
164
- { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: nil, models: %w[users enrollments] } },
165
- { job: CanvasSync::Jobs::SyncAssignmentGroupsJob.to_s, options: {} },
166
- ],
167
- global_options: { legacy_support: false },
205
+ expect(chain.normalize!).to eq(
206
+ :job => "CanvasSync::Jobs::BeginSyncChainJob",
207
+ :parameters => [[
208
+ {:job=>"CanvasSync::JobBatches::ConcurrentBatchJob", :parameters=>[[
209
+ {:job=>"CanvasSync::Jobs::SyncTermsJob", :parameters=>[{
210
+ :sub_jobs=>[
211
+ {:job=>"CanvasSync::Jobs::SyncAssignmentGroupsJob", :options=>{}},
212
+ {:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "enrollments"], :term_scope=>nil}}
213
+ ]
214
+ }]}
215
+ ]]}
216
+ ], {:legacy_support=>false, :updated_after=>nil}],
168
217
  )
169
218
  end
170
219
  end
171
220
  end
172
221
  end
173
222
 
174
- describe ".simple_report_sync" do
175
-
176
- it 'invokes the first job in the queue and passes on the rest of the job chain' do
177
- expected_job_chain = CanvasSync.simple_report_chain(
178
- [
179
- {
180
- report_name: 'proservices_provisioning_csv',
181
- model: 'users',
182
- params: {
183
- "parameters[include_deleted]" => true,
184
- "parameters[users]" => true
185
- }
186
- }
187
- ]
188
- ).chain_data
189
- first_job = expected_job_chain[:jobs].shift
190
-
191
- expect(CanvasSync::Jobs::SyncSimpleTableJob).to receive(:perform_later)
192
- .with(
193
- expected_job_chain,
194
- first_job[:options]
195
- )
196
-
197
- CanvasSync.simple_report_sync(
198
- [
199
- {
200
- report_name: 'proservices_provisioning_csv',
201
- model: 'users',
202
- params: {
203
- "parameters[include_deleted]" => true,
204
- "parameters[users]" => true
205
- }
206
- }
207
- ]
208
- )
209
- end
210
-
211
- it 'receives the job chain for the specified table' do
212
- chain = CanvasSync.simple_report_chain(
213
- [
214
- {
215
- report_name: 'proservices_provisioning_csv',
216
- model: 'users',
217
- params: {
218
- "parameters[include_deleted]" => true,
219
- "parameters[users]" => true
220
- }
221
- }
222
- ]
223
- )
224
-
225
- expected_job_chain = {
226
- jobs: [
227
- {
228
- job: CanvasSync::Jobs::SyncSimpleTableJob.to_s,
229
- options: {
230
- report_name: 'proservices_provisioning_csv',
231
- model: 'users',
232
- mapping: 'users',
233
- klass: 'User',
234
- term_scope: nil,
235
- params: {
236
- "parameters[include_deleted]" => true,
237
- "parameters[users]" => true
238
- }
239
- }
240
- }
241
- ],
242
- global_options: {}
243
- }
244
-
245
- expect(chain.chain_data).to eq(expected_job_chain)
246
-
247
- end
248
- end
249
-
250
223
  describe ".sync_scope" do
251
224
 
252
225
  end