Skip to content

Commit 8f44376

Browse files
committed
removes docker container timeout
better handled by having exceptions properly handled now
1 parent d12280f commit 8f44376

5 files changed

Lines changed: 5 additions & 77 deletions

File tree

src/nhp/docker/__main__.py

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,12 @@
33
import argparse
44
import logging
55
import os
6-
import threading
76

87
from nhp.docker.config import Config
98
from nhp.docker.run import RunWithAzureStorage, RunWithLocalStorage
109
from nhp.model.run import run_all
1110

1211

13-
def _exit_container():
14-
logging.error("\nTimed out, killing container")
15-
os._exit(2)
16-
17-
1812
def parse_args():
1913
"""Parse command line arguments."""
2014
parser = argparse.ArgumentParser()
@@ -53,7 +47,6 @@ def main(config: Config = Config()):
5347
runner = RunWithAzureStorage(args.params_file, config)
5448

5549
logging.info("running model for: %s", args.params_file)
56-
logging.info("container timeout: %ds", config.CONTAINER_TIMEOUT_SECONDS)
5750
logging.info("submitted by: %s", runner.params.get("user"))
5851
logging.info("model_runs: %s", runner.params["model_runs"])
5952
logging.info("start_year: %s", runner.params["start_year"])
@@ -72,23 +65,15 @@ def main(config: Config = Config()):
7265
def init():
7366
"""Method for calling main."""
7467
if __name__ == "__main__":
75-
exc = None
76-
config = Config()
68+
# run the model in a try catch block - ensures any exceptions that occur in the
69+
# multiprocessing pool are handled and logged correctly.
70+
# this prevents the docker container from hanging indefinitely.
7771
try:
78-
# start a timer to kill the container if we reach a timeout
79-
t = threading.Timer(config.CONTAINER_TIMEOUT_SECONDS, _exit_container)
80-
t.start()
81-
# run the model
72+
config = Config()
8273
main(config)
8374
except Exception as e:
8475
logging.error("An error occurred: %s", str(e))
85-
exc = e
86-
finally:
87-
# cancel the timer
88-
t.cancel()
89-
# if there was an exception, raise it
90-
if exc is not None:
91-
raise exc
76+
raise e
9277

9378

9479
init()

src/nhp/docker/config.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
class Config:
99
"""Configuration class for Docker container."""
1010

11-
__DEFAULT_CONTAINER_TIMEOUT_SECONDS = 60 * 60 # 1 hour
12-
1311
def __init__(self):
1412
"""Configuration settings for the Docker container."""
1513
dotenv.load_dotenv()
@@ -18,8 +16,6 @@ def __init__(self):
1816
self._data_version = os.environ.get("DATA_VERSION", "dev")
1917
self._storage_account = os.environ.get("STORAGE_ACCOUNT")
2018

21-
self._container_timeout_seconds = os.environ.get("CONTAINER_TIMEOUT_SECONDS")
22-
2319
@property
2420
def APP_VERSION(self) -> str:
2521
"""What is the version of the app?"""
@@ -36,9 +32,3 @@ def STORAGE_ACCOUNT(self) -> str:
3632
if self._storage_account is None:
3733
raise ValueError("STORAGE_ACCOUNT environment variable must be set")
3834
return self._storage_account
39-
40-
@property
41-
def CONTAINER_TIMEOUT_SECONDS(self) -> int:
42-
"""How long should the container run before timing out?"""
43-
t = self._container_timeout_seconds
44-
return self.__DEFAULT_CONTAINER_TIMEOUT_SECONDS if t is None else int(t)

tests/unit/nhp/docker/test___main__.py

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
11
"""test docker run."""
22

3-
import time
43
from unittest.mock import Mock, patch
54

65
import pytest
76

87
from nhp.docker.__main__ import main, parse_args
98

109

11-
def test_exit_container(mocker):
12-
m = mocker.patch("os._exit")
13-
import nhp.docker.__main__ as r
14-
15-
r._exit_container()
16-
17-
m.assert_called_once_with(2)
18-
19-
2010
@pytest.mark.parametrize(
2111
"args, expected_file, expected_local_storage, expected_save_full_model_results",
2212
[
@@ -95,7 +85,6 @@ def test_main_azure(mocker):
9585
config = Mock()
9686
config.APP_VERSION = "dev"
9787
config.DATA_VERSION = "dev"
98-
config.CONTAINER_TIMEOUT_SECONDS = 3600
9988
config.STORAGE_ACCOUNT = "sa"
10089

10190
params = {
@@ -127,7 +116,6 @@ def test_main_azure(mocker):
127116
def test_init(mocker):
128117
"""It should run the main method if __name__ is __main__."""
129118
config = mocker.patch("nhp.docker.__main__.Config")
130-
config().CONTAINER_TIMEOUT_SECONDS = 3600
131119

132120
import nhp.docker.__main__ as r
133121

@@ -141,36 +129,6 @@ def test_init(mocker):
141129
main_mock.assert_called_once_with(config())
142130

143131

144-
def test_init_timeout_call_exit(mocker):
145-
config = mocker.patch("nhp.docker.__main__.Config")
146-
config().CONTAINER_TIMEOUT_SECONDS = 0.1
147-
148-
import nhp.docker.__main__ as r
149-
150-
main_mock = mocker.patch("nhp.docker.__main__.main")
151-
exit_container_mock = mocker.patch("nhp.docker.__main__._exit_container")
152-
main_mock.side_effect = lambda *args, **kwargs: time.sleep(0.2)
153-
with patch.object(r, "__name__", "__main__"):
154-
r.init()
155-
156-
exit_container_mock.assert_called_once()
157-
158-
159-
def test_init_timeout_dont_call_exit(mocker):
160-
import nhp.docker.__main__ as r
161-
162-
config = mocker.patch("nhp.docker.__main__.Config")
163-
config().CONTAINER_TIMEOUT_SECONDS = 0.1
164-
165-
main_mock = mocker.patch("nhp.docker.__main__.main")
166-
exit_container_mock = mocker.patch("nhp.docker.__main__._exit_container")
167-
main_mock.side_effect = lambda *args, **kwargs: time.sleep(0.02)
168-
with patch.object(r, "__name__", "__main__"):
169-
r.init()
170-
171-
exit_container_mock.assert_not_called()
172-
173-
174132
def test_init_catches_exception(mocker):
175133
# arrange
176134
mocker.patch("nhp.docker.__main__.main", side_effect=Exception("Test error"))

tests/unit/nhp/docker/test_config.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ def test_config_sets_values_from_envvars(mocker):
1717
"APP_VERSION": "app version",
1818
"DATA_VERSION": "data version",
1919
"STORAGE_ACCOUNT": "storage account",
20-
"CONTAINER_TIMEOUT_SECONDS": "123",
2120
},
2221
):
2322
config = Config()
@@ -26,7 +25,6 @@ def test_config_sets_values_from_envvars(mocker):
2625
assert config.APP_VERSION == "app version"
2726
assert config.DATA_VERSION == "data version"
2827
assert config.STORAGE_ACCOUNT == "storage account"
29-
assert config.CONTAINER_TIMEOUT_SECONDS == 123
3028

3129

3230
def test_config_uses_default_values(mocker):
@@ -43,8 +41,6 @@ def test_config_uses_default_values(mocker):
4341
with pytest.raises(ValueError, match="STORAGE_ACCOUNT environment variable must be set"):
4442
config.STORAGE_ACCOUNT
4543

46-
assert config.CONTAINER_TIMEOUT_SECONDS == 3600
47-
4844

4945
def test_config_calls_dotenv_load(mocker):
5046
# arrange

tests/unit/nhp/docker/test_run.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ def mock_run_with_azure_storage():
6363
rwas._config.APP_VERSION = "dev"
6464
rwas._config.DATA_VERSION = "dev"
6565
rwas._config.STORAGE_ACCOUNT = "sa"
66-
rwas._config.CONTAINER_TIMEOUT_SECONDS = 3600
6766

6867
rwas._blob_storage_account_url = "https://sa.blob.core.windows.net"
6968
rwas._adls_storage_account_url = "https://sa.dfs.core.windows.net"

0 commit comments

Comments
 (0)