class_docstr: Python TaskScheduler object.
  
  This is the simplest object that supports msg_id based
  DAG dependencies. *Only* task msg_ids are checked, not
  msg_ids of jobs submitted via the MUX queue.
class_docstr_tok: ["Python","TaskScheduler","object",".","This","is","the","simplest","object","that","supports","msg_id","based","DAG","dependencies",".","*","Only","*","task","msg_ids","are","checked",",","not","msg_ids","of","jobs","submitted","via","the","MUX","queue","."]
docstr: dep_id just finished. Update our dependency
  graph and submit any jobs that just became runnable.
  
  Called with dep_id=None to update entire graph for hwm, but without finishing a task.
docstr_tok: ["dep_id","just","finished",".","Update","our","dependency","graph","and","submit","any","jobs","that","just","became","runnable",".","Called","with","dep_id=None","to","update","entire","graph","for","hwm",",","but","without","finishing","a","task","."]
code: def update_graph(self, dep_id=None, success=True):
      """dep_id just finished. Update our dependency
      graph and submit any jobs that just became runnable.
  
      Called with dep_id=None to update entire graph for hwm, but without finishing a task.
      """
      # print ("\n\n***********")
      # pprint (dep_id)
      # pprint (self.graph)
      # pprint (self.queue_map)
      # pprint (self.all_completed)
      # pprint (self.all_failed)
      # print ("\n\n***********\n\n")
      # update any jobs that depended on the dependency
      msg_ids = self.graph.pop(dep_id, [])
  
      # recheck *all* jobs if
      # a) we have HWM and an engine just become no longer full
      # or b) dep_id was given as None
  
      if (
          dep_id is None
          or self.hwm
          and any([load == self.hwm - 1 for load in self.loads])
      ):
          jobs = self.queue
          using_queue = True
      else:
          using_queue = False
          jobs = deque(
              sorted(self.queue_map[msg_id] for msg_id in msg_ids)
          )
  
      to_restore = []
      while jobs:
          job = jobs.popleft()
          if job.removed:
              continue
          msg_id = job.msg_id
  
          put_it_back = True
  
          if job.after.unreachable(
              self.all_completed, self.all_failed
          ) or job.follow.unreachable(
              self.all_completed, self.all_failed
          ):
              self.fail_unreachable(msg_id)
              put_it_back = False
  
          elif job.after.check(
              self.all_completed, self.all_failed
          ):  # time deps met, maybe run
              if self.maybe_run(job):
                  put_it_back = False
                  self.queue_map.pop(msg_id)
                  for mid in job.dependents:
                      if mid in self.graph:
                          self.graph[mid].remove(msg_id)
  
                  # abort the loop if we just filled up all of our engines.
                  # avoids an O(N) operation in situation of full queue,
                  # where graph update is triggered as soon as an engine becomes
                  # non-full, and all tasks after the first are checked,
                  # even though they can't run.
                  if not self.available_engines():
                      break
  
          if using_queue and put_it_back:
              # popped a job from the queue but it neither ran nor failed,
              # so we need to put it back when we are done
              # make sure to_restore preserves the same ordering
              to_restore.append(job)
  
      # put back any tasks we popped but didn't run
      if using_queue:
          self.queue.extendleft(to_restore)
  
imports: import time
  from collections import deque
  from random import randint, random
  from types import FunctionType
  import zmq
  from traitlets import Dict, Enum, Instance, Integer, List, observe
  from ipyparallel import Dependency, error, util
  from ipyparallel.controller.scheduler import Scheduler
label_desc: Use image node_id 20 for calling the TaskScheduler obj's underlying member method code with example usage: obj.update_graph(dep_id, success) without return types