• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

source-academy / backend / e0330f2cf38b2d8af12bffd20f4cac2158d607fc-PR-1236

31 Mar 2025 09:12AM UTC coverage: 19.982% (-73.6%) from 93.607%
e0330f2cf38b2d8af12bffd20f4cac2158d607fc-PR-1236

Pull #1236

github

RichDom2185
Redate migrations to maintain total ordering
Pull Request #1236: Added Exam mode

12 of 57 new or added lines in 8 files covered. (21.05%)

2430 existing lines in 97 files now uncovered.

671 of 3358 relevant lines covered (19.98%)

3.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lib/cadet/jobs/autograder/result_store_worker.ex
1
defmodule Cadet.Autograder.ResultStoreWorker do
2
  # Suppress no_match from macro
3
  @dialyzer {:no_match, __after_compile__: 2}
4
  @moduledoc """
5
  This module writes results from the autograder to db. Separate worker is created with lower
6
  concurrency on the assumption that autograding time >> db IO time so as to reduce db load.
7
  """
8
  use Que.Worker, concurrency: 5
9

10
  require Logger
11

12
  import Cadet.SharedHelper
13
  import Ecto.Query
14

15
  alias Ecto.Multi
16

17
  alias Cadet.{Assessments, Repo}
18
  alias Cadet.Assessments.{Answer, Assessment, Submission}
19
  alias Cadet.Courses.AssessmentConfig
20

21
  def perform(params = %{answer_id: answer_id, result: result})
22
      when is_ecto_id(answer_id) do
23
    Multi.new()
UNCOV
24
    |> Multi.run(:fetch, fn _repo, _ -> fetch_answer(answer_id) end)
×
25
    |> Multi.run(:update, fn _repo, %{fetch: answer} ->
UNCOV
26
      update_answer(answer, result, params[:overwrite] || false)
×
27
    end)
28
    |> Repo.transaction()
UNCOV
29
    |> case do
×
UNCOV
30
      {:ok, _} ->
×
31
        nil
32

33
      {:error, failed_operation, failed_value, _} ->
UNCOV
34
        error_message =
×
35
          "Failed to store autograder result. " <>
UNCOV
36
            "answer_id: #{answer_id}, #{failed_operation}, #{inspect(failed_value, pretty: true)}"
×
37

UNCOV
38
        Logger.error(error_message)
×
UNCOV
39
        Sentry.capture_message(error_message)
×
40
    end
41
  end
42

43
  defp fetch_answer(answer_id) when is_ecto_id(answer_id) do
UNCOV
44
    answer =
×
45
      Answer
46
      |> join(:inner, [a], q in assoc(a, :question))
UNCOV
47
      |> preload([_, q], question: q)
×
48
      |> Repo.get(answer_id)
49

UNCOV
50
    if answer do
×
51
      {:ok, answer}
52
    else
53
      {:error, "Answer not found"}
54
    end
55
  end
56

57
  defp update_answer(
58
         answer = %Answer{submission_id: submission_id},
59
         result = %{status: status},
60
         overwrite
61
       ) do
UNCOV
62
    xp =
×
63
      cond do
UNCOV
64
        result.max_score == 0 and length(result.result) > 0 ->
×
65
          testcase_results = result.result
×
66

67
          num_passed =
×
68
            testcase_results |> Enum.filter(fn r -> r["resultType"] == "pass" end) |> length()
×
69

70
          Integer.floor_div(answer.question.max_xp * num_passed, length(testcase_results))
×
71

UNCOV
72
        result.max_score == 0 ->
×
73
          0
74

UNCOV
75
        true ->
×
UNCOV
76
          Integer.floor_div(answer.question.max_xp * result.score, result.max_score)
×
77
      end
78

UNCOV
79
    changes = %{
×
80
      xp: xp,
81
      autograding_status: status,
UNCOV
82
      autograding_results: result.result
×
83
    }
84

UNCOV
85
    changes = if(overwrite, do: Map.put(changes, :xp_adjustment, 0), else: changes)
×
86

UNCOV
87
    res =
×
88
      answer
89
      |> Answer.autograding_changeset(changes)
90
      |> Repo.update()
91

UNCOV
92
    submission = Repo.get(Submission, submission_id)
×
UNCOV
93
    assessment = Repo.get(Assessment, submission.assessment_id)
×
UNCOV
94
    assessment_config = Repo.get_by(AssessmentConfig, id: assessment.config_id)
×
UNCOV
95
    is_grading_auto_published = assessment_config.is_grading_auto_published
×
UNCOV
96
    is_manually_graded = assessment_config.is_manually_graded
×
97

UNCOV
98
    if Assessments.is_fully_autograded?(submission_id) and is_grading_auto_published and
×
UNCOV
99
         not is_manually_graded do
×
UNCOV
100
      Assessments.publish_grading(submission_id)
×
101
    end
102

UNCOV
103
    res
×
104
  end
105
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc