canvas_sync 0.17.40 → 0.17.41

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: 252aa98d20ca9456416bab466fdbfc5bcfe5d7626a8462002a66034c5aa8e168
4
- data.tar.gz: da8257b9f54f1840b19661982a712c51a2e720e5defecdd2080b1ecd3d2962f7
3
+ metadata.gz: cfa9a724751a0d163496133f4c928f1ccfca544413d668ef045bb30178dd37fc
4
+ data.tar.gz: c6107cc707e8474dc23e429760b276d0f91f5e482860cd870b4069279bcc9120
5
5
  SHA512:
6
- metadata.gz: 247383e570fe4b9f89640bfee466ba616bd845e299c03fef240e14c45fbc9d2cd5558d3ea09bc8a80bb8d8a6d451ed7f6fa5f162ef93d0764f3e4fb9ea022c62
7
- data.tar.gz: d470874db2a8008a5be3bafbae07161fd79ec931eb7c98414fd233bccb4778bb5a4054337aa2c677c00a5e51c17e13dd69a7eb6759c2e30f817bac7817318ed7
6
+ metadata.gz: 6750a83429e8004c6c1a46079e349c63b5b14abd6ccc35f33117f74d791030708acd9918fe45f2a78f7da9bb0f07a5f3d2a1cd8990eabceb46541d430ae13719
7
+ data.tar.gz: 104ef9be9f7dab34e823f9705595ed4ee411b2ac1ef9a92fd04e4e42861997ccf7d85705765b65c3bad833bb25fa1409fb32354a2d816cd1034f05a94a0e90d1
@@ -28,7 +28,7 @@ module CanvasSync::Concerns
28
28
  @model = model
29
29
  @map_def = map_def
30
30
  @map_def[:conflict_target] ||= []
31
- @map_def[:report_columns] ||= {}
31
+ @map_def[:columns] ||= {}
32
32
  end
33
33
 
34
34
  def self.normalize_model_name(model)
@@ -50,9 +50,9 @@ module CanvasSync::Concerns
50
50
  legacy[:report_columns][lct][:database_column_name]
51
51
  end
52
52
 
53
- m[:report_columns] = {}
53
+ m[:columns] = {}
54
54
  legacy[:report_columns].each do |rcol, opts|
55
- m[:report_columns][opts[:database_column_name]] = opts.except(:database_column_name).merge!(
55
+ m[:columns][opts[:database_column_name]] = opts.except(:database_column_name).merge!(
56
56
  report_column: rcol,
57
57
  ).freeze
58
58
  end
@@ -84,23 +84,23 @@ module CanvasSync::Concerns
84
84
  end
85
85
 
86
86
  def reset_links
87
- @map_def[:report_columns] = {}.with_indifferent_access
87
+ @map_def[:columns] = {}.with_indifferent_access
88
88
  end
89
89
 
90
90
  def unlink_column(key)
91
- @map_def[:report_columns].delete(key)
91
+ @map_def[:columns].delete(key)
92
92
  end
93
93
 
94
94
  def link_column(m, type: nil, &blk)
95
95
  if m.is_a?(Hash)
96
96
  raise "Hash should have exactly 1 entry" if m && m.count != 1
97
- @map_def[:report_columns][m.values[0]] = {
97
+ @map_def[:columns][m.values[0]] = {
98
98
  report_column: m.keys[0],
99
99
  type: type,
100
100
  transform: blk,
101
101
  }
102
102
  elsif m.is_a?(Symbol)
103
- @map_def[:report_columns][m] = {
103
+ @map_def[:columns][m] = {
104
104
  report_column: m,
105
105
  type: type,
106
106
  transform: blk,
@@ -5,9 +5,9 @@ module CanvasSync
5
5
  class Engine < ::Rails::Engine
6
6
  isolate_namespace CanvasSync
7
7
 
8
- initializer "canvas_sync.serialze_symbols" do |app|
8
+ initializer "canvas_sync.safe_yaml_classes" do |app|
9
9
  app.config.active_record.yaml_column_permitted_classes ||= []
10
- app.config.active_record.yaml_column_permitted_classes |= [Symbol]
10
+ app.config.active_record.yaml_column_permitted_classes |= [Symbol, ActiveSupport::HashWithIndifferentAccess]
11
11
  rescue
12
12
  end
13
13
 
@@ -157,13 +157,13 @@ module CanvasSync
157
157
  let_close!
158
158
  end
159
159
  else
160
- redis.hset(@bidkey, 'keep_open', true)
160
+ redis.hset(@bidkey, 'keep_open', "true")
161
161
  end
162
162
  end
163
163
 
164
164
  def let_close!
165
165
  _, failed, pending, children, complete, success = redis.multi do |r|
166
- r.hset(@bidkey, 'keep_open', false)
166
+ r.hset(@bidkey, 'keep_open', "false")
167
167
 
168
168
  r.scard("BID-#{bid}-failed")
169
169
  r.hincrby("BID-#{bid}", "pending", 0)
@@ -333,7 +333,7 @@ module CanvasSync
333
333
  opts = {"bid" => bid, "event" => event}
334
334
  should_schedule_batch = callback_args.present? && !callback_params.present?
335
335
  already_processed = redis do |r|
336
- SCHEDULE_CALLBACK.call(r, [batch_key], [event.to_s, should_schedule_batch, BID_EXPIRE_TTL])
336
+ SCHEDULE_CALLBACK.call(r, [batch_key], [event.to_s, should_schedule_batch.to_s, BID_EXPIRE_TTL])
337
337
  end
338
338
 
339
339
  return if already_processed == 'true'
@@ -0,0 +1,73 @@
1
+ module CanvasSync::Jobs
2
+ class CanvasProcessWaiter < ActiveJob::Base
3
+ # rubocop:disable Metrics/PerceivedComplexity
4
+ def perform(progress_url, next_job, kwargs = {})
5
+ kwargs = kwargs.symbolize_keys
6
+
7
+ response = canvas_sync_client.get(progress_url)
8
+ status = kwargs[:status_key].present? ? response[kwargs[:status_key]] : response['workflow_state'] || response['status']
9
+
10
+ if %w[completed complete].include? status
11
+ InvokeCallbackWorker.perform_later(build_next_job(next_job, kwargs, response)) if next_job
12
+ elsif %w[failed error].include? status
13
+ if kwargs[:on_failure].is_a?(Hash)
14
+ InvokeCallbackWorker.perform_later(build_next_job(kwargs[:on_failure], kwargs, response))
15
+ else
16
+ Rails.logger.error("Progress #{progress_url} failed")
17
+ end
18
+ else # if status == 'queued' || status == 'running'
19
+ interval = kwargs[:interval] || (Rails.env.development? ? 3 : 60)
20
+ CanvasProcessWaiter.set(wait: interval).perform_later(progress_url, next_job, kwargs)
21
+ end
22
+ end
23
+ # rubocop:enable Metrics/PerceivedComplexity
24
+
25
+ def build_next_job(job, kwargs, response)
26
+ job = job.symbolize_keys
27
+ if kwargs[:progress_as].present?
28
+ job[:kwargs] ||= {}
29
+ job[:kwargs][kwargs[:progress_as].to_sym] = response
30
+ end
31
+ job
32
+ end
33
+
34
+ # This is a separate job so that, if it fails and a retry is triggered, it doesn't query the API needlessly
35
+ class InvokeCallbackWorker < ActiveJob::Base
36
+ # rubocop:disable Metrics/PerceivedComplexity
37
+ def perform(job)
38
+ job = job.symbolize_keys
39
+
40
+ params = job[:args] || []
41
+ params << job[:kwargs].symbolize_keys if job[:kwargs]
42
+ # params[-1] = params[-1].symbolize_keys if params[-1].is_a?(Hash)
43
+
44
+ if job[:model]
45
+ model_class = load_constant(job[:model])
46
+ find_by = job[:find_by]
47
+ target = find_by.is_a?(Hash) ? model_class.find_by(find_by) : model_class.find_by(id: find_by)
48
+ target.send(job[:method], *params)
49
+ elsif job[:class]
50
+ target = load_constant(job[:class])
51
+ target.send(job[:method], *params)
52
+ elsif job[:instance_of]
53
+ target = load_constant(job[:instance_of]).new
54
+ target.send(job[:method], *params)
55
+ elsif job[:job]
56
+ job_class = load_constant(job[:job])
57
+ job_class = job_class.set(job[:options]) if job[:options].present?
58
+ if job_class < ActiveJob::Base
59
+ job_class.perform_later(*params)
60
+ else
61
+ job_class.perform_async(*params)
62
+ end
63
+ end
64
+ end
65
+ # rubocop:enable Metrics/PerceivedComplexity
66
+
67
+ def load_constant(const)
68
+ const = const.constantize if const.is_a?(String)
69
+ const
70
+ end
71
+ end
72
+ end
73
+ end
@@ -8,6 +8,10 @@ module CanvasSync
8
8
  COMPILATION_TIMEOUT = 1.hour
9
9
  MAX_TRIES = 3
10
10
 
11
+ class FatalReportError < ::RuntimeError; end
12
+
13
+ discard_on FatalReportError
14
+
11
15
  # @param report_name [Hash] e.g., 'provisioning_csv'
12
16
  # @param report_id [Integer]
13
17
  # @param processor [String] a stringified report processor class name
@@ -36,21 +40,21 @@ module CanvasSync
36
40
  Rails.logger.error(message)
37
41
  if failed_attempts >= max_tries
38
42
  Rails.logger.error("This report has failed #{failed_attempts} times. Giving up.")
39
- raise message
43
+ raise FatalReportError, message
40
44
  else
41
45
  restart_report(options, report_name, processor, checker_context)
42
46
  end
43
47
  else
44
48
  report_timeout = parse_timeout(options[:report_timeout] || batch_context[:report_timeout] || REPORT_TIMEOUT)
45
49
  if timeout_met?(options[:sync_start_time], report_timeout)
46
- raise "Report appears to be stuck #{report_name}##{report_id}"
50
+ raise FatalReportError, "Report appears to be stuck #{report_name}##{report_id}"
47
51
  end
48
52
 
49
53
  if report_status["status"].downcase == 'compiling'
50
54
  checker_context['compiling_since'] ||= DateTime.now.iso8601
51
55
  compilation_timeout = parse_timeout(options[:report_compilation_timeout] || batch_context[:report_compilation_timeout] || COMPILATION_TIMEOUT)
52
56
  if timeout_met?(checker_context['compiling_since'], compilation_timeout)
53
- raise "Report appears to be stuck #{report_name}##{report_id}"
57
+ raise FatalReportError, "Report appears to be stuck #{report_name}##{report_id}"
54
58
  end
55
59
  end
56
60
 
@@ -10,12 +10,22 @@ module CanvasSync
10
10
  options[:models].each do |model|
11
11
  # group_membership is the only model param that is singular :(
12
12
  model = 'group_membership' if model == 'group_memberships'
13
+
13
14
  params[model] = true
14
15
  end
15
16
 
17
+ merged_params = merge_report_params(options, params, {}).with_indifferent_access
18
+
19
+ # Make sure the report also checks last_activity_at when checking updated_at
20
+ if options[:models].include?("enrollments")
21
+ if (%w[last_activity_at total_activity_time] & Enrollment.get_sync_mapping[:columns].keys).present? && merged_params.dig(:parameters, :include_last_activity) == nil
22
+ merged_params[:parameters][:include_last_activity] = true
23
+ end
24
+ end
25
+
16
26
  super(
17
27
  "proservices_provisioning_csv",
18
- merge_report_params(options, params, {}),
28
+ merged_params,
19
29
  CanvasSync::Processors::ProvisioningReportProcessor.to_s,
20
30
  options,
21
31
  )
@@ -16,10 +16,9 @@ module CanvasSync
16
16
  m = mapping[options[:mapping].to_sym]
17
17
  CanvasSync::Importers::BulkImporter.import(
18
18
  report_file_path,
19
- m[:report_columns],
19
+ m[:columns],
20
20
  options[:klass].constantize,
21
21
  m[:conflict_target],
22
- import_args: options
23
22
  )
24
23
  end
25
24
  end
@@ -16,7 +16,7 @@ module CanvasSync
16
16
  m = mapping_for(model, mapping_key)
17
17
  CanvasSync::Importers::BulkImporter.import(
18
18
  report_file_path,
19
- m[:report_columns],
19
+ m[:columns],
20
20
  model,
21
21
  m[:conflict_target],
22
22
  import_args: options,
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.17.40".freeze
2
+ VERSION = "0.17.41".freeze
3
3
  end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe CanvasSync::Jobs::CanvasProcessWaiter do
4
+ let!(:worker) { CanvasSync::Jobs::CanvasProcessWaiter.new }
5
+
6
+ describe 'perform' do
7
+ it 'queues a InvokeCallbackWorker when complete' do
8
+ job = {
9
+ args: [1, 2],
10
+ kwargs: { progress: anything },
11
+ }
12
+ allow_any_instance_of(Bearcat::Client).to receive(:get).and_return('workflow_state' => 'completed')
13
+ expect(CanvasSync::Jobs::CanvasProcessWaiter::InvokeCallbackWorker).to receive(:perform_later).with(job)
14
+ worker.perform('/blah/', job)
15
+ end
16
+
17
+ it 'invokes the on_failure callback if failed' do
18
+ job = {
19
+ args: [1, 2],
20
+ kwargs: { progress: anything },
21
+ }
22
+ allow_any_instance_of(Bearcat::Client).to receive(:get).and_return('workflow_state' => 'failed')
23
+ expect(CanvasSync::Jobs::CanvasProcessWaiter::InvokeCallbackWorker).to receive(:perform_later).with(job)
24
+ worker.perform('/blah/', nil, on_failure: job)
25
+ end
26
+
27
+ it 're-enqueues if incomplete' do
28
+ ActiveJob::Base.queue_adapter = :test
29
+ allow_any_instance_of(Bearcat::Client).to receive(:get).and_return('workflow_state' => 'pending')
30
+ worker.perform('/blah/', nil, interval: 13)
31
+ expect(CanvasSync::Jobs::CanvasProcessWaiter).to have_been_enqueued.once.with('/blah/', nil, interval: 13)
32
+ end
33
+ end
34
+
35
+ describe 'InvokeCallbackWorker' do
36
+ let!(:worker) { CanvasSync::Jobs::CanvasProcessWaiter::InvokeCallbackWorker.new }
37
+
38
+ with_model :Model do
39
+ table
40
+ model do
41
+ def wait_callback(*args); end
42
+
43
+ def self.wait_callback(*args); end
44
+ end
45
+ end
46
+
47
+ class CPW_TestWorker
48
+ extend Sidekiq::Worker
49
+ end
50
+
51
+ it 'schedules a given job' do
52
+ expect(CPW_TestWorker).to receive(:perform_async)
53
+ worker.perform(
54
+ job: 'CPW_TestWorker',
55
+ args: [1, 2],
56
+ )
57
+ end
58
+
59
+ it 'invokes a model method' do
60
+ model = Model.create!
61
+ expect(Model).to receive(:find_by).with(id: model.id).and_return(model)
62
+ expect(model).to receive(:wait_callback).with(1, 2, a: 3, b: 4)
63
+ worker.perform(
64
+ model: Model.to_s,
65
+ find_by: { id: model.id },
66
+ method: :wait_callback,
67
+ args: [1, 2],
68
+ kwargs: { a: 3, b: 4 },
69
+ )
70
+ end
71
+
72
+ it 'invokes a class method' do
73
+ expect(Model).to receive(:wait_callback).with(1, 2, a: 3, b: 4)
74
+ worker.perform(
75
+ class: Model.to_s,
76
+ method: :wait_callback,
77
+ args: [1, 2],
78
+ kwargs: { a: 3, b: 4 },
79
+ )
80
+ end
81
+ end
82
+ end
@@ -2260,3 +2260,196 @@ Migrating to CreateUsers (20220926221926)
2260
2260
   (1.2ms) COMMIT
2261
2261
   (0.2ms) SELECT pg_advisory_unlock(1438354376499275445)
2262
2262
   (0.3ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
2263
+  (1.1ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
2264
+  (0.8ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 [["key", "environment"]]
2265
+  (0.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
2266
+  (0.2ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 [["key", "environment"]]
2267
+  (0.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
2268
+  (0.2ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 [["key", "environment"]]
2269
+  (48.4ms) DROP DATABASE IF EXISTS "canvas_sync_development"
2270
+  (49.8ms) DROP DATABASE IF EXISTS "canvas_sync_test"
2271
+  (133.7ms) CREATE DATABASE "canvas_sync_development" ENCODING = 'unicode'
2272
+  (105.4ms) CREATE DATABASE "canvas_sync_test" ENCODING = 'unicode'
2273
+  (11.6ms) CREATE TABLE "schema_migrations" ("version" character varying NOT NULL PRIMARY KEY)
2274
+  (8.8ms) CREATE TABLE "ar_internal_metadata" ("key" character varying NOT NULL PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2275
+  (0.1ms) SELECT pg_try_advisory_lock(1438354376499275445)
2276
+  (0.4ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
2277
+ Migrating to CreateCanvasSyncJobLog (20170915210836)
2278
+  (0.2ms) BEGIN
2279
+  (8.8ms) CREATE TABLE "canvas_sync_job_logs" ("id" serial NOT NULL PRIMARY KEY, "started_at" timestamp, "completed_at" timestamp, "exception" character varying, "backtrace" text, "job_class" character varying, "status" character varying, "metadata" text, "job_arguments" text, "created_at" timestamp, "updated_at" timestamp)
2280
+ ActiveRecord::SchemaMigration Create (0.5ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20170915210836"]]
2281
+  (1.2ms) COMMIT
2282
+ Migrating to AddJobIdToCanvasSyncJobLogs (20180725155729)
2283
+  (0.2ms) BEGIN
2284
+  (0.4ms) ALTER TABLE "canvas_sync_job_logs" ADD "job_id" character varying
2285
+  (3.9ms) CREATE INDEX "index_canvas_sync_job_logs_on_job_id" ON "canvas_sync_job_logs" ("job_id")
2286
+ ActiveRecord::SchemaMigration Create (0.5ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20180725155729"]]
2287
+  (1.3ms) COMMIT
2288
+ Migrating to CreateCourses (20190702203621)
2289
+  (0.2ms) BEGIN
2290
+  (10.3ms) CREATE TABLE "courses" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "sis_id" character varying, "course_code" character varying, "name" character varying, "workflow_state" character varying, "canvas_account_id" integer, "canvas_term_id" integer, "start_at" timestamp, "end_at" timestamp, "grading_standard_id" bigint, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2291
+  (5.4ms) CREATE UNIQUE INDEX "index_courses_on_canvas_id" ON "courses" ("canvas_id")
2292
+ ActiveRecord::SchemaMigration Create (0.5ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190702203621"]]
2293
+  (1.2ms) COMMIT
2294
+ Migrating to CreateAccounts (20190702203622)
2295
+  (0.2ms) BEGIN
2296
+  (9.6ms) CREATE TABLE "accounts" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "sis_id" character varying, "canvas_parent_account_id" bigint, "sis_parent_account_id" character varying, "name" character varying, "workflow_state" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2297
+  (4.0ms) CREATE UNIQUE INDEX "index_accounts_on_canvas_id" ON "accounts" ("canvas_id")
2298
+ ActiveRecord::SchemaMigration Create (0.5ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190702203622"]]
2299
+  (1.3ms) COMMIT
2300
+ Migrating to CreateTerms (20190702203623)
2301
+  (0.3ms) BEGIN
2302
+  (8.1ms) CREATE TABLE "terms" ("id" bigserial primary key, "canvas_id" integer NOT NULL, "name" character varying, "start_at" timestamp, "end_at" timestamp, "workflow_state" character varying, "grading_period_group_id" integer, "sis_id" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2303
+  (4.1ms) CREATE UNIQUE INDEX "index_terms_on_canvas_id" ON "terms" ("canvas_id")
2304
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190702203623"]]
2305
+  (1.2ms) COMMIT
2306
+ Migrating to CreateEnrollments (20190702203624)
2307
+  (0.2ms) BEGIN
2308
+  (9.2ms) CREATE TABLE "enrollments" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "canvas_course_id" bigint, "course_sis_id" character varying, "canvas_user_id" bigint, "user_sis_id" character varying, "role" character varying, "canvas_role_id" integer, "canvas_section_id" bigint, "workflow_state" character varying, "base_role_type" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2309
+  (3.8ms) CREATE UNIQUE INDEX "index_enrollments_on_canvas_id" ON "enrollments" ("canvas_id")
2310
+  (3.8ms) CREATE INDEX "index_enrollments_on_canvas_course_id" ON "enrollments" ("canvas_course_id")
2311
+  (4.1ms) CREATE INDEX "index_enrollments_on_canvas_user_id" ON "enrollments" ("canvas_user_id")
2312
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190702203624"]]
2313
+  (1.2ms) COMMIT
2314
+ Migrating to CreateSections (20190702203625)
2315
+  (0.2ms) BEGIN
2316
+  (9.7ms) CREATE TABLE "sections" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "sis_id" character varying, "canvas_course_id" bigint, "canvas_nonxlist_course_id" bigint, "name" character varying, "workflow_state" character varying, "start_at" timestamp, "end_at" timestamp, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2317
+  (4.0ms) CREATE UNIQUE INDEX "index_sections_on_canvas_id" ON "sections" ("canvas_id")
2318
+  (3.6ms) CREATE INDEX "index_sections_on_canvas_course_id" ON "sections" ("canvas_course_id")
2319
+ ActiveRecord::SchemaMigration Create (0.5ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190702203625"]]
2320
+  (1.3ms) COMMIT
2321
+ Migrating to CreateAssignments (20190702203626)
2322
+  (0.3ms) BEGIN
2323
+  (9.0ms) CREATE TABLE "assignments" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "title" character varying, "description" text, "due_at" timestamp, "unlock_at" timestamp, "lock_at" timestamp, "points_possible" float, "min_score" float, "max_score" float, "mastery_score" float, "grading_type" character varying, "submission_types" character varying, "workflow_state" character varying, "canvas_context_id" integer, "canvas_context_type" character varying, "canvas_assignment_group_id" integer, "canvas_grading_scheme_id" integer, "canvas_grading_standard_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2324
+  (3.8ms) CREATE UNIQUE INDEX "index_assignments_on_canvas_id" ON "assignments" ("canvas_id")
2325
+  (3.9ms) CREATE INDEX "index_assignments_on_canvas_context_id_and_canvas_context_type" ON "assignments" ("canvas_context_id", "canvas_context_type")
2326
+ ActiveRecord::SchemaMigration Create (0.3ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190702203626"]]
2327
+  (1.3ms) COMMIT
2328
+ Migrating to CreateSubmissions (20190702203627)
2329
+  (0.2ms) BEGIN
2330
+  (9.0ms) CREATE TABLE "submissions" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "canvas_course_id" bigint, "canvas_assignment_id" bigint, "canvas_user_id" bigint, "submitted_at" timestamp, "due_at" timestamp, "graded_at" timestamp, "score" float, "points_possible" float, "excused" boolean, "workflow_state" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2331
+  (3.9ms) CREATE UNIQUE INDEX "index_submissions_on_canvas_id" ON "submissions" ("canvas_id")
2332
+  (3.7ms) CREATE INDEX "index_submissions_on_canvas_assignment_id" ON "submissions" ("canvas_assignment_id")
2333
+  (3.9ms) CREATE INDEX "index_submissions_on_canvas_course_id" ON "submissions" ("canvas_course_id")
2334
+  (3.9ms) CREATE INDEX "index_submissions_on_canvas_user_id" ON "submissions" ("canvas_user_id")
2335
+ ActiveRecord::SchemaMigration Create (0.3ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190702203627"]]
2336
+  (1.2ms) COMMIT
2337
+ Migrating to CreateAssignmentGroups (20190702203630)
2338
+  (0.2ms) BEGIN
2339
+  (9.0ms) CREATE TABLE "assignment_groups" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "canvas_course_id" bigint, "name" character varying, "rules" text, "position" integer, "group_weight" float, "workflow_state" character varying, "canvas_created_at" timestamp, "canvas_updated_at" timestamp, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2340
+  (3.8ms) CREATE UNIQUE INDEX "index_assignment_groups_on_canvas_id" ON "assignment_groups" ("canvas_id")
2341
+  (3.9ms) CREATE INDEX "index_assignment_groups_on_canvas_course_id" ON "assignment_groups" ("canvas_course_id")
2342
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190702203630"]]
2343
+  (1.3ms) COMMIT
2344
+ Migrating to CreateContextModules (20190702203631)
2345
+  (0.2ms) BEGIN
2346
+  (10.4ms) CREATE TABLE "context_modules" ("id" bigserial primary key, "canvas_id" bigint, "canvas_context_id" bigint, "canvas_context_type" character varying, "position" integer, "name" character varying, "workflow_state" character varying, "deleted_at" timestamp, "unlock_at" timestamp, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2347
+  (4.1ms) CREATE UNIQUE INDEX "index_context_modules_on_canvas_id" ON "context_modules" ("canvas_id")
2348
+  (3.8ms) CREATE INDEX "index_context_modules_on_context" ON "context_modules" ("canvas_context_id", "canvas_context_type")
2349
+ ActiveRecord::SchemaMigration Create (0.3ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190702203631"]]
2350
+  (1.3ms) COMMIT
2351
+ Migrating to CreateContextModuleItems (20190702203632)
2352
+  (0.2ms) BEGIN
2353
+  (10.0ms) CREATE TABLE "context_module_items" ("id" bigserial primary key, "canvas_id" bigint, "canvas_context_module_id" bigint, "position" integer, "canvas_content_id" bigint, "canvas_content_type" character varying, "canvas_assignment_id" bigint, "workflow_state" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2354
+  (3.8ms) CREATE UNIQUE INDEX "index_context_module_items_on_canvas_id" ON "context_module_items" ("canvas_id")
2355
+  (3.9ms) CREATE INDEX "index_context_module_items_on_canvas_context_module_id" ON "context_module_items" ("canvas_context_module_id")
2356
+ ActiveRecord::SchemaMigration Create (0.5ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190702203632"]]
2357
+  (1.5ms) COMMIT
2358
+ Migrating to AddForkCountToCanvasSyncJobLogs (20190916154829)
2359
+  (0.3ms) BEGIN
2360
+  (0.4ms) ALTER TABLE "canvas_sync_job_logs" ADD "fork_count" integer
2361
+ ActiveRecord::SchemaMigration Create (0.3ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190916154829"]]
2362
+  (1.0ms) COMMIT
2363
+ Migrating to CreateRoles (20190927204545)
2364
+  (0.1ms) BEGIN
2365
+  (8.8ms) CREATE TABLE "roles" ("id" bigserial primary key, "canvas_id" integer NOT NULL, "label" character varying, "base_role_type" character varying, "canvas_account_id" integer, "workflow_state" character varying, "permissions" json, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2366
+  (3.6ms) CREATE UNIQUE INDEX "index_roles_on_canvas_id" ON "roles" ("canvas_id")
2367
+  (3.8ms) CREATE INDEX "index_roles_on_canvas_account_id" ON "roles" ("canvas_account_id")
2368
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190927204545"]]
2369
+  (1.4ms) COMMIT
2370
+ Migrating to CreateAdmins (20190927204546)
2371
+  (0.2ms) BEGIN
2372
+  (8.5ms) CREATE TABLE "admins" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "role_name" character varying, "canvas_account_id" bigint, "canvas_role_id" bigint, "canvas_user_id" bigint, "workflow_state" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2373
+  (3.9ms) CREATE UNIQUE INDEX "index_admins_on_canvas_id" ON "admins" ("canvas_id")
2374
+  (3.6ms) CREATE INDEX "index_admins_on_canvas_role_id" ON "admins" ("canvas_role_id")
2375
+  (4.1ms) CREATE INDEX "index_admins_on_canvas_user_id" ON "admins" ("canvas_user_id")
2376
+  (3.7ms) CREATE INDEX "index_admins_on_canvas_account_id" ON "admins" ("canvas_account_id")
2377
+ ActiveRecord::SchemaMigration Create (0.6ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20190927204546"]]
2378
+  (1.5ms) COMMIT
2379
+ Migrating to CreateGroups (20200415171620)
2380
+  (0.3ms) BEGIN
2381
+  (9.3ms) CREATE TABLE "groups" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "sis_id" character varying, "canvas_group_category_id" bigint, "group_category_sis_id" character varying, "canvas_account_id" bigint, "canvas_course_id" bigint, "name" character varying, "workflow_state" character varying, "context_id" bigint, "context_type" character varying, "max_membership" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2382
+  (3.8ms) CREATE UNIQUE INDEX "index_groups_on_canvas_id" ON "groups" ("canvas_id")
2383
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20200415171620"]]
2384
+  (1.4ms) COMMIT
2385
+ Migrating to CreateGroupMemberships (20200416214248)
2386
+  (0.2ms) BEGIN
2387
+  (14.1ms) CREATE TABLE "group_memberships" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "canvas_user_id" bigint NOT NULL, "canvas_group_id" bigint NOT NULL, "group_sis_id" character varying, "user_sis_id" character varying, "workflow_state" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2388
+  (3.6ms) CREATE UNIQUE INDEX "index_group_memberships_on_canvas_id" ON "group_memberships" ("canvas_id")
2389
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20200416214248"]]
2390
+  (1.7ms) COMMIT
2391
+ Migrating to CreatePseudonyms (20201016181346)
2392
+  (0.3ms) BEGIN
2393
+  (9.1ms) CREATE TABLE "pseudonyms" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "canvas_user_id" bigint, "sis_id" character varying, "unique_id" character varying, "workflow_state" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2394
+  (3.9ms) CREATE UNIQUE INDEX "index_pseudonyms_on_canvas_id" ON "pseudonyms" ("canvas_id")
2395
+  (3.6ms) CREATE INDEX "index_pseudonyms_on_canvas_user_id" ON "pseudonyms" ("canvas_user_id")
2396
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20201016181346"]]
2397
+  (1.3ms) COMMIT
2398
+ Migrating to CreateCanvasSyncSyncBatches (20201018210836)
2399
+  (0.2ms) BEGIN
2400
+  (8.7ms) CREATE TABLE "canvas_sync_sync_batches" ("id" serial NOT NULL PRIMARY KEY, "started_at" timestamp, "completed_at" timestamp, "status" character varying, "created_at" timestamp, "updated_at" timestamp)
2401
+ ActiveRecord::SchemaMigration Create (0.3ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20201018210836"]]
2402
+  (1.2ms) COMMIT
2403
+ Migrating to AddFullSyncToCanvasSyncSyncBatch (20201030210836)
2404
+  (0.2ms) BEGIN
2405
+  (0.6ms) ALTER TABLE "canvas_sync_sync_batches" ADD "full_sync" boolean DEFAULT FALSE
2406
+  (0.5ms) ALTER TABLE "canvas_sync_sync_batches" ADD "batch_genre" character varying
2407
+  (0.7ms) ALTER TABLE "canvas_sync_sync_batches" ADD "batch_bid" character varying
2408
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20201030210836"]]
2409
+  (1.5ms) COMMIT
2410
+ Migrating to CreateUserObservers (20210907233329)
2411
+  (0.2ms) BEGIN
2412
+  (9.8ms) CREATE TABLE "user_observers" ("id" bigserial primary key, "observing_user_id" bigint, "observed_user_id" bigint, "workflow_state" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2413
+  (4.1ms) CREATE UNIQUE INDEX "index_user_observers_on_observed_user_id_and_observing_user_id" ON "user_observers" ("observed_user_id", "observing_user_id")
2414
+  (4.0ms) CREATE INDEX "index_user_observers_on_observing_user_id" ON "user_observers" ("observing_user_id")
2415
+  (3.9ms) CREATE INDEX "index_user_observers_on_observed_user_id" ON "user_observers" ("observed_user_id")
2416
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20210907233329"]]
2417
+  (1.4ms) COMMIT
2418
+ Migrating to CreateGradingPeriods (20210907233330)
2419
+  (0.3ms) BEGIN
2420
+  (9.8ms) CREATE TABLE "grading_periods" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "title" character varying, "weight" float, "start_date" timestamp, "end_date" timestamp, "close_date" timestamp, "canvas_grading_period_group_id" bigint, "workflow_state" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2421
+  (4.3ms) CREATE UNIQUE INDEX "index_grading_periods_on_canvas_id" ON "grading_periods" ("canvas_id")
2422
+  (4.0ms) CREATE INDEX "index_grading_periods_on_canvas_grading_period_group_id" ON "grading_periods" ("canvas_grading_period_group_id")
2423
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20210907233330"]]
2424
+  (1.3ms) COMMIT
2425
+ Migrating to CreateGradingPeriodGroups (20211001184920)
2426
+  (0.3ms) BEGIN
2427
+  (10.1ms) CREATE TABLE "grading_period_groups" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "title" character varying, "weighted" boolean, "display_totals_for_all_grading_periods" boolean, "workflow_state" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2428
+  (4.0ms) CREATE UNIQUE INDEX "index_grading_period_groups_on_canvas_id" ON "grading_period_groups" ("canvas_id")
2429
+ ActiveRecord::SchemaMigration Create (0.6ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20211001184920"]]
2430
+  (1.2ms) COMMIT
2431
+ Migrating to CreateContentMigrations (20220308072643)
2432
+  (0.2ms) BEGIN
2433
+  (10.7ms) CREATE TABLE "content_migrations" ("id" bigserial primary key, "canvas_id" bigint, "canvas_context_id" bigint, "canvas_context_type" character varying, "workflow_state" character varying, "migration_settings" text, "started_at" timestamp, "finished_at" timestamp, "progress" float, "canvas_source_course_id" bigint, "migration_type" character varying, "canvas_child_subscription_id" bigint, "canvas_root_account_id" bigint, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2434
+  (4.1ms) CREATE UNIQUE INDEX "index_content_migrations_on_canvas_id" ON "content_migrations" ("canvas_id")
2435
+ ActiveRecord::SchemaMigration Create (0.7ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20220308072643"]]
2436
+  (1.5ms) COMMIT
2437
+ Migrating to CreateLearningOutcomes (20220712210559)
2438
+  (0.3ms) BEGIN
2439
+  (10.5ms) CREATE TABLE "learning_outcomes" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "canvas_context_id" integer, "canvas_context_type" character varying, "name" character varying, "friendly_name" character varying, "workflow_state" character varying, "canvas_created_at" timestamp, "canvas_updated_at" timestamp, "migration_id" character varying, "vendor_guid" character varying, "low_grade" character varying, "high_grade" character varying, "calculation_method" character varying, "calculation_int" character varying, "outcome_import_id" integer, "root_account_ids" integer[] DEFAULT '{}', "description" text, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2440
+  (4.0ms) CREATE UNIQUE INDEX "index_learning_outcomes_on_canvas_id" ON "learning_outcomes" ("canvas_id")
2441
+  (3.9ms) CREATE INDEX "index_learning_outcomes_on_context" ON "learning_outcomes" ("canvas_context_id", "canvas_context_type")
2442
+ ActiveRecord::SchemaMigration Create (0.5ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20220712210559"]]
2443
+  (1.4ms) COMMIT
2444
+ Migrating to CreateUsers (20220926221926)
2445
+  (0.3ms) BEGIN
2446
+  (9.6ms) CREATE TABLE "users" ("id" bigserial primary key, "canvas_id" bigint NOT NULL, "email" character varying, "first_name" character varying, "last_name" character varying, "workflow_state" character varying, "login_id" character varying, "name" character varying, "sortable_name" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
2447
+  (4.0ms) CREATE UNIQUE INDEX "index_users_on_canvas_id" ON "users" ("canvas_id")
2448
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20220926221926"]]
2449
+  (1.4ms) COMMIT
2450
+ ActiveRecord::InternalMetadata Load (0.5ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2 [["key", "environment"], ["LIMIT", 1]]
2451
+  (0.4ms) BEGIN
2452
+ ActiveRecord::InternalMetadata Create (0.6ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "key" [["key", "environment"], ["value", "development"], ["created_at", "2022-12-12 21:35:40.947063"], ["updated_at", "2022-12-12 21:35:40.947063"]]
2453
+  (1.3ms) COMMIT
2454
+  (0.3ms) SELECT pg_advisory_unlock(1438354376499275445)
2455
+  (0.3ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC