From 43740e6e8d079390eb4be8a954b80b7865711175 Mon Sep 17 00:00:00 2001 From: Fernando Celmer Date: Sat, 2 May 2026 19:51:38 -0300 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=AA=B2=20BUG-#246:=20Run=20background?= =?UTF-8?q?=20cleanup=20regardless=20of=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dotflow/core/workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotflow/core/workflow.py b/dotflow/core/workflow.py index 028bcad4..8da74641 100644 --- a/dotflow/core/workflow.py +++ b/dotflow/core/workflow.py @@ -176,7 +176,7 @@ def __init__( if mode != TypeExecution.BACKGROUND: self._callback_workflow(tasks=self.tasks) - elif self.config: + else: def _background_cleanup(): self.thread.join() From da334c00c67ca7f5a2b2d42523feeb71f5ea4d59 Mon Sep 17 00:00:00 2001 From: Fernando Celmer Date: Sat, 2 May 2026 19:51:38 -0300 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9D=A4=EF=B8=8F=20TEST-#246:=20Cover=20b?= =?UTF-8?q?ackground=20callbacks=20without=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/core/test_workflow.py | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/core/test_workflow.py b/tests/core/test_workflow.py index f62a57ba..f4f948ba 100644 --- a/tests/core/test_workflow.py +++ b/tests/core/test_workflow.py @@ -1,5 +1,6 @@ """Test context of controller""" +import threading import unittest from types import FunctionType from unittest.mock import Mock @@ -98,3 +99,57 @@ def test_workflow_with_class_completed(self): controller = Manager(tasks=[task]) self.assertEqual(controller.tasks[0].status, TypeStatus.COMPLETED) + + def test_background_callback_runs_without_config(self): + task = Task( + task_id="01ARZ3NDEKTSV4RRFFQ69G5FAV", + step=action_step, + callback=simple_callback, + ) + mock_success = Mock() + + manager = Manager( + tasks=[task], + mode=TypeExecution.BACKGROUND, + on_success=mock_success, + config=None, + ) + + for executor in (manager.tasks, getattr(manager, "thread", None)): + if hasattr(executor, "join"): + executor.join(timeout=5) + + for thread in list(threading.enumerate()): + if thread is threading.current_thread(): + continue + if not thread.daemon: + continue + thread.join(timeout=5) + + mock_success.assert_called() + + def test_background_callback_failure_runs_without_config(self): + task = Task( + task_id="01ARZ3NDEKTSV4RRFFQ69G5FAV", + step=action_step_with_error, + callback=simple_callback, + ) + mock_failure = Mock() + + manager = Manager( + tasks=[task], + mode=TypeExecution.BACKGROUND, + on_failure=mock_failure, + config=None, + ) + + if hasattr(manager, "thread"): + manager.thread.join(timeout=5) + for thread in list(threading.enumerate()): + if thread is threading.current_thread(): + continue + if not thread.daemon: + continue + thread.join(timeout=5) + + mock_failure.assert_called()