Refactor listing files to be independent of exiting runners

Previously, we were always fetching files, even if not required (e.g., for score runs). Now, we reduce the number of file listings and use a dedicated callback.
This commit is contained in:
Sebastian Serth
2023-02-15 23:24:55 +01:00
parent e96eda69d7
commit e9cf79085a
2 changed files with 23 additions and 8 deletions

View File

@ -178,7 +178,7 @@ class SubmissionsController < ApplicationController
send_and_store client_socket, message send_and_store client_socket, message
end end
runner_socket.on :exit do |exit_code, files| runner_socket.on :exit do |exit_code|
@testrun[:exit_code] = exit_code @testrun[:exit_code] = exit_code
exit_statement = exit_statement =
if @testrun[:output].empty? && exit_code.zero? if @testrun[:output].empty? && exit_code.zero?
@ -201,6 +201,10 @@ class SubmissionsController < ApplicationController
@testrun[:status] = :out_of_memory @testrun[:status] = :out_of_memory
end end
# The client connection will be closed once the file listing finished.
end
runner_socket.on :files do |files|
downloadable_files, = convert_files_json_to_files files downloadable_files, = convert_files_json_to_files files
if downloadable_files.present? if downloadable_files.present?
js_tree = FileTree.new(downloadable_files).to_js_tree js_tree = FileTree.new(downloadable_files).to_js_tree

View File

@ -5,7 +5,7 @@ require 'json_schemer'
class Runner::Connection class Runner::Connection
# These are events for which callbacks can be registered. # These are events for which callbacks can be registered.
EVENTS = %i[start exit stdout stderr].freeze EVENTS = %i[start exit stdout stderr files].freeze
WEBSOCKET_MESSAGE_TYPES = %i[start stdout stderr error timeout exit].freeze WEBSOCKET_MESSAGE_TYPES = %i[start stdout stderr error timeout exit].freeze
BACKEND_OUTPUT_SCHEMA = JSONSchemer.schema(JSON.parse(File.read('lib/runner/backend-output.schema.json'))) BACKEND_OUTPUT_SCHEMA = JSONSchemer.schema(JSON.parse(File.read('lib/runner/backend-output.schema.json')))
SENTRY_OP_NAME = 'websocket.client' SENTRY_OP_NAME = 'websocket.client'
@ -15,6 +15,7 @@ class Runner::Connection
# @!attribute exit_callback # @!attribute exit_callback
# @!attribute stdout_callback # @!attribute stdout_callback
# @!attribute stderr_callback # @!attribute stderr_callback
# @!attribute files_callback
attr_writer :status attr_writer :status
attr_reader :error attr_reader :error
@ -158,12 +159,8 @@ class Runner::Connection
@strategy.destroy_at_management @strategy.destroy_at_management
@error = Runner::Error::ExecutionTimeout.new('Execution exceeded its time limit') @error = Runner::Error::ExecutionTimeout.new('Execution exceeded its time limit')
when :terminated_by_codeocean, :terminated_by_management when :terminated_by_codeocean, :terminated_by_management
files = begin @exit_callback.call @exit_code
@strategy.retrieve_files list_filesystem
rescue Runner::Error::RunnerNotFound, Runner::Error::WorkspaceError
{'files' => []}
end
@exit_callback.call @exit_code, files
when :terminated_by_client, :error when :terminated_by_client, :error
@strategy.destroy_at_management @strategy.destroy_at_management
else # :established else # :established
@ -181,6 +178,20 @@ class Runner::Connection
@event_loop.stop @event_loop.stop
end end
def list_filesystem
files = {'files' => []}
begin
# Retrieve files from runner management ONLY IF the callback was defined outside of this class.
# Otherwise, we would call our default callback and retrieve the files without any further processing.
files = @strategy.retrieve_files if @files_callback.source_location.first != __FILE__
rescue Runner::Error::RunnerNotFound, Runner::Error::WorkspaceError
# Ignore errors when retrieving files. This is not critical and a suitable default is already provided.
ensure
@files_callback.call files
end
end
private :list_filesystem
# === Message Handlers # === Message Handlers
# Each message type indicated by the +type+ attribute in the JSON # Each message type indicated by the +type+ attribute in the JSON
# sent be the runner management has a dedicated method. # sent be the runner management has a dedicated method.