func()

in internal/pkg/agent/application/coordinator/coordinator.go [1619:1749]


func (c *Coordinator) checkAndLogUpdate(lastComponentModel []component.Component) {
	if lastComponentModel == nil {
		c.logger.Debugf("Received initial component update; total of %d components", len(c.componentModel))
		return
	}

	type compCheck struct {
		inCurrent bool
		inLast    bool

		diffUnits map[string]diffCheck
	}

	lastCompMap := convertComponentListToMap(lastComponentModel)
	currentCompMap := convertComponentListToMap(c.componentModel)

	compDiffMap := map[string]compCheck{}
	outDiffMap := map[string]diffCheck{}
	// kinda-callbacks for dealing with output logic
	foundInLast := func(outName string) {
		if outDiff, ok := outDiffMap[outName]; ok {
			outDiff.inLast = true
			outDiffMap[outName] = outDiff
		} else {
			outDiffMap[outName] = diffCheck{inLast: true}
		}
	}

	foundInUpdated := func(outName string) {
		if outDiff, ok := outDiffMap[outName]; ok {
			outDiff.inNew = true
			outDiffMap[outName] = outDiff
		} else {
			outDiffMap[outName] = diffCheck{inNew: true}
		}
	}

	// diff the maps

	// find added & updated components
	for id, comp := range currentCompMap {
		// check output
		foundInUpdated(comp.OutputType)
		// compare with last state
		diff := compCheck{inCurrent: true}
		if lastComp, ok := lastCompMap[id]; ok {
			diff.inLast = true
			// if the unit is in both the past and previous, check for updated units
			diff.diffUnits = diffUnitList(lastComp.Units, comp.Units)
			foundInLast(lastComp.OutputType)
			// a bit of optimization: after we're done, we'll need to iterate over lastCompMap to fetch removed units,
			// so delete items we don't need to iterate over
			delete(lastCompMap, id)
		}
		compDiffMap[id] = diff
	}

	// find removed components
	// if something is still in this map, that means it's only in this map
	for id, comp := range lastCompMap {
		compDiffMap[id] = compCheck{inLast: true}
		foundInLast(comp.OutputType)
	}

	addedList := []string{}
	removedList := []string{}

	formattedUpdated := []string{}

	// reduced to list of added/removed outputs
	addedOutputs := []string{}
	removedOutputs := []string{}

	// take our diff map and format everything for output
	for id, diff := range compDiffMap {
		if diff.inLast && !diff.inCurrent {
			removedList = append(removedList, id)
		}
		if !diff.inLast && diff.inCurrent {
			addedList = append(addedList, id)
		}
		// format a user-readable list of diffs
		if diff.inLast && diff.inCurrent {
			units := []string{}
			for unitId, state := range diff.diffUnits {
				action := ""
				if state.inLast && !state.inNew {
					action = "removed"
				}
				if state.inNew && !state.inLast {
					action = "added"
				}
				if state.updated {
					action = "updated"
				}
				if action != "" {
					units = append(units, fmt.Sprintf("(%s: %s)", unitId, action))
				}
			}
			if len(units) > 0 {
				formatted := fmt.Sprintf("%s: %v", id, units)
				formattedUpdated = append(formattedUpdated, formatted)
			}
		}
	}

	// format outputs
	for output, comp := range outDiffMap {
		if comp.inLast && !comp.inNew {
			removedOutputs = append(removedOutputs, output)
		}
		if !comp.inLast && comp.inNew {
			addedOutputs = append(addedOutputs, output)
		}
	}

	logStruct := UpdateStats{
		Components: UpdateComponentChange{
			Added:   addedList,
			Removed: removedList,
			Count:   len(c.componentModel),
			Updated: formattedUpdated,
		},
		Outputs: UpdateComponentChange{
			Added:   addedOutputs,
			Removed: removedOutputs,
		},
	}

	c.logger.Infow("component model updated", "changes", logStruct)
}