22# Copyright 2015-2016 Camptocamp SA
33# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)
44import logging
5+ from collections import namedtuple
56from functools import total_ordering
67from heapq import heappop , heappush
78from weakref import WeakValueDictionary
1011from ..job import CANCELLED , DONE , ENQUEUED , FAILED , PENDING , STARTED , WAIT_DEPENDENCIES
1112
1213NOT_DONE = (WAIT_DEPENDENCIES , PENDING , ENQUEUED , STARTED , FAILED )
14+ JobSortingKey = namedtuple ("SortingKey" , "eta priority date_created seq" )
1315
1416_logger = logging .getLogger (__name__ )
1517
@@ -108,7 +110,7 @@ class ChannelJob:
108110 job that are necessary to prioritise them.
109111
110112 Channel jobs are comparable according to the following rules:
111- * jobs with an eta come before all other jobs
113+ * jobs with an eta cannot be compared with jobs without
112114 * then jobs with a smaller eta come first
113115 * then jobs with a smaller priority come first
114116 * then jobs with a smaller creation time come first
@@ -135,14 +137,18 @@ class ChannelJob:
135137 >>> j3 < j1
136138 True
137139
138- j4 and j5 comes even before j3, because they have an eta
140+ j4 and j5 have an eta, they cannot be compared with j3
139141
140142 >>> j4 = ChannelJob(None, None, 4,
141143 ... seq=0, date_created=4, priority=9, eta=9)
142144 >>> j5 = ChannelJob(None, None, 5,
143145 ... seq=0, date_created=5, priority=9, eta=9)
144- >>> j4 < j5 < j3
146+ >>> j4 < j5
145147 True
148+ >>> j4 < j3
149+ Traceback (most recent call last):
150+ ...
151+ TypeError: '<' not supported between instances of 'int' and 'NoneType'
146152
147153 j6 has same date_created and priority as j5 but a smaller eta
148154
@@ -153,7 +159,7 @@ class ChannelJob:
153159
154160 Here is the complete suite:
155161
156- >>> j6 < j4 < j5 < j3 < j1 < j2
162+ >>> j6 < j4 < j5 and j3 < j1 < j2
157163 True
158164
159165 j0 has the same properties as j1 but they are not considered
@@ -173,14 +179,13 @@ class ChannelJob:
173179
174180 """
175181
182+ __slots__ = ("db_name" , "channel" , "uuid" , "_sorting_key" , "__weakref__" )
183+
176184 def __init__ (self , db_name , channel , uuid , seq , date_created , priority , eta ):
177185 self .db_name = db_name
178186 self .channel = channel
179187 self .uuid = uuid
180- self .seq = seq
181- self .date_created = date_created
182- self .priority = priority
183- self .eta = eta
188+ self ._sorting_key = JobSortingKey (eta , priority , date_created , seq )
184189
185190 def __repr__ (self ):
186191 return "<ChannelJob %s>" % self .uuid
@@ -191,18 +196,36 @@ def __eq__(self, other):
191196 def __hash__ (self ):
192197 return id (self )
193198
199+ def set_no_eta (self ):
200+ self ._sorting_key = JobSortingKey (None , * self ._sorting_key [1 :])
201+
202+ @property
203+ def seq (self ):
204+ return self ._sorting_key .seq
205+
206+ @property
207+ def date_created (self ):
208+ return self ._sorting_key .date_created
209+
210+ @property
211+ def priority (self ):
212+ return self ._sorting_key .priority
213+
214+ @property
215+ def eta (self ):
216+ return self ._sorting_key .eta
217+
194218 def sorting_key (self ):
195- return self .eta , self .priority , self .date_created , self .seq
219+ # DEPRECATED
220+ return self ._sorting_key
196221
197222 def sorting_key_ignoring_eta (self ):
198- return self .priority , self . date_created , self . seq
223+ return self ._sorting_key [ 1 :]
199224
200225 def __lt__ (self , other ):
201- if self .eta and not other .eta :
202- return True
203- elif not self .eta and other .eta :
204- return False
205- return self .sorting_key () < other .sorting_key ()
226+ # Do not compare job where ETA is set with job where it is not
227+ # If one job 'eta' is set, and the other is None, it raises TypeError
228+ return self ._sorting_key < other ._sorting_key
206229
207230
208231class ChannelQueue :
@@ -312,7 +335,7 @@ def remove(self, job):
312335 def pop (self , now ):
313336 while self ._eta_queue and self ._eta_queue [0 ].eta <= now :
314337 eta_job = self ._eta_queue .pop ()
315- eta_job .eta = None
338+ eta_job .set_no_eta ()
316339 self ._queue .add (eta_job )
317340 if self .sequential and self ._eta_queue and self ._queue :
318341 eta_job = self ._eta_queue [0 ]
0 commit comments