From ea49e3678b23ab3bfda015f5c45dc3396f84304c Mon Sep 17 00:00:00 2001 From: Jainal Gosaliya Date: Mon, 29 Dec 2025 12:34:55 -0500 Subject: [PATCH] Remove processed background tasks from queue This change modifies BackgroundTasks.__call__ to remove tasks from the list after they are executed. This enables users to monitor the queue length for implementing features like graceful shutdowns. Previously, all tasks remained in the list even after execution, making it impossible to determine how many tasks were still pending. Closes encode/starlette#2542 --- starlette/background.py | 3 ++- tests/test_background.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/starlette/background.py b/starlette/background.py index 55135eed3..2a60bf617 100644 --- a/starlette/background.py +++ b/starlette/background.py @@ -32,5 +32,6 @@ def add_task(self, func: Callable[P, Any], *args: P.args, **kwargs: P.kwargs) -> self.tasks.append(task) async def __call__(self) -> None: - for task in self.tasks: + while self.tasks: + task = self.tasks.pop(0) await task() diff --git a/tests/test_background.py b/tests/test_background.py index 48f348769..fbfea0070 100644 --- a/tests/test_background.py +++ b/tests/test_background.py @@ -87,3 +87,22 @@ async def app(scope: Scope, receive: Receive, send: Send) -> None: with pytest.raises(Exception): client.get("/") assert TASK_COUNTER == 1 + + +def test_tasks_removed_after_execution(test_client_factory: TestClientFactory) -> None: + tasks = BackgroundTasks() + + def noop() -> None: + pass + + async def app(scope: Scope, receive: Receive, send: Send) -> None: + tasks.add_task(noop) + tasks.add_task(noop) + tasks.add_task(noop) + assert len(tasks.tasks) == 3 + response = Response("tasks initiated", media_type="text/plain", background=tasks) + await response(scope, receive, send) + + client = test_client_factory(app) + client.get("/") + assert len(tasks.tasks) == 0