Opened 4 months ago

Closed 10 days ago

#36816 closed New feature (fixed)

Allow **kwargs in @task decorator to support custom Task subclasses

Reported by: Pietro Owned by: Nilesh Pahari
Component: Tasks Version: dev
Severity: Normal Keywords: task
Cc: Nilesh Pahari, Jake Howard Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

Currently, the @task decorator accepts a fixed set of parameters and passes only those to task_class:

Problem: When using a custom backend with a custom task_class that accepts additional parameters (e.g., max_retries, timeout), there's no way to pass those through the decorator.

def task(
    function=None,
    *,
    priority=DEFAULT_TASK_PRIORITY,
    queue_name=DEFAULT_TASK_QUEUE_NAME,
    backend=DEFAULT_TASK_BACKEND_ALIAS,
    takes_context=False,
):
    # ...
    return task_backends[backend].task_class(
        priority=priority,
        func=f,
        queue_name=queue_name,
        backend=backend,
        takes_context=takes_context,
        run_after=None
    )

Proposed solution: Add kwargs to the decorator signature and pass it through to task_class:

def task(
    function=None,
    *,
    priority=DEFAULT_TASK_PRIORITY,
    queue_name=DEFAULT_TASK_QUEUE_NAME,
    backend=DEFAULT_TASK_BACKEND_ALIAS,
    takes_context=False,
    **kwargs,
):
    def wrapper(f):
        return task_backends[backend].task_class(
            priority=priority,
            func=f,
            queue_name=queue_name,
            backend=backend,
            takes_context=takes_context,
            run_after=None,
            **kwargs,
        )
    

Use case example:

class MyTask(Task):
    def __init__(self, *, max_retries=3, timeout=300, **kwargs):
        super().__init__(**kwargs)
        self.max_retries = max_retries
        self.timeout = timeout

# With the proposed change:
@task(backend="my_backend", max_retries=5, timeout=600)
def my_task():
    pass

This change is backwards compatible and aligns with Django's common extensibility patterns.

Change History (18)

comment:2 by Kshitij, 4 months ago

Type: BugNew feature

comment:3 by JaeHyuckSa, 4 months ago

Has patch: unset

comment:4 by Nilesh Pahari, 4 months ago

Cc: Nilesh Pahari added

comment:5 by Jacob Walls, 4 months ago

Cc: Jake Howard added

comment:6 by Jake Howard, 4 months ago

Triage Stage: UnreviewedAccepted

This sounds like a reasonable change to me.

As for the solution, my suggestion would be to drop all explicit arguments, and only accept **kwargs in the @task decorator - instead moving the defaults to the Task class itself. That also means that, for whatever reason, a custom Task can override defaults.

comment:7 by Nilesh Pahari, 4 months ago

Owner: set to Nilesh Pahari
Status: newassigned

comment:8 by Jacob Walls, 4 months ago

Version: 6.0dev

comment:9 by Nilesh Pahari, 4 months ago

Has patch: set

comment:11 by Jacob Walls, 6 weeks ago

Needs documentation: set

comment:12 by Kerollos Emad, 5 weeks ago

Needs documentation: unset
Triage Stage: AcceptedReady for checkin

comment:13 by Kerollos Emad, 5 weeks ago

Triage Stage: Ready for checkinAccepted

comment:14 by Jacob Walls, 5 weeks ago

Needs documentation: set

comment:15 by Nilesh Pahari, 13 days ago

Needs documentation: unset

comment:16 by Jacob Walls, 11 days ago

Needs documentation: set

comment:17 by Nilesh Pahari, 11 days ago

Needs documentation: unset

comment:18 by Jacob Walls, 11 days ago

Triage Stage: AcceptedReady for checkin

comment:19 by Jacob Walls <jacobtylerwalls@…>, 10 days ago

Resolution: fixed
Status: assignedclosed

In e27f23b:

Fixed #36816 -- Allowed kwargs in @task decorator.

The decorator was updated to accept kwargs and forward them to
task_class, allowing additional parameters to be passed to custom
Task subclasses.

Note: See TracTickets for help on using tickets.
Back to Top