(w http.ResponseWriter, req *http.Request)
| 62 | } |
| 63 | |
| 64 | func (h *HATracker) ServeHTTP(w http.ResponseWriter, req *http.Request) { |
| 65 | h.electedLock.RLock() |
| 66 | type replica struct { |
| 67 | UserID string `json:"userID"` |
| 68 | Cluster string `json:"cluster"` |
| 69 | Replica string `json:"replica"` |
| 70 | ElectedAt time.Time `json:"electedAt"` |
| 71 | UpdateTime time.Duration `json:"updateDuration"` |
| 72 | FailoverTime time.Duration `json:"failoverDuration"` |
| 73 | } |
| 74 | |
| 75 | electedReplicas := []replica{} |
| 76 | for key, desc := range h.elected { |
| 77 | chunks := strings.SplitN(key, "/", 2) |
| 78 | |
| 79 | electedReplicas = append(electedReplicas, replica{ |
| 80 | UserID: chunks[0], |
| 81 | Cluster: chunks[1], |
| 82 | Replica: desc.Replica, |
| 83 | ElectedAt: timestamp.Time(desc.ReceivedAt), |
| 84 | UpdateTime: time.Until(timestamp.Time(desc.ReceivedAt).Add(h.cfg.UpdateTimeout)), |
| 85 | FailoverTime: time.Until(timestamp.Time(desc.ReceivedAt).Add(h.cfg.FailoverTimeout)), |
| 86 | }) |
| 87 | } |
| 88 | h.electedLock.RUnlock() |
| 89 | |
| 90 | sort.Slice(electedReplicas, func(i, j int) bool { |
| 91 | first := electedReplicas[i] |
| 92 | second := electedReplicas[j] |
| 93 | |
| 94 | if first.UserID != second.UserID { |
| 95 | return first.UserID < second.UserID |
| 96 | } |
| 97 | return first.Cluster < second.Cluster |
| 98 | }) |
| 99 | |
| 100 | util.RenderHTTPResponse(w, struct { |
| 101 | Elected []replica `json:"elected"` |
| 102 | Now time.Time `json:"now"` |
| 103 | Config HATrackerStatusConfig `json:"config"` |
| 104 | }{ |
| 105 | Elected: electedReplicas, |
| 106 | Now: time.Now(), |
| 107 | Config: h.trackerStatusConfig, |
| 108 | }, trackerTmpl, req) |
| 109 | } |
nothing calls this directly
no test coverage detected