66 Any ,
77 Callable ,
88 Generic ,
9+ Literal ,
910 Optional ,
1011 TypeVar ,
1112 Union ,
1718from django .db .models .enums import TextChoices
1819from django .utils .module_loading import import_string
1920from django .utils .translation import gettext_lazy as _
20- from typing_extensions import ParamSpec , Self
21+ from typing_extensions import Concatenate , ParamSpec , Self
2122
2223from .exceptions import ResultDoesNotExist
2324from .utils import (
@@ -87,6 +88,11 @@ class Task(Generic[P, T]):
8788 immediately, or whatever the backend decides
8889 """
8990
91+ takes_context : bool = False
92+ """
93+ Whether the task receives the task context when executed.
94+ """
95+
9096 def __post_init__ (self ) -> None :
9197 self .get_backend ().validate_task (self )
9298
@@ -197,18 +203,37 @@ def task(
197203 queue_name : str = DEFAULT_QUEUE_NAME ,
198204 backend : str = DEFAULT_TASK_BACKEND_ALIAS ,
199205 enqueue_on_commit : Optional [bool ] = None ,
206+ takes_context : Literal [False ] = False ,
200207) -> Callable [[Callable [P , T ]], Task [P , T ]]: ...
201208
202209
203- # Implementation
210+ # Decorator with context and arguments
211+ # e.g. @task(takes_context=True, ...)
212+ @overload
204213def task (
214+ * ,
215+ priority : int = DEFAULT_PRIORITY ,
216+ queue_name : str = DEFAULT_QUEUE_NAME ,
217+ backend : str = DEFAULT_TASK_BACKEND_ALIAS ,
218+ enqueue_on_commit : Optional [bool ] = None ,
219+ takes_context : Literal [True ],
220+ ) -> Callable [[Callable [Concatenate ["TaskContext" , P ], T ]], Task [P , T ]]: ...
221+
222+
223+ # Implementation
224+ def task ( # type: ignore[misc]
205225 function : Optional [Callable [P , T ]] = None ,
206226 * ,
207227 priority : int = DEFAULT_PRIORITY ,
208228 queue_name : str = DEFAULT_QUEUE_NAME ,
209229 backend : str = DEFAULT_TASK_BACKEND_ALIAS ,
210230 enqueue_on_commit : Optional [bool ] = None ,
211- ) -> Union [Task [P , T ], Callable [[Callable [P , T ]], Task [P , T ]]]:
231+ takes_context : bool = False ,
232+ ) -> Union [
233+ Task [P , T ],
234+ Callable [[Callable [P , T ]], Task [P , T ]],
235+ Callable [[Callable [Concatenate ["TaskContext" , P ], T ]], Task [P , T ]],
236+ ]:
212237 """
213238 A decorator used to create a task.
214239 """
@@ -221,6 +246,7 @@ def wrapper(f: Callable[P, T]) -> Task[P, T]:
221246 queue_name = queue_name ,
222247 backend = backend ,
223248 enqueue_on_commit = enqueue_on_commit ,
249+ takes_context = takes_context ,
224250 )
225251
226252 if function :
@@ -330,3 +356,12 @@ async def arefresh(self) -> None:
330356
331357 for attr in TASK_REFRESH_ATTRS :
332358 object .__setattr__ (self , attr , getattr (refreshed_task , attr ))
359+
360+
361+ @dataclass (frozen = True )
362+ class TaskContext :
363+ task_result : TaskResult
364+
365+ @property
366+ def attempt (self ) -> int :
367+ return self .task_result .attempts
0 commit comments