code: func (e *engineImpl) withController(c context.Context, jobID string, invID int64, action string, cb func(context.Context, *taskController) error) error {
  	c = logging.SetField(c, "JobID", jobID)
  	c = logging.SetField(c, "InvID", invID)
  
  	logging.Infof(c, "Handling %s", action)
  
  	inv, err := e.getInvocation(c, jobID, invID)
  	switch {
  	case err != nil:
  		logging.WithError(err).Errorf(c, "Failed to fetch the invocation")
  		return err
  	case inv.Status.Final():
  		logging.Infof(c, "Skipping %s, the invocation is in final state %q", action, inv.Status)
  		return nil
  	}
  
  	ctl, err := controllerForInvocation(c, e, inv)
  	if err != nil {
  		logging.WithError(err).Errorf(c, "Cannot get the controller")
  		return err
  	}
  
  	if err := cb(c, ctl); err != nil {
  		logging.WithError(err).Errorf(c, "Failed to perform %s, skipping saving the invocation", action)
  		return err
  	}
  
  	if err := ctl.Save(c); err != nil {
  		logging.WithError(err).Errorf(c, "Error when saving the invocation")
  		return err
  	}
  
  	return nil
  }
docs: // withController fetches the invocation, instantiates the task controller,
  // calls the callback, and saves back the modified invocation state, initiating
  // all necessary engine transitions along the way.
  //
  // Does nothing and returns nil if the invocation is already in a final state.
  // The callback is not called in this case at all.
  //
  // Skips saving the invocation if the callback returns non-nil.
  //
  // 'action' is used exclusively for logging. It's a human readable cause of why
  // the controller is instantiated.