code: func (e *engineImpl) AbortJob(c context.Context, job *Job) error {
  	if err := job.CheckRole(c, acl.Owner); err != nil {
  		return err
  	}
  	jobID := job.JobID
  
  	var invs []int64
  	err := e.jobTxn(c, jobID, func(c context.Context, job *Job, isNew bool) (err error) {
  		if isNew {
  			return errSkipPut // the job was removed, nothing to abort
  		}
  		// We just abort all active invocations. This should cause them to
  		// eventually move to Aborted state, which will kick them out of
  		// ActiveInvocations list.
  		invs = job.ActiveInvocations
  		// AbortJob is sometimes used manually to "reset" the job state if it got
  		// stuck for some reason. We initiate a triage for this purpose. This is not
  		// strictly necessary (but doesn't hurt either).
  		return e.kickTriageLater(c, job.JobID, 0)
  	})
  	if err != nil {
  		return err
  	}
  
  	// Now we kill the invocations. We do it separately because it may involve
  	// an RPC to remote service (e.g. to cancel a task) that can't be done from
  	// the transaction.
  	wg := sync.WaitGroup{}
  	wg.Add(len(invs))
  	errs := errors.NewLazyMultiError(len(invs))
  	for i, invID := range invs {
  		go func(i int, invID int64) {
  			defer wg.Done()
  			errs.Assign(i, e.abortInvocation(c, jobID, invID))
  		}(i, invID)
  	}
  	wg.Wait()
  	if err := errs.Get(); err != nil {
  		return transient.Tag.Apply(err)
  	}
  	return nil
  }
docs: // AbortJob aborts all currently pending or running invocations (if any).
  //
  // Part of the public interface, checks ACLs.