diff --git a/docs/api.md b/docs/api.md index 3ddfe5cb7..f15d8fe93 100644 --- a/docs/api.md +++ b/docs/api.md @@ -291,7 +291,7 @@ This API is *not atomic* and does not follow the [typical guidelines for a batch messages. The server attempts to issue every code in the batch. If errors are encountered, each item in `codes` will contain the error details for -the corresponding code. The overall request will get the error status code and message of the first seen error, although some codes may have +the corresponding code. The overall request will get the error status code of the first seen error, although some codes may have succeeded. eg. diff --git a/pkg/controller/issueapi/issue_batch.go b/pkg/controller/issueapi/issue_batch.go index 711b53be3..d1ffffb64 100644 --- a/pkg/controller/issueapi/issue_batch.go +++ b/pkg/controller/issueapi/issue_batch.go @@ -16,13 +16,14 @@ package issueapi import ( "errors" + "fmt" "net/http" + "strings" "github.com/google/exposure-notifications-server/pkg/logging" "github.com/google/exposure-notifications-verification-server/pkg/api" "github.com/google/exposure-notifications-verification-server/pkg/controller" "github.com/google/exposure-notifications-verification-server/pkg/observability" - "github.com/hashicorp/go-multierror" ) const maxBatchSize = 10 @@ -79,7 +80,7 @@ func (c *Controller) HandleBatchIssue() http.Handler { } httpCode := http.StatusOK - var merr *multierror.Error + errCount := 0 resp.Codes = make([]*api.IssueCodeResponse, l) for i, singleIssue := range request.Codes { @@ -92,7 +93,7 @@ func (c *Controller) HandleBatchIssue() http.Handler { // continue processing if when a single code issuance fails. // if any issuance fails, the returned code is the code of the first failure. logger.Warnw("single code issuance failed", "error", result.errorReturn) - merr = multierror.Append(merr, errors.New(result.errorReturn.Error)) + errCount++ if resp.Codes[i] == nil { resp.Codes[i] = &api.IssueCodeResponse{} } @@ -100,13 +101,20 @@ func (c *Controller) HandleBatchIssue() http.Handler { resp.Codes[i].Error = result.errorReturn.Error if httpCode == http.StatusOK { httpCode = result.httpCode + resp.ErrorCode = result.errorReturn.ErrorCode } continue } } - if err := merr.ErrorOrNil(); err != nil { - resp.Error = err.Error() + if errCount > 0 { + var sb strings.Builder + sb.WriteString(fmt.Sprintf("Failed to issue %d codes.", errCount)) + if succeeded := len(request.Codes) - errCount; succeeded > 0 { + sb.WriteString(fmt.Sprintf(" Issued %d codes successfully.", succeeded)) + } + sb.WriteString("See each error status in the codes array.") + resp.Error = sb.String() } c.h.RenderJSON(w, httpCode, resp)