Refactor submission scoring and testing
* Properly cancel code execution if running is prohibited * Correctly monitor duration with Sentry * Align methods with running submissions
This commit is contained in:

committed by
Sebastian Serth

parent
a1ec4579fe
commit
9c3ec3c7ff
@ -239,31 +239,32 @@ class SubmissionsController < ApplicationController
|
||||
# rubocop:enable Metrics/CyclomaticComplexity:
|
||||
|
||||
def score
|
||||
client_socket = nil
|
||||
disable_scoring = @embed_options[:disable_score] || !@submission.exercise.teacher_defined_assessment?
|
||||
|
||||
hijack do |tubesock|
|
||||
client_socket = tubesock
|
||||
tubesock.onopen do |_event|
|
||||
switch_locale do
|
||||
return kill_client_socket(tubesock) if @embed_options[:disable_score] || !@submission.exercise.teacher_defined_assessment?
|
||||
kill_client_socket(tubesock) and return true if disable_scoring
|
||||
end
|
||||
end
|
||||
|
||||
# If scoring is not allowed (and the socket is closed), we can stop here.
|
||||
return true if disable_scoring
|
||||
|
||||
# The score is stored separately, we can forward it to the client immediately
|
||||
tubesock.send_data(JSON.dump(@submission.calculate_score))
|
||||
client_socket&.send_data(JSON.dump(@submission.calculate_score))
|
||||
# To enable hints when scoring a submission, uncomment the next line:
|
||||
# send_hints(tubesock, StructuredError.where(submission: @submission))
|
||||
kill_client_socket(tubesock)
|
||||
# send_hints(client_socket, StructuredError.where(submission: @submission))
|
||||
kill_client_socket(client_socket)
|
||||
rescue Runner::Error => e
|
||||
extract_durations(e)
|
||||
send_and_store tubesock, {cmd: :status, status: :container_depleted}
|
||||
kill_client_socket(tubesock)
|
||||
send_and_store client_socket, {cmd: :status, status: :container_depleted}
|
||||
kill_client_socket(client_socket)
|
||||
Rails.logger.debug { "Runner error while scoring submission #{@submission.id}: #{e.message}" }
|
||||
@testrun[:passed] = false
|
||||
save_testrun_output 'assess'
|
||||
rescue StandardError => e
|
||||
Sentry.capture_exception(e)
|
||||
raise e
|
||||
ensure
|
||||
ActiveRecord::Base.connection_pool.release_connection
|
||||
end
|
||||
end
|
||||
end
|
||||
save_testrun_output 'assess'
|
||||
end
|
||||
|
||||
def create
|
||||
@ -275,25 +276,30 @@ class SubmissionsController < ApplicationController
|
||||
def statistics; end
|
||||
|
||||
def test
|
||||
client_socket = nil
|
||||
|
||||
hijack do |tubesock|
|
||||
client_socket = tubesock
|
||||
tubesock.onopen do |_event|
|
||||
switch_locale do
|
||||
return kill_client_socket(tubesock) if @embed_options[:disable_run]
|
||||
kill_client_socket(tubesock) and return true if @embed_options[:disable_run]
|
||||
end
|
||||
end
|
||||
|
||||
# If running is not allowed (and the socket is closed), we can stop here.
|
||||
return true if @embed_options[:disable_run]
|
||||
|
||||
# The score is stored separately, we can forward it to the client immediately
|
||||
tubesock.send_data(JSON.dump(@submission.test(@file)))
|
||||
kill_client_socket(tubesock)
|
||||
client_socket&.send_data(JSON.dump(@submission.test(@file)))
|
||||
kill_client_socket(client_socket)
|
||||
rescue Runner::Error => e
|
||||
extract_durations(e)
|
||||
send_and_store tubesock, {cmd: :status, status: :container_depleted}
|
||||
kill_client_socket(tubesock)
|
||||
send_and_store client_socket, {cmd: :status, status: :container_depleted}
|
||||
kill_client_socket(client_socket)
|
||||
Rails.logger.debug { "Runner error while testing submission #{@submission.id}: #{e.message}" }
|
||||
@testrun[:passed] = false
|
||||
ensure
|
||||
save_testrun_output 'assess'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
@ -233,6 +233,7 @@ describe SubmissionsController do
|
||||
|
||||
before do
|
||||
allow_any_instance_of(described_class).to receive(:hijack)
|
||||
allow_any_instance_of(described_class).to receive(:kill_client_socket)
|
||||
perform_request.call
|
||||
end
|
||||
|
||||
@ -247,6 +248,7 @@ describe SubmissionsController do
|
||||
before do
|
||||
file.update(hidden: false)
|
||||
allow_any_instance_of(described_class).to receive(:hijack)
|
||||
allow_any_instance_of(described_class).to receive(:kill_client_socket)
|
||||
get :test, params: {filename: "#{file.filepath}.json", id: submission.id}
|
||||
end
|
||||
|
||||
|
Reference in New Issue
Block a user