code: func (e *engineImpl) UpdateProjectJobs(c context.Context, projectID string, defs []catalog.Definition) error {
  	// JobID -> *Job map.
  	existing, err := e.getProjectJobs(c, projectID)
  	if err != nil {
  		return err
  	}
  	// JobID -> new definition revision map.
  	updated := make(map[string]string, len(defs))
  	for _, def := range defs {
  		updated[def.JobID] = def.Revision
  	}
  	// List of job ids to disable.
  	var toDisable []string
  	for id := range existing {
  		if updated[id] == "" {
  			toDisable = append(toDisable, id)
  		}
  	}
  
  	wg := sync.WaitGroup{}
  
  	// Add new jobs, update existing ones.
  	updateErrs := errors.NewLazyMultiError(len(defs))
  	for i, def := range defs {
  		if ent := existing[def.JobID]; ent != nil {
  			if ent.Enabled && ent.MatchesDefinition(def) {
  				continue
  			}
  		}
  		wg.Add(1)
  		go func(i int, def catalog.Definition) {
  			updateErrs.Assign(i, e.updateJob(c, def))
  			wg.Done()
  		}(i, def)
  	}
  
  	// Disable old jobs.
  	disableErrs := errors.NewLazyMultiError(len(toDisable))
  	for i, jobID := range toDisable {
  		wg.Add(1)
  		go func(i int, jobID string) {
  			disableErrs.Assign(i, e.disableJob(c, jobID))
  			wg.Done()
  		}(i, jobID)
  	}
  
  	wg.Wait()
  	if updateErrs.Get() == nil && disableErrs.Get() == nil {
  		return nil
  	}
  	return transient.Tag.Apply(errors.NewMultiError(updateErrs.Get(), disableErrs.Get()))
  }
docs: // UpdateProjectJobs adds new, removes old and updates existing jobs.
  //
  // Part of the internal interface, doesn't check ACLs.