in pkg/degradation-detector/postDegradation.go [59:140]
func PostDegradations(client *http.Client, backendURL string, degradations <-chan DegradationWithSettings) chan InsertionResults {
url := backendURL + "/api/meta/accidents"
insertionResults := make(chan InsertionResults, 100)
go func() {
defer close(insertionResults)
var wg sync.WaitGroup
accidentStates := sync.Map{} // map[string]*accidentState
for degradation := range degradations {
wg.Go(func() {
d := degradation.Details
if d.timestamp < time.Now().Add(-672*time.Hour).UnixMilli() { // Do not post degradations older than 28 days
return
}
accidentKey := fmt.Sprintf("%s:%s", degradation.Settings.DBTestName(), d.Build)
stateInterface, _ := accidentStates.LoadOrStore(accidentKey, &accidentState{})
state, ok := stateInterface.(*accidentState)
if !ok {
insertionResults <- InsertionResults{Error: errors.New("unexpected type in accidentStates map")}
return
}
state.mu.Lock()
defer state.mu.Unlock()
if state.posted {
if state.successfullyInserted {
insertionResults <- InsertionResults{DegradationWithSettings{d, degradation.Settings}, nil}
}
return
}
state.posted = true
date := time.UnixMilli(d.timestamp).UTC().Format("2006-01-02")
medianMessage := getMessageBasedOnMedianChange(d.medianValues)
kind := "InferredRegression"
if !d.IsDegradation {
kind = "InferredImprovement"
}
insertParams := meta.AccidentInsertParams{Date: date, Test: degradation.Settings.DBTestName(), Kind: kind, Reason: medianMessage, BuildNumber: d.Build, UserName: "R2D2"}
params, err := json.Marshal(insertParams)
if err != nil {
insertionResults <- InsertionResults{Error: fmt.Errorf("failed to marshal query: %w", err)}
return
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(params))
if err != nil {
insertionResults <- InsertionResults{Error: fmt.Errorf("failed to create request: %w", err)}
return
}
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
insertionResults <- InsertionResults{Error: fmt.Errorf("failed to send POST request: %w", err)}
return
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
state.successfullyInserted = true
insertionResults <- InsertionResults{DegradationWithSettings{d, degradation.Settings}, nil}
return
}
// the accident already exists
if resp.StatusCode == http.StatusConflict {
return
}
insertionResults <- InsertionResults{Error: fmt.Errorf("failed to post Details: %v", resp.Status)}
})
}
wg.Wait()
}()
return insertionResults
}