code: def _updateJobWhenDone(self):
          
  
          def asyncUpdate():
              try:
                  # Wait till all file writes have completed
                  for i in range(len(self.workers)):
                      self.queue.put(None)
  
                  for thread in self.workers:
                      thread.join()
  
                  # Wait till input block-fn returns - in the event of an exception
                  # this will eventually terminate
                  self.inputBlockFn()
  
                  # Check the terminate event, if set we can not guarantee
                  # that the workers ended correctly, therefore we exit without
                  # completing the update
                  if self._terminateEvent.isSet():
                      raise RuntimeError("The termination flag is set, exiting before update")
  
                  # Indicate any files that should be deleted once the update of
                  # the job wrapper is completed.
                  self.jobGraph.filesToDelete = list(self.filesToDelete)
  
                  # Complete the job
                  self.jobStore.update(self.jobGraph)
  
                  # Delete any remnant jobs
                  list(map(self.jobStore.delete, self.jobsToDelete))
  
                  # Delete any remnant files
                  list(map(self.jobStore.deleteFile, self.filesToDelete))
  
                  # Remove the files to delete list, having successfully removed the files
                  if len(self.filesToDelete) > 0:
                      self.jobGraph.filesToDelete = []
                      # Update, removing emptying files to delete
                      self.jobStore.update(self.jobGraph)
              except:
                  self._terminateEvent.set()
                  raise
              finally:
                  # Indicate that _blockFn can return
                  # This code will always run
                  self.updateSemaphore.release()
  
          # The update semaphore is held while the job is written to the job store
          try:
              self.updateSemaphore.acquire()
              t = Thread(target=asyncUpdate)
              t.start()
          except:
              # This is to ensure that the semaphore is released in a crash to stop a deadlock
              # scenario
              self.updateSemaphore.release()
              raise
docs: Asynchronously update the status of the job on the disk, first waiting \
          until the writing threads have finished and the input blockFn has stopped \
          blocking.