code: func (e *engineImpl) initInvocation(c context.Context, jobID string, inv *Invocation, req *task.Request) (*Invocation, error) {
  	assertInTransaction(c)
  
  	invID, err := generateInvocationID(c)
  	if err != nil {
  		return nil, errors.Annotate(err, "failed to generate invocation ID").Err()
  	}
  	inv.ID = invID
  	inv.JobID = jobID
  
  	if req != nil {
  		if err := putRequestIntoInv(inv, req); err != nil {
  			return nil, errors.Annotate(err, "failed to serialize task request").Err()
  		}
  		if req.DebugLog != "" {
  			inv.DebugLog += "Debug output from the triage procedure:\n"
  			inv.DebugLog += "---------------------------------------\n"
  			inv.DebugLog += req.DebugLog
  			inv.DebugLog += "---------------------------------------\n\n"
  			inv.trimDebugLog() // in case it is HUGE
  			inv.DebugLog += "Debug output from the invocation itself:\n"
  		}
  	}
  	return inv, nil
  }
docs: // initInvocation populates fields of Invocation struct.
  //
  // It allocates invocation ID and populates ID and JobID fields. It also copies
  // data from the given task.Request object into the corresponding fields of the
  // invocation entity (so they can be indexed etc).
  //
  // On success returns exact same 'inv' for convenience. It doesn't Put it into
  // the datastore.
  //
  // Must be called within a transaction, since it verifies an allocated ID is
  // not used yet.