docs: def add_job(cls, identifier, queue_name=None, priority=0, queue_model=None,
                  prepend=False, delayed_for=None, delayed_until=None,
                  **fields_if_new):
          """
          Add a job to a queue.
          If this job already exists, check it's current priority. If its higher
          than the new one, don't touch it, else move the job to the wanted queue.
          Before setting/moving the job to the queue, check for a `delayed_for`
          (int/foat/timedelta) or `delayed_until` (datetime) argument to see if
          it must be delayed instead of queued.
          If the job is created, fields in fields_if_new will be set for the new
          job.
          Finally return the job.
          """
  
          # check for delayed_for/delayed_until arguments
          delayed_until = compute_delayed_until(delayed_for, delayed_until)
  
          # create the job or get an existing one
          job_kwargs = {'identifier': identifier, 'queued': '1'}
          retries = 0
          while retries < 10:
              retries += 1
              try:
                  job, created = cls.get_or_connect(**job_kwargs)
              except IndexError:
                  # Failure during the retrieval https://friendpaste.com/5U63a8aFuV44SEgQckgMP
                  # => retry
                  continue
              except ValueError:
                  # more than one already in the queue !
                  try:
                      job = cls.collection(**job_kwargs).instances()[0]
                  except IndexError:
                      # but no more now ?!
                      # => retry
                      continue
                  else:
                      created = False
  
              # ok we have our job, stop now
              break
  
          try:
              # check queue_name
              queue_name = cls._get_queue_name(queue_name)
  
              # if the job already exists, and we want a higher priority or move it,
              # start by updating it
              if not created:
                  current_priority = int(job.priority.hget() or 0)
                  # if the job has a higher priority, or don't need to be moved,
                  # don't move it
                  if not prepend and current_priority >= priority:
                      return job
  
                  # cancel it temporarily, we'll set it as waiting later
                  job.status.hset(STATUSES.CANCELED)
  
                  # remove it from the current queue, we'll add it to the new one later
                  if queue_model is None:
                      queue_model = cls.queue_model
                  current_queue = queue_model.get_queue(queue_name, current_priority)
                  current_queue.waiting.lrem(0, job.ident)
  
              else:
                  job.set_fields(added=str(datetime.utcnow()), **(fields_if_new or {}))
  
              # add the job to the queue
              job.enqueue_or_delay(queue_name, priority, delayed_until, prepend, queue_model)
  
              return job
          except Exception:
              job.queued.delete()
              raise