code: func (e *engineImpl) allocateInvocation(c context.Context, job *Job, req task.Request) (*Invocation, error) {
  	var inv *Invocation
  	err := runIsolatedTxn(c, func(c context.Context) (err error) {
  		inv, err = e.initInvocation(c, job.JobID, &Invocation{
  			Started:         clock.Now(c).UTC(),
  			Revision:        job.Revision,
  			RevisionURL:     job.RevisionURL,
  			Task:            job.Task,
  			TriggeredJobIDs: job.TriggeredJobIDs,
  			Status:          task.StatusStarting,
  		}, &req)
  		if err != nil {
  			return
  		}
  		inv.debugLog(c, "New invocation is queued and will start shortly")
  		if req.TriggeredBy != "" {
  			inv.debugLog(c, "Triggered by %s", req.TriggeredBy)
  		}
  		return transient.Tag.Apply(ds.Put(c, inv))
  	})
  	if err != nil {
  		return nil, err
  	}
  	return inv, nil
  }
docs: // allocateInvocation creates new Invocation entity in a separate transaction.