1
+ import datetime
1
2
import logging
2
3
import uuid
3
4
from typing import TYPE_CHECKING , Any , Generic , Optional , TypeVar
@@ -46,14 +47,17 @@ def __class_getitem__(cls, _):
46
47
return cls
47
48
48
49
50
+ DATE_MAX = datetime .datetime (9999 , 1 , 1 , tzinfo = datetime .timezone .utc )
51
+
52
+
49
53
class DBTaskResultQuerySet (models .QuerySet ):
50
54
def ready (self ) -> "DBTaskResultQuerySet" :
51
55
"""
52
56
Return tasks which are ready to be processed.
53
57
"""
54
58
return self .filter (
55
59
status = ResultStatus .NEW ,
56
- ).filter (models .Q (run_after = None ) | models .Q (run_after__lte = timezone .now ()))
60
+ ).filter (models .Q (run_after = DATE_MAX ) | models .Q (run_after__lte = timezone .now ()))
57
61
58
62
def succeeded (self ) -> "DBTaskResultQuerySet" :
59
63
return self .filter (status = ResultStatus .SUCCEEDED )
@@ -95,10 +99,12 @@ class DBTaskResult(GenericBase[P, T], models.Model):
95
99
96
100
task_path = models .TextField (_ ("task path" ))
97
101
98
- queue_name = models .TextField (_ ("queue name" ), default = DEFAULT_QUEUE_NAME )
99
- backend_name = models .TextField (_ ("backend name" ))
102
+ queue_name = models .CharField (
103
+ _ ("queue name" ), default = DEFAULT_QUEUE_NAME , max_length = 32
104
+ )
105
+ backend_name = models .CharField (_ ("backend name" ), max_length = 32 )
100
106
101
- run_after = models .DateTimeField (_ ("run after" ), null = True )
107
+ run_after = models .DateTimeField (_ ("run after" ), default = DATE_MAX )
102
108
103
109
return_value = models .JSONField (_ ("return value" ), default = None , null = True )
104
110
@@ -108,9 +114,18 @@ class DBTaskResult(GenericBase[P, T], models.Model):
108
114
objects = DBTaskResultQuerySet .as_manager ()
109
115
110
116
class Meta :
111
- ordering = [F ("priority" ).desc (), F ("run_after" ).asc (nulls_last = True )]
117
+ ordering = [F ("priority" ).desc (), F ("run_after" ).asc ()]
112
118
verbose_name = _ ("Task Result" )
113
119
verbose_name_plural = _ ("Task Results" )
120
+ indexes = [
121
+ models .Index (
122
+ "status" , * ordering ,
123
+ name = "django_task_new_ordering_idx" ,
124
+ condition = Q (status = ResultStatus .NEW ),
125
+ ),
126
+ models .Index (fields = ["queue_name" ]),
127
+ models .Index (fields = ["backend_name" ]),
128
+ ]
114
129
115
130
if django .VERSION >= (5 , 1 ):
116
131
constraints = [
@@ -127,6 +142,11 @@ class Meta:
127
142
)
128
143
]
129
144
145
+ def save (self , ** kwargs ):
146
+ if self .run_after is None :
147
+ self .run_after = DATE_MAX
148
+ super ().save (** kwargs )
149
+
130
150
@property
131
151
def task (self ) -> Task [P , T ]:
132
152
task = import_string (self .task_path )
@@ -136,6 +156,9 @@ def task(self) -> Task[P, T]:
136
156
f"Task { self .id } does not point to a Task ({ self .task_path } )"
137
157
)
138
158
159
+ if self .run_after == DATE_MAX :
160
+ self .run_after = None
161
+
139
162
return task .using (
140
163
priority = self .priority ,
141
164
queue_name = self .queue_name ,
0 commit comments