diff --git a/lib/coursemology/evaluator/services/evaluate_programming_package_service.rb b/lib/coursemology/evaluator/services/evaluate_programming_package_service.rb index 2c77142..b1af14b 100644 --- a/lib/coursemology/evaluator/services/evaluate_programming_package_service.rb +++ b/lib/coursemology/evaluator/services/evaluate_programming_package_service.rb @@ -106,12 +106,21 @@ def copy_archive(zip_file, tar_file, prefix = nil) def execute_package(container) container.start! + execute_package_wait(container) + end + + # Waits for the container to exit the Running state. + # + # This will time out for long running operations, so keep retrying until we return. + def execute_package_wait(container) container_state = container.info while container_state.fetch('State', {}).fetch('Running', true) container.wait container.refresh! container_state = container.info end + rescue Docker::Error::TimeoutError + retry end def extract_result(container) diff --git a/spec/coursemology/evaluator/services/evaluate_programming_package_service_spec.rb b/spec/coursemology/evaluator/services/evaluate_programming_package_service_spec.rb index 5248f6a..c0d436f 100644 --- a/spec/coursemology/evaluator/services/evaluate_programming_package_service_spec.rb +++ b/spec/coursemology/evaluator/services/evaluate_programming_package_service_spec.rb @@ -82,6 +82,24 @@ def evaluate_result end end + describe '#execute_package_wait' do + let(:image) { 'python:2.7' } + let(:container) { subject.send(:create_container, image) } + after { subject.send(:destroy_container, container) } + + it 'retries until the container finishes' do + called = 0 + expect(container).to receive(:wait).and_wrap_original do |block, *args| + args.push(0.second) if called == 0 + called += 1 + + block.call(*args) + end.at_least(:twice) + + subject.send(:execute_package_wait, container) + end + end + describe '#extract_result' do let(:image) { 'python:2.7' } let(:container) do