diff --git a/app/controllers/concerns/submission_scoring.rb b/app/controllers/concerns/submission_scoring.rb index d35a2afe..0911957e 100644 --- a/app/controllers/concerns/submission_scoring.rb +++ b/app/controllers/concerns/submission_scoring.rb @@ -53,6 +53,8 @@ module SubmissionScoring rfc.full_score_reached = true rfc.save } + ensure + ActiveRecord::Base.connection_pool.release_connection end end if @embed_options.present? && @embed_options[:hide_test_results] && outputs.present? diff --git a/app/controllers/request_for_comments_controller.rb b/app/controllers/request_for_comments_controller.rb index 9a8e4656..916039cb 100644 --- a/app/controllers/request_for_comments_controller.rb +++ b/app/controllers/request_for_comments_controller.rb @@ -99,6 +99,8 @@ class RequestForCommentsController < ApplicationController # create thread here and execute tests. A run is triggered from the frontend and does not need to be handled here. Thread.new do score_submission(@request_for_comment.submission) + ensure + ActiveRecord::Base.connection_pool.release_connection end format.json { render :show, status: :created, location: @request_for_comment } else @@ -136,18 +138,18 @@ class RequestForCommentsController < ApplicationController private # Use callbacks to share common setup or constraints between actions. - def set_request_for_comment - @request_for_comment = RequestForComment.find(params[:id]) - end + def set_request_for_comment + @request_for_comment = RequestForComment.find(params[:id]) + end # Never trust parameters from the scary internet, only allow the white list through. - def request_for_comment_params - # The study_group_id might not be present in the session (e.g. for internal users), resulting in session[:study_group_id] = nil which is intended. - params.require(:request_for_comment).permit(:exercise_id, :file_id, :question, :requested_at, :solved, :submission_id).merge(user_id: current_user.id, user_type: current_user.class.name) - end + def request_for_comment_params + # The study_group_id might not be present in the session (e.g. for internal users), resulting in session[:study_group_id] = nil which is intended. + params.require(:request_for_comment).permit(:exercise_id, :file_id, :question, :requested_at, :solved, :submission_id).merge(user_id: current_user.id, user_type: current_user.class.name) + end - def comment_params - params.permit(:exercise_id, :feedback_text).merge(user_id: current_user.id, user_type: current_user.class.name) - end + def comment_params + params.permit(:exercise_id, :feedback_text).merge(user_id: current_user.id, user_type: current_user.class.name) + end end diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 7256077c..cdc9687e 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -147,7 +147,13 @@ class SubmissionsController < ApplicationController # #guarantee that the thread is releasing the DB connection after it is done # ApplicationRecord.connectionpool.releaseconnection # end - Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? + unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? + Thread.new do + EventMachine.run + ensure + ActiveRecord::Base.connection_pool.release_connection + end + end # socket is the socket into the container, tubesock is the socket to the client @@ -319,19 +325,27 @@ class SubmissionsController < ApplicationController return end - Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? + unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? + Thread.new do + EventMachine.run + ensure + ActiveRecord::Base.connection_pool.release_connection + end + end # tubesock is the socket to the client # the score_submission call will end up calling docker exec, which is blocking. # to ensure responsiveness, we therefore open a thread here. - Thread.new { + Thread.new do tubesock.send_data JSON.dump(score_submission(@submission)) # To enable hints when scoring a submission, uncomment the next line: #send_hints(tubesock, StructuredError.where(submission: @submission)) tubesock.send_data JSON.dump({'cmd' => 'exit'}) - } + ensure + ActiveRecord::Base.connection_pool.release_connection + end end end @@ -388,7 +402,13 @@ class SubmissionsController < ApplicationController def test hijack do |tubesock| - Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? + unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? + Thread.new do + EventMachine.run + ensure + ActiveRecord::Base.connection_pool.release_connection + end + end output = @docker_client.execute_test_command(@submission, sanitize_filename) diff --git a/app/helpers/action_cable_helper.rb b/app/helpers/action_cable_helper.rb index 4422a7cb..01fa00d9 100644 --- a/app/helpers/action_cable_helper.rb +++ b/app/helpers/action_cable_helper.rb @@ -1,17 +1,20 @@ +# frozen_string_literal: true module ActionCableHelper -def trigger_rfc_action_cable - Thread.new do - # Context: RfC - if submission.study_group_id.present? - ActionCable.server.broadcast( - "la_exercises_#{exercise_id}_channel_study_group_#{submission.study_group_id}", - type: :rfc, - id: id, - html: (ApplicationController.render(partial: 'request_for_comments/list_entry', - locals: {request_for_comment: self}))) + def trigger_rfc_action_cable + Thread.new do + # Context: RfC + if submission.study_group_id.present? + ActionCable.server.broadcast( + "la_exercises_#{exercise_id}_channel_study_group_#{submission.study_group_id}", + type: :rfc, + id: id, + html: ApplicationController.render(partial: 'request_for_comments/list_entry', + locals: {request_for_comment: self})) + end + ensure + ActiveRecord::Base.connection_pool.release_connection end end -end def trigger_rfc_action_cable_from_comment # Context: Comment @@ -27,6 +30,8 @@ end type: :working_times, working_time_data: exercise.get_working_times_for_study_group(study_group_id, user)) end + ensure + ActiveRecord::Base.connection_pool.release_connection end end end