func getServerUpdateStatuses()

in traffic_ops/traffic_ops_golang/server/servers_update_status.go [314:434]


func getServerUpdateStatuses(db *sql.DB, timeout time.Duration) (map[string][]tc.ServerUpdateStatusV5, error) {
	dbCtx, dbClose := context.WithTimeout(context.Background(), timeout)
	defer dbClose()
	serversByID := make(map[int]serverInfo)
	updatePendingByCDNCachegroup := make(map[int]map[int]bool)
	revalPendingByCDNCachegroup := make(map[int]map[int]bool)
	tx, err := db.BeginTx(dbCtx, nil)
	if err != nil {
		return nil, fmt.Errorf("beginning server update status transaction: %w", err)
	}
	defer func() {
		if err := tx.Commit(); err != nil && err != sql.ErrTxDone {
			log.Errorln("committing server update status transaction: " + err.Error())
		}
	}()

	useRevalPending := false
	if err := tx.QueryRowContext(dbCtx, getUseRevalPendingQuery).Scan(&useRevalPending); err != nil {
		return nil, fmt.Errorf("querying use_reval_pending param: %w", err)
	}

	// get all servers and build map of update/revalPending by cachegroup+CDN
	serverRows, err := tx.QueryContext(dbCtx, getServerInfoQuery)
	if err != nil {
		return nil, fmt.Errorf("querying servers: %w", err)
	}
	defer log.Close(serverRows, "closing server rows")
	for serverRows.Next() {
		s := serverInfo{}
		if err := serverRows.Scan(&s.id, &s.hostName, &s.typeName, &s.cdnId, &s.status, &s.cachegroup, &s.configUpdateTime, &s.configApplyTime, &s.configUpdateFailed, &s.revalUpdateTime, &s.revalApplyTime, &s.revalUpdateFailed); err != nil {
			return nil, fmt.Errorf("scanning servers: %w", err)
		}
		serversByID[s.id] = s
		if _, ok := updatePendingByCDNCachegroup[s.cdnId]; !ok {
			updatePendingByCDNCachegroup[s.cdnId] = make(map[int]bool)
		}
		if _, ok := revalPendingByCDNCachegroup[s.cdnId]; !ok {
			revalPendingByCDNCachegroup[s.cdnId] = make(map[int]bool)
		}
		status := tc.CacheStatusFromString(s.status)
		if tc.IsValidCacheType(s.typeName) && (status == tc.CacheStatusOnline || status == tc.CacheStatusReported || status == tc.CacheStatusAdminDown) {
			if s.configUpdateTime.After(*s.configApplyTime) {
				updatePendingByCDNCachegroup[s.cdnId][s.cachegroup] = true
			}
			if s.revalUpdateTime.After(*s.revalApplyTime) {
				revalPendingByCDNCachegroup[s.cdnId][s.cachegroup] = true
			}
		}
	}
	if err := serverRows.Err(); err != nil {
		return nil, fmt.Errorf("iterating over server rows: %w", err)
	}

	// get all legacy cachegroup parents
	cacheGroupParents := make(map[int]map[int]struct{})
	cacheGroupRows, err := tx.QueryContext(dbCtx, getCacheGroupsQuery)
	if err != nil {
		return nil, fmt.Errorf("querying cachegroups: %w", err)
	}
	defer log.Close(cacheGroupRows, "closing cachegroup rows")
	for cacheGroupRows.Next() {
		id := 0
		parentID := new(int)
		secondaryParentID := new(int)
		if err := cacheGroupRows.Scan(&id, &parentID, &secondaryParentID); err != nil {
			return nil, fmt.Errorf("scanning cachegroups: %w", err)
		}
		cacheGroupParents[id] = make(map[int]struct{})
		if parentID != nil {
			cacheGroupParents[id][*parentID] = struct{}{}
		}
		if secondaryParentID != nil {
			cacheGroupParents[id][*secondaryParentID] = struct{}{}
		}
	}
	if err := cacheGroupRows.Err(); err != nil {
		return nil, fmt.Errorf("iterating over cachegroup rows: %w", err)
	}

	// get all topology-based cachegroup parents
	topologyCachegroupRows, err := tx.QueryContext(dbCtx, getTopologyCacheGroupParentsQuery)
	if err != nil {
		return nil, fmt.Errorf("querying topology cachegroups: %w", err)
	}
	defer log.Close(topologyCachegroupRows, "closing topology cachegroup rows")
	for topologyCachegroupRows.Next() {
		id := 0
		parents := []int32{}
		if err := topologyCachegroupRows.Scan(&id, pq.Array(&parents)); err != nil {
			return nil, fmt.Errorf("scanning topology cachegroup rows: %w", err)
		}
		for _, p := range parents {
			cacheGroupParents[id][int(p)] = struct{}{}
		}
	}
	if err = topologyCachegroupRows.Err(); err != nil {
		return nil, fmt.Errorf("iterating over topology cachegroup rows: %w", err)
	}

	serverUpdateStatuses := make(map[string][]tc.ServerUpdateStatusV5, len(serversByID))
	for serverID, server := range serversByID {
		updateStatus := tc.ServerUpdateStatusV5{
			HostName:               server.hostName,
			UpdatePending:          server.configUpdateTime.After(*server.configApplyTime),
			RevalPending:           server.revalUpdateTime.After(*server.revalApplyTime),
			UseRevalPending:        useRevalPending,
			HostId:                 serverID,
			Status:                 server.status,
			ParentPending:          getParentPending(cacheGroupParents[server.cachegroup], updatePendingByCDNCachegroup[server.cdnId]),
			ParentRevalPending:     getParentPending(cacheGroupParents[server.cachegroup], revalPendingByCDNCachegroup[server.cdnId]),
			ConfigUpdateTime:       server.configUpdateTime,
			ConfigApplyTime:        server.configApplyTime,
			ConfigUpdateFailed:     &server.configUpdateFailed,
			RevalidateUpdateTime:   server.revalUpdateTime,
			RevalidateApplyTime:    server.revalApplyTime,
			RevalidateUpdateFailed: &server.revalUpdateFailed,
		}
		serverUpdateStatuses[server.hostName] = append(serverUpdateStatuses[server.hostName], updateStatus)
	}
	return serverUpdateStatuses, nil
}