2323from . import context
2424
2525
26+ FINAL_STATUSES = {"timeout" , "abort" , "failed" , "success" , "interrupt" , "retry" , "maxretries" , "maxconcurrency" }
27+ TRANSIENT_STATUSES = {"cancel" , "queued" , "started" }
28+
29+
2630class Job (object ):
2731
2832 timeout = None
@@ -438,6 +442,11 @@ def _save_status(self, status, updates=None, exception=False, w=None, j=None):
438442 if self .id is None :
439443 return
440444
445+ # Forbid some status transitions
446+ if self .data and self .data .get ("status" ) in FINAL_STATUSES and status not in TRANSIENT_STATUSES :
447+ context .log .error ("Can't go from status %s to %s" % (self .data ["status" ], status ))
448+ return
449+
441450 context .metric ("jobs.status.%s" % status )
442451
443452 if self .stored is False and self .statuses_no_storage is not None and status in self .statuses_no_storage :
@@ -476,7 +485,8 @@ def _save_status(self, status, updates=None, exception=False, w=None, j=None):
476485 db_updates ["traceback" ] = trace
477486 db_updates ["exceptiontype" ] = exc .__name__
478487
479- self ._save_traceback_history (status , trace , exc )
488+ if self .data :
489+ self .data .update (db_updates )
480490
481491 # In the most common case, we allow an optimization on Mongo writes
482492 if status == "success" :
@@ -500,8 +510,9 @@ def _save_status(self, status, updates=None, exception=False, w=None, j=None):
500510 "_id" : self .id
501511 }, {"$set" : db_updates }, w = w , j = j , manipulate = False )
502512
503- if self .data :
504- self .data .update (db_updates )
513+ if exception :
514+ self ._save_traceback_history (status , trace , exc )
515+
505516
506517 def set_current_io (self , io_data ):
507518
0 commit comments