Error handling in northbound interface und testing
Wir haben aktuell eine Unstimmigkeit beim Error-Handling zwischen gRPC Server (goSDN Controller) und allem was über das NBI kommuniziert. Wir haben ein eigenes Status
Feld in jeder Response, welche auch Fehler ausdrücken kann. Status kann die folgenden Werte haben:
enum Status {
STATUS_UNSPECIFIED = 0;
STATUS_OK = 1;
STATUS_ERROR = 2;
}
Dadurch können wir aber nicht mehr ohne weiteres das Fehlerhandling von gRPC nutzen und müssen immer eine korrekte Response senden und können darin unseren Fehlercode transportieren.
Generell ist die Implementierung in allen Entities gleich, daher nehmen wir hier die User
Entity als Beispiel.
Im Erfolgsfall returnen wir code:
return &apb.CreateUsersResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
}, nil
Im Fehlerfall returnen wir code:
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
oder reichen den Fehler aus dem Service Layer durch code:
userData, err := u.userService.Get(store.Query{Name: request.Name, ID: userID})
if err != nil {
return nil, err
}
Demnach gibt es im Fehlerfall kein Status
Feld in der Response. In den Tests testen wir jedoch immer auf den Wert dieses Status Felds (zb hier).
Validation Errors werden aber korrekt in einen Error Status gepackt, zB
if err := t.protoValidator.Validate(request); err != nil {
return nil, status.Errorf(codes.Aborted, "%v", err)
}
aber damit ist "unser" return Status nil
und wir können in tests nicht darauf zugreifen.
Lösungsmöglichkeiten
Wir können unsern eigenen Status entfernen und im Fehlerfall immer den gRPC Weg nehmen und unseren Fehler darin wrappen:
return status.Errorf(codes.Aborted, "%v", err)