diff --git a/lib/docker_client.rb b/lib/docker_client.rb index 95b89e50..72960723 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -53,6 +53,7 @@ class DockerClient local_workspace_path = generate_local_workspace_path FileUtils.mkdir(local_workspace_path) container.start(container_start_options(execution_environment, local_workspace_path)) + container.start_time = Time.now container rescue Docker::Error::NotFoundError => error destroy_container(container) @@ -187,7 +188,17 @@ class DockerClient {status: :ok, stderr: stderr.join, stdout: stdout.join} end rescue Timeout::Error - container.restart if RECYCLE_CONTAINERS + #container.restart if RECYCLE_CONTAINERS + DockerContainerPool.remove_from_all_containers(container, @execution_environment) + + # destroy container + destroy_container(container) + + if(RECYCLE_CONTAINERS) + # create new container and add it to @all_containers. will be added to @containers on return_container + container = create_container(@execution_environment) + DockerContainerPool.add_to_all_containers(container, @execution_environment) + end {status: :timeout} ensure RECYCLE_CONTAINERS ? return_container(container) : self.class.destroy_container(container) diff --git a/lib/docker_container_mixin.rb b/lib/docker_container_mixin.rb index a8d3c8a4..fde9fe5b 100644 --- a/lib/docker_container_mixin.rb +++ b/lib/docker_container_mixin.rb @@ -1,4 +1,8 @@ module DockerContainerMixin + + attr_accessor :start_time + attr_accessor :status + def binds json['HostConfig']['Binds'] end diff --git a/lib/docker_container_pool.rb b/lib/docker_container_pool.rb index 8823d989..fc3aee99 100644 --- a/lib/docker_container_pool.rb +++ b/lib/docker_container_pool.rb @@ -3,6 +3,8 @@ require 'concurrent/timer_task' require 'concurrent/utilities' class DockerContainerPool + TIME_TILL_RESTART = 900 + @containers = ThreadSafe::Hash[ExecutionEnvironment.all.map { |execution_environment| [execution_environment.id, ThreadSafe::Array.new] }] #as containers are not containing containers in use @all_containers = ThreadSafe::Hash[ExecutionEnvironment.all.map { |execution_environment| [execution_environment.id, ThreadSafe::Array.new] }] @@ -17,17 +19,51 @@ class DockerContainerPool @config ||= CodeOcean::Config.new(:docker).read(erb: true)[:pool] end + def self.remove_from_all_containers(container, execution_environment) + @all_containers[execution_environment.id]-=[container] + if(@containers[execution_environment.id].include?(container)) + @containers[execution_environment.id]-=[container] + end + end + + def self.add_to_all_containers(container, execution_environment) + @all_containers[execution_environment.id]+=[container] + if(!@containers[execution_environment.id].include?(container)) + @containers[execution_environment.id]+=[container] + end + end + def self.create_container(execution_environment) - DockerClient.create_container(execution_environment) + container = DockerClient.create_container(execution_environment) + container.status = 'available' + container end def self.return_container(container, execution_environment) + container.status = 'available' @containers[execution_environment.id].push(container) end def self.get_container(execution_environment) if config[:active] - @containers[execution_environment.id].try(:shift) || nil + container = @containers[execution_environment.id].try(:shift) || nil + + if(!container.nil?) + if ((Time.now - container.start_time).to_i.abs > TIME_TILL_RESTART) + # remove container from @all_containers + remove_from_all_containers(container, execution_environment) + + # destroy container + DockerClient.destroy_container(container) + + # create new container and add it to @all_containers. will be added to @containers on return_container + container = create_container(execution_environment) + add_to_all_containers(container, execution_environment) + end + #container.status = 'used' + end + container + else create_container(execution_environment) end diff --git a/spec/lib/docker_container_pool_spec.rb b/spec/lib/docker_container_pool_spec.rb index f820a49b..464c3221 100644 --- a/spec/lib/docker_container_pool_spec.rb +++ b/spec/lib/docker_container_pool_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' describe DockerContainerPool do - let(:container) { double } + let(:container) { double(:start_time => Time.now, :status => 'available') } def reload_class load('docker_container_pool.rb')