Repository: alephdata/servicelayer

Issue:
Worker doesn't exit on KeyboardInterrupt when running in multi-threaded mode

Discussion:

Patch:
diff --git a/servicelayer/worker.py b/servicelayer/worker.py
index 939a3a3..daa0be9 100644
--- a/servicelayer/worker.py
+++ b/servicelayer/worker.py
@@ -1,5 +1,6 @@
 import signal
 import logging
+import sys
 from threading import Thread
 from banal import ensure_list
 from abc import ABC, abstractmethod
@@ -23,8 +24,10 @@ class Worker(ABC):
         self.exit_code = 0
 
     def _handle_signal(self, signal, frame):
-        log.warning("Shutting down worker (signal %s)", signal)
+        log.warning(f"Shutting down worker (signal {signal})")
         self.exit_code = int(signal)
+        # Exit eagerly without waiting for current task to finish running
+        sys.exit(self.exit_code)
 
     def handle_safe(self, task):
         try:


Test patch:
diff --git a/tests/test_worker.py b/tests/test_worker.py
index 60e14a9..f4af193 100644
--- a/tests/test_worker.py
+++ b/tests/test_worker.py
@@ -1,4 +1,5 @@
 from unittest import TestCase
+import pytest
 
 from servicelayer.cache import get_fakeredis
 from servicelayer.jobs import Job
@@ -34,8 +35,6 @@ class WorkerTest(TestCase):
         assert job.is_done()
         assert worker.exit_code == 0, worker.exit_code
         assert worker.test_done == 1, worker.test_done
-        worker._handle_signal(5, None)
-        assert worker.exit_code == 5, worker.exit_code
         worker.retry(task)
         worker.run(blocking=False)
         assert job.is_done()
@@ -45,3 +44,9 @@ class WorkerTest(TestCase):
         worker.run(blocking=False)
         assert job.is_done()
         assert worker.exit_code == 0, worker.exit_code
+        try:
+            worker._handle_signal(5, None)
+        except SystemExit as exc:
+            assert exc.code == 5, exc.code
+        with pytest.raises(SystemExit) as exc:  # noqa
+            worker._handle_signal(5, None)