From 4f1c4f6aab68293533e24ba90ca655a4df2c54f2 Mon Sep 17 00:00:00 2001 From: Nico Hinderling Date: Fri, 13 Mar 2026 12:00:34 -0700 Subject: [PATCH 1/2] feat(taskworker): Attempt to add healthcheck logic --- .gitignore | 3 +++ src/launchpad/worker/config.py | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 3bdf52a3..0cedc4b2 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ output/ # gocd generated output gocd/templates/vendor/ gocd/generated-pipelines/ + +# uv +uv.lock diff --git a/src/launchpad/worker/config.py b/src/launchpad/worker/config.py index 5b01b740..555c6de0 100644 --- a/src/launchpad/worker/config.py +++ b/src/launchpad/worker/config.py @@ -12,10 +12,14 @@ logger = get_logger(__name__) +DEFAULT_HEALTH_CHECK_FILE_PATH = "/tmp/health" + + @dataclass class WorkerConfig: rpc_hosts: list[str] concurrency: int + health_check_file_path: str def get_worker_config() -> WorkerConfig: @@ -34,16 +38,20 @@ def get_worker_config() -> WorkerConfig: except ValueError: raise ValueError(f"LAUNCHPAD_WORKER_CONCURRENCY must be a valid integer, got: {concurrency_str}") - return WorkerConfig(rpc_hosts=rpc_hosts, concurrency=concurrency) + health_check_file_path = os.getenv("LAUNCHPAD_WORKER_HEALTH_CHECK_FILE_PATH", DEFAULT_HEALTH_CHECK_FILE_PATH) + + return WorkerConfig(rpc_hosts=rpc_hosts, concurrency=concurrency, health_check_file_path=health_check_file_path) def run_worker() -> None: initialize_sentry_sdk() config = get_worker_config() - logger.info(f"Starting TaskWorker (rpc_hosts={config.rpc_hosts}, concurrency={config.concurrency})") + logger.info( + f"Starting TaskWorker (rpc_hosts={config.rpc_hosts}, concurrency={config.concurrency}, " + f"health_check_file_path={config.health_check_file_path})" + ) - # TODO: Should we explore setting health_check_file_path for K8s file-based liveness probes (TaskWorker has no HTTP server) worker = TaskWorker( app_module="launchpad.worker.app:app", broker_hosts=config.rpc_hosts, @@ -54,6 +62,7 @@ def run_worker() -> None: rebalance_after=16, processing_pool_name="launchpad", process_type="forkserver", + health_check_file_path=config.health_check_file_path, ) exitcode = worker.start() From 31d60d7b29dc63db4896d4caeaea9ac6de3bc6c5 Mon Sep 17 00:00:00 2001 From: Nico Hinderling Date: Wed, 18 Mar 2026 15:48:50 -0700 Subject: [PATCH 2/2] address comment --- tests/unit/test_worker_config.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_worker_config.py b/tests/unit/test_worker_config.py index 9d4590e4..a75cacd8 100644 --- a/tests/unit/test_worker_config.py +++ b/tests/unit/test_worker_config.py @@ -4,7 +4,7 @@ import pytest -from launchpad.worker.config import WorkerConfig, get_worker_config +from launchpad.worker.config import DEFAULT_HEALTH_CHECK_FILE_PATH, WorkerConfig, get_worker_config class TestGetWorkerConfig: @@ -17,7 +17,23 @@ def test_valid_config(self): }, ): config = get_worker_config() - assert config == WorkerConfig(rpc_hosts=["localhost:50051"], concurrency=8) + assert config == WorkerConfig( + rpc_hosts=["localhost:50051"], + concurrency=8, + health_check_file_path=DEFAULT_HEALTH_CHECK_FILE_PATH, + ) + + def test_custom_health_check_file_path(self): + with patch.dict( + os.environ, + { + "LAUNCHPAD_WORKER_RPC_HOST": "localhost:50051", + "LAUNCHPAD_WORKER_CONCURRENCY": "8", + "LAUNCHPAD_WORKER_HEALTH_CHECK_FILE_PATH": "/custom/health", + }, + ): + config = get_worker_config() + assert config.health_check_file_path == "/custom/health" def test_comma_separated_hosts(self): with patch.dict(