Migrate legacy moderated graders to new moderation_graders table
fixes GRADE-1020 test plan: migrations run and specs pass Change-Id: I03ee7f87139b5d5373e7c62942670741f50d9ff1 Reviewed-on: https://gerrit.instructure.com/152299 Reviewed-by: Adrian Packel <apackel@instructure.com> Reviewed-by: Spencer Olson <solson@instructure.com> Tested-by: Jenkins QA-Review: Neil Gupta <ngupta@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
This commit is contained in:
parent
bd08854581
commit
c9b6791e1f
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# Copyright (C) 2018 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
class BackfillModerationGraders < ActiveRecord::Migration[5.0]
|
||||
tag :postdeploy
|
||||
|
||||
def self.up
|
||||
Assignment.where(moderated_grading: true).where("grader_count = 0 or grader_count is null").find_ids_in_ranges do |start_at, end_at|
|
||||
DataFixup::BackfillModerationGraders.send_later_if_production_enqueue_args(
|
||||
:run,
|
||||
{
|
||||
priority: Delayed::LOW_PRIORITY,
|
||||
n_strand: ["DataFixup::BackfillModerationGraders", Shard.current.database_server.id]
|
||||
},
|
||||
start_at,
|
||||
end_at
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,79 @@
|
|||
#
|
||||
# Copyright (C) 2018 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
module DataFixup::BackfillModerationGraders
|
||||
def self.run(start_at, end_at)
|
||||
assignments = Assignment.where(id: start_at..end_at).where(moderated_grading: true).where("grader_count = 0 or grader_count is null")
|
||||
|
||||
courses = assignments.distinct.pluck(:context_id)
|
||||
return if courses.blank?
|
||||
|
||||
# Find all provisional graders for this batch of assignments
|
||||
graders = ModeratedGrading::ProvisionalGrade.joins(:submission).
|
||||
where("submissions.assignment_id IN (?)", assignments.select(:id)).
|
||||
pluck("distinct submissions.assignment_id, moderated_grading_provisional_grades.scorer_id")
|
||||
created_at = Time.zone.now
|
||||
|
||||
Assignment.transaction do
|
||||
unless graders.blank?
|
||||
# generate unique anonymous ids for each grader
|
||||
existing_anonymous_ids = Hash.new { |hsh, key| hsh[key] = [] }
|
||||
graders.map! do |assignment_id, grader_id|
|
||||
anonymous_id = Anonymity.generate_id(existing_ids: existing_anonymous_ids[assignment_id])
|
||||
existing_anonymous_ids[assignment_id] << anonymous_id
|
||||
{
|
||||
anonymous_id: anonymous_id,
|
||||
assignment_id: assignment_id,
|
||||
user_id: grader_id,
|
||||
created_at: created_at,
|
||||
updated_at: created_at
|
||||
}
|
||||
end
|
||||
ModerationGrader.bulk_insert(graders)
|
||||
|
||||
existing_anonymous_ids.each do |assignment_id, grader_ids|
|
||||
Assignment.where(id: assignment_id).update_all(grader_count: [grader_ids.length, 2].max, updated_at: created_at)
|
||||
end
|
||||
end
|
||||
|
||||
# update remaining assignments with default 2 grader count
|
||||
assignments.update_all(grader_count: 2, updated_at: created_at)
|
||||
|
||||
# Turn on moderated_grading feature flag for all courses of these assignments
|
||||
courses.map! do |course_id|
|
||||
vals = [
|
||||
Course.connection.quote(course_id),
|
||||
Course.connection.quote('Course'),
|
||||
Course.connection.quote('moderated_grading'),
|
||||
Course.connection.quote('on'),
|
||||
Course.connection.quote(created_at),
|
||||
Course.connection.quote(created_at)
|
||||
]
|
||||
"(#{vals.join(',')})"
|
||||
end
|
||||
ActiveRecord::Base.connection.exec_insert <<~SQL
|
||||
INSERT INTO #{FeatureFlag.quoted_table_name}
|
||||
(context_id, context_type, feature, state, created_at, updated_at) VALUES #{courses.join(',')}
|
||||
ON CONFLICT (context_id, context_type, feature) DO UPDATE SET
|
||||
state = excluded.state,
|
||||
updated_at = excluded.updated_at
|
||||
WHERE feature_flags.state <> excluded.state
|
||||
SQL
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,84 @@
|
|||
#
|
||||
# Copyright (C) 2018 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe DataFixup::BackfillModerationGraders do
|
||||
before(:once) do
|
||||
@root_account = account_model
|
||||
@root_account.enable_feature!(:anonymous_moderated_marking)
|
||||
course_factory(account: @root_account)
|
||||
@student = User.create!
|
||||
@course.enroll_student(@student)
|
||||
@teacher = User.create!
|
||||
@course.enroll_teacher(@teacher)
|
||||
@assignment = @course.assignments.create!(title: 'test')
|
||||
@assignment.update_columns(moderated_grading: true, grader_count: 1)
|
||||
@assignment.grade_student(@student, grade: 90, provisional: true, grader: @teacher)
|
||||
|
||||
ModerationGrader.delete_all
|
||||
@assignment.update_columns(grader_count: 0)
|
||||
end
|
||||
|
||||
def do_backfill
|
||||
DataFixup::BackfillModerationGraders.run(@assignment.id, @assignment.id+1)
|
||||
end
|
||||
private :do_backfill
|
||||
|
||||
context "when an assignment has moderated grading disabled" do
|
||||
before(:once) do
|
||||
@assignment.update_columns(moderated_grading: false)
|
||||
end
|
||||
|
||||
it "does not enable Moderated Grading feature flag" do
|
||||
do_backfill
|
||||
expect(@course).not_to be_feature_enabled(:moderated_grading)
|
||||
end
|
||||
|
||||
it "does not set assignments to be anonymously graded" do
|
||||
do_backfill
|
||||
expect(@assignment.reload.grader_count).to eq 0
|
||||
end
|
||||
end
|
||||
|
||||
context "when an assignment has moderated grading enabled" do
|
||||
it "enables Moderated Grading feature flag for the course" do
|
||||
do_backfill
|
||||
expect(@course).to be_feature_enabled(:moderated_grading)
|
||||
end
|
||||
|
||||
it "creates moderation grader for the assignment" do
|
||||
expect { do_backfill }.to change { @assignment.moderation_graders.count }.by(1)
|
||||
end
|
||||
|
||||
it "updates grader count" do
|
||||
do_backfill
|
||||
expect(@assignment.reload.grader_count).to eq 2
|
||||
end
|
||||
|
||||
it "creates anonymous id for moderation grader" do
|
||||
do_backfill
|
||||
expect(@assignment.moderation_graders.first.user_id).to eq @teacher.id
|
||||
expect(@assignment.moderation_graders.first.anonymous_id).not_to be_nil
|
||||
end
|
||||
|
||||
it "re-running fixup is ok" do
|
||||
do_backfill
|
||||
expect { do_backfill }.not_to raise_exception
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue