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
}