func()

in codegen/module.go [1194:1344]


func (system *ModuleSystem) IncrementalBuild(
	packageRoot,
	baseDirectory,
	targetGenDir string,
	instances []ModuleDependency,
	resolvedModules map[string][]*ModuleInstance,
	options Options,
) (map[string][]*ModuleInstance, error) {

	skipModuleMap := map[*ModuleInstance]struct{}{}
	toBeBuiltModules := make(map[string][]*ModuleInstance)

	for _, className := range system.classOrder {
		var wg sync.WaitGroup
		wg.Add(len(resolvedModules[className]))
		ch := make(chan *populateSpecRes, len(resolvedModules[className]))
		for _, instance := range resolvedModules[className] {
			go func(instance *ModuleInstance) {
				defer wg.Done()
				if err := system.populateSpec(instance); err != nil {
					baseErr := errors.Cause(err)
					if _, ok := baseErr.(*IgnorePopulateSpecStageErr); ok {
						return
					}
					if _, ok := baseErr.(*ErrorSkipCodeGen); ok {
						// HACK: to get get of bad modules, which should not be even be loaded in dag at first place
						ch <- &populateSpecRes{mi: instance}
					} else {
						ch <- &populateSpecRes{err: err}
					}
				}
			}(instance)
		}

		go func() {
			wg.Wait()
			close(ch)
		}()

		for psRes := range ch {
			if psRes.err != nil {
				return nil, psRes.err
			}
			skipModuleMap[psRes.mi] = struct{}{}
		}
	}

	resolvedModulesCopy := map[string][]*ModuleInstance{}
	for cls, modules := range resolvedModules {
		for _, m := range modules {
			if _, ok := skipModuleMap[m]; ok {
				// skipping error modules
				fmt.Println("skipping module gen", m.InstanceName)
				continue
			}
			m.RecursiveDependencies = trimSkipDependencies(m.RecursiveDependencies, skipModuleMap)
			m.ResolvedDependencies = trimSkipDependencies(m.ResolvedDependencies, skipModuleMap)
			resolvedModulesCopy[cls] = append(resolvedModulesCopy[cls], m)
		}
	}
	resolvedModules = resolvedModulesCopy

	if instances == nil || len(instances) == 0 {
		for _, modules := range resolvedModules {
			for _, instance := range modules {
				instances = append(instances, instance.AsModuleDependency())
			}
		}
	}

	// If toBeBuiltModules is not empty already, it is likely that one of the modules does not implement
	// the SpecProvider interface, hence incremental build is not possible.
	if len(toBeBuiltModules) == 0 {
		var err error
		toBeBuiltModules, err = system.collectTransitiveDependencies(instances,
			resolvedModules)
		if err != nil {
			// if incrementalBuild fails, perform a full build.
			fmt.Printf("Falling back to full build due to err: %s\n", err.Error())
			toBeBuiltModules = resolvedModules
		}
	}

	moduleCount := 0
	var moduleIndex int32
	for _, moduleList := range toBeBuiltModules {
		moduleCount += len(moduleList)
	}
	qpsLevels, err := PopulateQPSLevels(baseDirectory+"/endpoints", options.QPSLevelsEnabled)
	if err != nil {
		return nil, errors.Errorf(
			"error in populating qps levels for base directory %q",
			baseDirectory,
		)
	}
	for _, class := range system.classOrder {
		var wg sync.WaitGroup
		wg.Add(len(toBeBuiltModules[class]))
		ch := make(chan error, len(toBeBuiltModules[class]))
		for _, moduleInstance := range toBeBuiltModules[class] {
			go func(moduleInstance *ModuleInstance) {
				defer wg.Done()
				physicalGenDir := filepath.Join(targetGenDir, moduleInstance.Directory)
				prettyDir, _ := filepath.Rel(baseDirectory, physicalGenDir)
				PrintGenLine(moduleInstance.ClassType, moduleInstance.ClassName, moduleInstance.InstanceName,
					prettyDir, int(atomic.AddInt32(&moduleIndex, 1)), moduleCount)
				moduleInstance.QPSLevels = qpsLevels
				if err := system.Build(packageRoot, baseDirectory, physicalGenDir, moduleInstance, options); err != nil {
					ch <- err
				}
			}(moduleInstance)
		}

		go func() {
			wg.Wait()
			close(ch)
		}()

		for err := range ch {
			if err != nil {
				return nil, err
			}
		}
	}

	var wg sync.WaitGroup
	ch := make(chan error, len(system.postGenHook))
	for i, hook := range system.postGenHook {
		if hook != nil {
			wg.Add(1)
			go func(hook PostGenHook) {
				defer wg.Done()
				if err := hook(toBeBuiltModules); err != nil {
					ch <- errors.Wrapf(err, "error running %dth post generation hook", i)
				}
			}(hook)
		}
	}

	go func() {
		wg.Wait()
		close(ch)
	}()
	for err := range ch {
		if err != nil {
			return toBeBuiltModules, err
		}
	}

	return toBeBuiltModules, nil
}