improve outcome rollup performance with mastery scales

- passes mastery scale info as params rather than
  passing context for RollupScore to query

closes OUT-4087
flag=account_level_mastery_scales

Test plan:
- verify rollups work as intended in lmgb
- verify performance for a reasonable number of
  students and outcomes

Change-Id: Idae8fb535933e4fa533409189ea98904d8429671
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/253117
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Pat Renner <prenner@instructure.com>
Reviewed-by: Augusto Callejas <acallejas@instructure.com>
QA-Review: Pat Renner <prenner@instructure.com>
Product-Review: Michael Brewer-Davis <mbd@instructure.com>
This commit is contained in:
Michael Brewer-Davis 2020-11-18 16:11:51 -06:00 committed by Michael Brewer-Davis
parent 35b872f330
commit ce22a6b653
2 changed files with 26 additions and 10 deletions

View File

@ -24,24 +24,23 @@ class RollupScore
attr_reader :outcome_results, :outcome, :score, :count, :title, :submitted_at, :hide_points
def initialize(outcome_results:, opts: {}, context: nil)
def initialize(outcome_results:, opts: {})
@outcome_results = outcome_results
@aggregate = opts[:aggregate_score]
@median = opts[:aggregate_stat] == 'median'
@outcome = @outcome_results.first.learning_outcome
@count = @outcome_results.size
if context.is_a?(Course) && context.root_account.feature_enabled?(:account_level_mastery_scales) && context.resolved_outcome_proficiency.present?
ratings = context.resolved_outcome_proficiency
@points_possible = ratings.points_possible
@mastery_points = ratings.mastery_points
if opts[:points_possible].present?
@points_possible = opts[:points_possible]
@mastery_points = opts[:mastery_points]
else
@points_possible = @outcome.rubric_criterion[:points_possible]
@mastery_points = @outcome.rubric_criterion[:mastery_points]
end
if context.is_a?(Course) && context.root_account.feature_enabled?(:account_level_mastery_scales) && context.resolved_outcome_calculation_method
@calculation_method = context.resolved_outcome_calculation_method.calculation_method
@calculation_int = context.resolved_outcome_calculation_method.calculation_int
if opts[:calculation_method].present?
@calculation_method = opts[:calculation_method]
@calculation_int = opts[:calculation_int]
else
@calculation_method = @outcome.calculation_method || "highest"
@calculation_int = @outcome.calculation_int

View File

@ -102,8 +102,9 @@ module Outcomes
aggregate_results = outcome_results.map do |scores|
scores.map{|score| Result.new(score.outcome, score.score, score.count, score.hide_points)}
end
opts = {aggregate_score: true, aggregate_stat: stat, **mastery_scale_opts(context)}
aggregate_rollups = aggregate_results.map do |result|
RollupScore.new(outcome_results: result, opts: {aggregate_score: true, aggregate_stat: stat}, context: context)
RollupScore.new(outcome_results: result, opts: opts)
end
Rollup.new(context, aggregate_rollups)
end
@ -117,8 +118,24 @@ module Outcomes
# Returns an Array of RollupScore objects
def rollup_user_results(user_results, context = nil)
filtered_results = user_results.select{|r| !r.score.nil?}
opts = mastery_scale_opts(context)
filtered_results.group_by(&:learning_outcome_id).map do |_, outcome_results|
RollupScore.new(outcome_results:outcome_results, opts:{}, context: context)
RollupScore.new(outcome_results:outcome_results, opts: opts)
end
end
def mastery_scale_opts(context)
return {} unless context.is_a?(Course) && context.root_account.feature_enabled?(:account_level_mastery_scales)
@mastery_scale_opts ||= {}
@mastery_scale_opts[context.asset_string] ||= begin
method = context.resolved_outcome_calculation_method
mastery_scale = context.resolved_outcome_proficiency
{
calculation_method: method&.calculation_method,
calculation_int: method&.calculation_int,
points_possible: mastery_scale&.points_possible,
mastery_points: mastery_scale&.mastery_points
}
end
end