code: func (s *Server) updateLocalLegacyACLs(changes structs.ACLRequests, ctx context.Context) (bool, error) {
  	defer metrics.MeasureSince([]string{"leader", "updateLocalACLs"}, time.Now())
  
  	minTimePerOp := time.Second / time.Duration(s.config.ACLReplicationApplyLimit)
  	for _, change := range changes {
  		// Note that we are using the single ACL interface here and not
  		// performing all this inside a single transaction. This is OK
  		// for two reasons. First, there's nothing else other than this
  		// replication routine that alters the local ACLs, so there's
  		// nothing to contend with locally. Second, if an apply fails
  		// in the middle (most likely due to losing leadership), the
  		// next replication pass will clean up and check everything
  		// again.
  		var reply string
  		start := time.Now()
  		if err := aclApplyInternal(s, change, &reply); err != nil {
  			return false, err
  		}
  
  		// Do a smooth rate limit to wait out the min time allowed for
  		// each op. If this op took longer than the min, then the sleep
  		// time will be negative and we will just move on.
  		elapsed := time.Since(start)
  		select {
  		case <-ctx.Done():
  			return true, nil
  		case <-time.After(minTimePerOp - elapsed):
  			// do nothing
  		}
  	}
  	return false, nil
  }
docs: // UpdateLocalACLs is given a list of changes to apply in order to bring the
  // local ACLs in-line with the remote ACLs from the ACL datacenter.