Fix autocorrectable rubocop offences and implement suggestions
This commit is contained in:

committed by
Sebastian Serth

parent
b29bc5e70f
commit
286a3f394d
@ -1,2 +1,4 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ApplicationError < StandardError
|
class ApplicationError < StandardError
|
||||||
end
|
end
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class RunnerNotAvailableError < ApplicationError
|
class RunnerNotAvailableError < ApplicationError
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ApplicationJob < ActiveJob::Base
|
class ApplicationJob < ActiveJob::Base
|
||||||
queue_as :default
|
queue_as :default
|
||||||
end
|
end
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class RunnerCleanupJob < ApplicationJob
|
class RunnerCleanupJob < ApplicationJob
|
||||||
CLEANUP_INTERVAL = CodeOcean::Config.new(:code_ocean).read[:runner_management][:cleanup_interval].seconds
|
CLEANUP_INTERVAL = CodeOcean::Config.new(:code_ocean).read[:runner_management][:cleanup_interval].seconds
|
||||||
|
|
||||||
after_perform do |job|
|
after_perform do |_job|
|
||||||
# re-schedule job
|
# re-schedule job
|
||||||
self.class.set(wait: CLEANUP_INTERVAL).perform_later
|
self.class.set(wait: CLEANUP_INTERVAL).perform_later
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform
|
def perform
|
||||||
Rails.logger.debug(Time.now)
|
Rails.logger.debug(Time.zone.now)
|
||||||
Runner.inactive_runners.each do |runner|
|
Runner.inactive_runners.each do |runner|
|
||||||
Rails.logger.debug("Destroying runner #{runner.runner_id}, unused since #{runner.last_used}")
|
Rails.logger.debug("Destroying runner #{runner.runner_id}, unused since #{runner.last_used}")
|
||||||
runner.destroy
|
runner.destroy
|
||||||
|
@ -10,20 +10,22 @@ class Runner < ApplicationRecord
|
|||||||
belongs_to :execution_environment
|
belongs_to :execution_environment
|
||||||
belongs_to :user, polymorphic: true
|
belongs_to :user, polymorphic: true
|
||||||
|
|
||||||
before_create :get_runner
|
before_create :new_runner
|
||||||
before_destroy :destroy_runner
|
before_destroy :destroy_runner
|
||||||
|
|
||||||
validates :execution_environment_id, presence: true
|
validates :execution_environment, presence: true
|
||||||
validates :user, presence: true
|
validates :user, presence: true
|
||||||
validates :time_limit, presence: true
|
validates :time_limit, presence: true
|
||||||
|
|
||||||
scope :inactive_runners, -> { where('last_used < ?', Time.now - UNUSED_EXPIRATION_TIME) }
|
scope :inactive_runners, -> { where('last_used < ?', Time.zone.now - UNUSED_EXPIRATION_TIME) }
|
||||||
|
|
||||||
def self.for(user, exercise, time_limit = 0)
|
def self.for(user, exercise)
|
||||||
execution_environment = ExecutionEnvironment.find(exercise.execution_environment_id)
|
execution_environment = ExecutionEnvironment.find(exercise.execution_environment_id)
|
||||||
runner = Runner.find_or_create_by(user: user, execution_environment: execution_environment, time_limit: time_limit)
|
runner = Runner.find_or_create_by(user: user, execution_environment: execution_environment,
|
||||||
|
time_limit: execution_environment.permitted_execution_time)
|
||||||
|
|
||||||
return runner if runner.save
|
return runner if runner.save
|
||||||
|
|
||||||
raise(RunnerNotAvailableError, 'No runner available')
|
raise(RunnerNotAvailableError, 'No runner available')
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -31,22 +33,22 @@ class Runner < ApplicationRecord
|
|||||||
url = "#{runner_url}/files"
|
url = "#{runner_url}/files"
|
||||||
body = {files: files.map { |filename, content| {filepath: filename, content: content} }}
|
body = {files: files.map { |filename, content| {filepath: filename, content: content} }}
|
||||||
response = Faraday.patch(url, body.to_json, HEADERS)
|
response = Faraday.patch(url, body.to_json, HEADERS)
|
||||||
if response.status == 404
|
return unless response.status == 404
|
||||||
|
|
||||||
# runner has disappeared for some reason
|
# runner has disappeared for some reason
|
||||||
self.destroy
|
destroy
|
||||||
raise(RunnerNotAvailableError, "Runner unavailable")
|
raise(RunnerNotAvailableError, 'Runner unavailable')
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute_command(command)
|
def execute_command(command)
|
||||||
|
used_now
|
||||||
url = "#{runner_url}/execute"
|
url = "#{runner_url}/execute"
|
||||||
response = Faraday.post(url, {command: command}.to_json, HEADERS)
|
response = Faraday.post(url, {command: command}.to_json, HEADERS)
|
||||||
if response.status == 404
|
if response.status == 404
|
||||||
# runner has disappeared for some reason
|
# runner has disappeared for some reason
|
||||||
self.destroy
|
destroy
|
||||||
raise(RunnerNotAvailableError, "Runner unavailable")
|
raise(RunnerNotAvailableError, 'Runner unavailable')
|
||||||
end
|
end
|
||||||
used_now
|
|
||||||
parse response
|
parse response
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -71,10 +73,9 @@ class Runner < ApplicationRecord
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def get_runner
|
def new_runner
|
||||||
url = "#{BASE_URL}/runners"
|
url = "#{BASE_URL}/runners"
|
||||||
body = {executionEnvironmentId: execution_environment.id}
|
body = {executionEnvironmentId: execution_environment.id, timeLimit: time_limit}
|
||||||
body[:timeLimit] = time_limit
|
|
||||||
response = Faraday.post(url, body.to_json, HEADERS)
|
response = Faraday.post(url, body.to_json, HEADERS)
|
||||||
response_body = parse response
|
response_body = parse response
|
||||||
self.runner_id = response_body[:runnerId]
|
self.runner_id = response_body[:runnerId]
|
||||||
@ -90,7 +91,7 @@ class Runner < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def used_now
|
def used_now
|
||||||
self.last_used = Time.now
|
self.last_used = Time.zone.now
|
||||||
save
|
save
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -72,7 +72,7 @@ class Submission < ApplicationRecord
|
|||||||
# expects the full file path incl. file extension
|
# expects the full file path incl. file extension
|
||||||
# Caution: There must be no unnecessary path prefix included.
|
# Caution: There must be no unnecessary path prefix included.
|
||||||
# Use `file.ext` rather than `./file.ext`
|
# Use `file.ext` rather than `./file.ext`
|
||||||
collect_files.detect {|file| file.filepath == file_path }
|
collect_files.detect { |file| file.filepath == file_path }
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalized_score
|
def normalized_score
|
||||||
@ -144,18 +144,18 @@ class Submission < ApplicationRecord
|
|||||||
prepared_runner do |runner|
|
prepared_runner do |runner|
|
||||||
scores = collect_files.select(&:teacher_defined_assessment?).map do |file|
|
scores = collect_files.select(&:teacher_defined_assessment?).map do |file|
|
||||||
score_command = command_for execution_environment.test_command, file.name_with_extension
|
score_command = command_for execution_environment.test_command, file.name_with_extension
|
||||||
stdout = ""
|
stdout = ''
|
||||||
stderr = ""
|
stderr = ''
|
||||||
exit_code = 1 # default to error
|
exit_code = 1 # default to error
|
||||||
execution_time = runner.execute_interactively(score_command) do |runner, socket|
|
execution_time = runner.execute_interactively(score_command) do |_runner, socket|
|
||||||
socket.on :stderr do |data|
|
socket.on :stderr do |data|
|
||||||
stderr << data
|
stderr << data
|
||||||
end
|
end
|
||||||
socket.on :stdout do |data|
|
socket.on :stdout do |data|
|
||||||
stdout << data
|
stdout << data
|
||||||
end
|
end
|
||||||
socket.on :exit do |_exit_code|
|
socket.on :exit do |received_exit_code|
|
||||||
exit_code = _exit_code
|
exit_code = received_exit_code
|
||||||
EventMachine.stop_event_loop
|
EventMachine.stop_event_loop
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -163,9 +163,9 @@ class Submission < ApplicationRecord
|
|||||||
file_role: file.role,
|
file_role: file.role,
|
||||||
waiting_for_container_time: runner.waiting_time,
|
waiting_for_container_time: runner.waiting_time,
|
||||||
container_execution_time: execution_time,
|
container_execution_time: execution_time,
|
||||||
status: (exit_code == 0) ? :ok : :failed,
|
status: exit_code.zero? ? :ok : :failed,
|
||||||
stdout: stdout,
|
stdout: stdout,
|
||||||
stderr: stderr,
|
stderr: stderr
|
||||||
}
|
}
|
||||||
test_result(output, file)
|
test_result(output, file)
|
||||||
end
|
end
|
||||||
@ -194,10 +194,10 @@ class Submission < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def prepared_runner
|
def prepared_runner
|
||||||
request_time = Time.now
|
request_time = Time.zone.now
|
||||||
runner = Runner.for(user, exercise, execution_environment.permitted_execution_time)
|
runner = Runner.for(user, exercise)
|
||||||
copy_files_to runner
|
copy_files_to runner
|
||||||
runner.waiting_time = Time.now - request_time
|
runner.waiting_time = Time.zone.now - request_time
|
||||||
yield(runner) if block_given?
|
yield(runner) if block_given?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1 +1,3 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
RunnerCleanupJob.perform_now unless Rake.application.top_level_tasks.to_s.match?(/db:|assets:/)
|
RunnerCleanupJob.perform_now unless Rake.application.top_level_tasks.to_s.match?(/db:|assets:/)
|
||||||
|
Reference in New Issue
Block a user