From 3239525e2ad4e0a8baf1550b8adaa220566fff71 Mon Sep 17 00:00:00 2001 From: Marcel Klehr Date: Tue, 17 Feb 2026 10:37:16 +0100 Subject: [PATCH 1/4] feat: Gracefully shutdown if SIGTERM is received Signed-off-by: Marcel Klehr --- lib/main.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/main.py b/lib/main.py index c5bfd5a..e70439b 100644 --- a/lib/main.py +++ b/lib/main.py @@ -42,6 +42,8 @@ def log(nc, level, content): CHECK_INTERVAL = 5 CHECK_INTERVAL_WITH_TRIGGER = 5 * 60 CHECK_INTERVAL_ON_ERROR = 10 +SHUTDOWN_EVENT_RECEIVED = Event() +SHUTDOWN_CLEAR = Event() @asynccontextmanager async def lifespan(_app: FastAPI): @@ -56,6 +58,9 @@ async def lifespan(_app: FastAPI): app_enabled.set() start_bg_task() yield + print("\nSIGTERM received. Processing last task and stopping to fetch and process new tasks..") + SHUTDOWN_EVENT_RECEIVED.set() + SHUTDOWN_CLEAR.wait() APP = FastAPI(lifespan=lifespan) @@ -80,6 +85,9 @@ def background_thread_task(): sleep(30) continue + if SHUTDOWN_EVENT_RECEIVED.is_set(): + break + current_minute = int(strftime("%M")) if current_minute % 5 == 0: # scan dir and load new models every 5 minutes @@ -136,7 +144,7 @@ def background_thread_task(): nc.providers.task_processing.report_result(task["id"], error_message=str(e)) except (NextcloudException, RequestException) as net_err: log(nc, LogLvl.INFO, f"Network error in reporting the error: {net_err}") - + SHUTDOWN_CLEAR.set() def start_bg_task(): t = Thread(target=background_thread_task, args=()) @@ -202,6 +210,5 @@ def wait_for_tasks(interval = None): CHECK_INTERVAL = CHECK_INTERVAL_WITH_TRIGGER trigger.clear() - if __name__ == "__main__": run_app("main:APP", log_level="trace") From 193df767ce0d3e317dcdc74473918a909e6bd7bf Mon Sep 17 00:00:00 2001 From: Marcel Klehr Date: Mon, 23 Feb 2026 10:59:31 +0100 Subject: [PATCH 2/4] feat: Add TASK_POLLING_INTERVAL env var Signed-off-by: Marcel Klehr --- appinfo/info.xml | 6 ++++++ lib/main.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index 2aa7913..73a7c0a 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -33,5 +33,11 @@ See [the nextcloud admin docs](https://docs.nextcloud.com/server/latest/admin_ma 2.6.0 false + + + TASK_POLLING_INTERVAL + Task polling interval + The interval in which the app will poll for new tasks, in seconds (can be floating point numbers). This will only be used when running in Kubernetes or with Nextcloud below v33. This value defaults to 5 seconds. + diff --git a/lib/main.py b/lib/main.py index e70439b..b821543 100644 --- a/lib/main.py +++ b/lib/main.py @@ -39,7 +39,7 @@ def log(nc, level, content): } app_enabled = Event() trigger = Event() -CHECK_INTERVAL = 5 +CHECK_INTERVAL = float(os.getenv('TASK_POLLING_INTERVAL', '5')) CHECK_INTERVAL_WITH_TRIGGER = 5 * 60 CHECK_INTERVAL_ON_ERROR = 10 SHUTDOWN_EVENT_RECEIVED = Event() From b7e04a1f141059d2b9d483c349ace156ecfa5273 Mon Sep 17 00:00:00 2001 From: Marcel Klehr Date: Wed, 25 Feb 2026 10:35:28 +0100 Subject: [PATCH 3/4] fix: Address review comments Signed-off-by: Marcel Klehr --- appinfo/info.xml | 1 + lib/main.py | 1 + 2 files changed, 2 insertions(+) diff --git a/appinfo/info.xml b/appinfo/info.xml index 73a7c0a..bb819d3 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -39,5 +39,6 @@ See [the nextcloud admin docs](https://docs.nextcloud.com/server/latest/admin_ma Task polling interval The interval in which the app will poll for new tasks, in seconds (can be floating point numbers). This will only be used when running in Kubernetes or with Nextcloud below v33. This value defaults to 5 seconds. + diff --git a/lib/main.py b/lib/main.py index b821543..8ab3be0 100644 --- a/lib/main.py +++ b/lib/main.py @@ -60,6 +60,7 @@ async def lifespan(_app: FastAPI): yield print("\nSIGTERM received. Processing last task and stopping to fetch and process new tasks..") SHUTDOWN_EVENT_RECEIVED.set() + trigger.set() SHUTDOWN_CLEAR.wait() From 3201ed308226565a25e3b2a039bd422079f77608 Mon Sep 17 00:00:00 2001 From: Marcel Klehr Date: Wed, 25 Feb 2026 11:27:41 +0100 Subject: [PATCH 4/4] fix: Validate TASK_POLLING_INTERVAL env var Signed-off-by: Marcel Klehr --- lib/main.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/main.py b/lib/main.py index 8ab3be0..ced1a64 100644 --- a/lib/main.py +++ b/lib/main.py @@ -39,7 +39,16 @@ def log(nc, level, content): } app_enabled = Event() trigger = Event() -CHECK_INTERVAL = float(os.getenv('TASK_POLLING_INTERVAL', '5')) + +try: + CHECK_INTERVAL = float(os.getenv('TASK_POLLING_INTERVAL', '5')) + if CHECK_INTERVAL <= 0: + logger.warning("Invalid TASK_POLLING_INTERVAL env variable, falling back to default 5 seconds") + CHECK_INTERVAL = 5 +except (TypeError, ValueError): + logger.warning("Invalid TASK_POLLING_INTERVAL env variable, falling back to default 5 seconds") + CHECK_INTERVAL = 5 + CHECK_INTERVAL_WITH_TRIGGER = 5 * 60 CHECK_INTERVAL_ON_ERROR = 10 SHUTDOWN_EVENT_RECEIVED = Event()