Skip to content

Commit 2a9c166

Browse files
committed
[IMP] queue_job: more efficient ChannelJob sorting
1 parent 7cf92ba commit 2a9c166

File tree

1 file changed

+36
-17
lines changed

1 file changed

+36
-17
lines changed

queue_job/jobrunner/channels.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class ChannelJob:
108108
job that are necessary to prioritise them.
109109
110110
Channel jobs are comparable according to the following rules:
111-
* jobs with an eta come before all other jobs
111+
* jobs with an eta cannot be compared with jobs without
112112
* then jobs with a smaller eta come first
113113
* then jobs with a smaller priority come first
114114
* then jobs with a smaller creation time come first
@@ -135,14 +135,18 @@ class ChannelJob:
135135
>>> j3 < j1
136136
True
137137
138-
j4 and j5 comes even before j3, because they have an eta
138+
j4 and j5 have an eta, they cannot be compared with j3
139139
140140
>>> j4 = ChannelJob(None, None, 4,
141141
... seq=0, date_created=4, priority=9, eta=9)
142142
>>> j5 = ChannelJob(None, None, 5,
143143
... seq=0, date_created=5, priority=9, eta=9)
144-
>>> j4 < j5 < j3
144+
>>> j4 < j5
145145
True
146+
>>> j4 < j3
147+
Traceback (most recent call last):
148+
...
149+
TypeError: '<' not supported between instances of 'int' and 'NoneType'
146150
147151
j6 has same date_created and priority as j5 but a smaller eta
148152
@@ -153,7 +157,7 @@ class ChannelJob:
153157
154158
Here is the complete suite:
155159
156-
>>> j6 < j4 < j5 < j3 < j1 < j2
160+
>>> j6 < j4 < j5 and j3 < j1 < j2
157161
True
158162
159163
j0 has the same properties as j1 but they are not considered
@@ -173,16 +177,13 @@ class ChannelJob:
173177
174178
"""
175179

176-
__slots__ = ("db_name", "channel", "uuid", "seq", "date_created", "priority", "eta", "__weakref__")
180+
__slots__ = ("db_name", "channel", "uuid", "_sorting_key", "__weakref__")
177181

178182
def __init__(self, db_name, channel, uuid, seq, date_created, priority, eta):
179183
self.db_name = db_name
180184
self.channel = channel
181185
self.uuid = uuid
182-
self.seq = seq
183-
self.date_created = date_created
184-
self.priority = priority
185-
self.eta = eta
186+
self._sorting_key = (eta, priority, date_created, seq)
186187

187188
def __repr__(self):
188189
return "<ChannelJob %s>" % self.uuid
@@ -193,18 +194,36 @@ def __eq__(self, other):
193194
def __hash__(self):
194195
return id(self)
195196

197+
def set_no_eta(self):
198+
self._sorting_key = (None,) + self._sorting_key[1:]
199+
200+
@property
201+
def seq(self):
202+
return self._sorting_key[3]
203+
204+
@property
205+
def date_created(self):
206+
return self._sorting_key[2]
207+
208+
@property
209+
def priority(self):
210+
return self._sorting_key[1]
211+
212+
@property
213+
def eta(self):
214+
return self._sorting_key[0]
215+
196216
def sorting_key(self):
197-
return self.eta, self.priority, self.date_created, self.seq
217+
# DEPRECATED
218+
return self._sorting_key
198219

199220
def sorting_key_ignoring_eta(self):
200-
return self.priority, self.date_created, self.seq
221+
return self._sorting_key[1:]
201222

202223
def __lt__(self, other):
203-
if self.eta and not other.eta:
204-
return True
205-
elif not self.eta and other.eta:
206-
return False
207-
return self.sorting_key() < other.sorting_key()
224+
# Do not compare job where ETA is set with job where it is not
225+
# If one job 'eta' is set, and the other is None, it raises TypeError
226+
return self._sorting_key < other._sorting_key
208227

209228

210229
class ChannelQueue:
@@ -314,7 +333,7 @@ def remove(self, job):
314333
def pop(self, now):
315334
while self._eta_queue and self._eta_queue[0].eta <= now:
316335
eta_job = self._eta_queue.pop()
317-
eta_job.eta = None
336+
eta_job.set_no_eta()
318337
self._queue.add(eta_job)
319338
if self.sequential and self._eta_queue and self._queue:
320339
eta_job = self._eta_queue[0]

0 commit comments

Comments
 (0)