Skip to content

Commit

Permalink
remove go-multierror lib (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
theganyo committed Mar 24, 2021
1 parent 3355f79 commit 9e03f80
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 19 deletions.
20 changes: 10 additions & 10 deletions analytics/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import (
"unicode/utf8"

"github.com/apigee/apigee-remote-service-golib/v2/auth"
"github.com/apigee/apigee-remote-service-golib/v2/errorset"
"github.com/apigee/apigee-remote-service-golib/v2/log"
"github.com/google/uuid"
"github.com/hashicorp/go-multierror"
)

const (
Expand Down Expand Up @@ -102,36 +102,36 @@ func (r Record) validate(now time.Time) error {

// Validate that certain fields are set.
if r.Organization == "" {
err = multierror.Append(err, errors.New("missing Organization"))
err = errorset.Append(err, errors.New("missing Organization"))
}
if r.Environment == "" {
err = multierror.Append(err, errors.New("missing Environment"))
err = errorset.Append(err, errors.New("missing Environment"))
}
if r.GatewayFlowID == "" {
err = multierror.Append(err, errors.New("missing GatewayFlowID"))
err = errorset.Append(err, errors.New("missing GatewayFlowID"))
}
if r.ClientReceivedStartTimestamp == 0 {
err = multierror.Append(err, errors.New("missing ClientReceivedStartTimestamp"))
err = errorset.Append(err, errors.New("missing ClientReceivedStartTimestamp"))
}
if r.ClientReceivedEndTimestamp == 0 {
err = multierror.Append(err, errors.New("missing ClientReceivedEndTimestamp"))
err = errorset.Append(err, errors.New("missing ClientReceivedEndTimestamp"))
}
if r.ClientReceivedStartTimestamp > r.ClientReceivedEndTimestamp {
err = multierror.Append(err, errors.New("ClientReceivedStartTimestamp > ClientReceivedEndTimestamp"))
err = errorset.Append(err, errors.New("ClientReceivedStartTimestamp > ClientReceivedEndTimestamp"))
}

// Validate that timestamps make sense.
ts := time.Unix(r.ClientReceivedStartTimestamp/1000, 0)
if ts.After(now.Add(time.Minute)) { // allow a minute of tolerance
err = multierror.Append(err, errors.New("ClientReceivedStartTimestamp cannot be in the future"))
err = errorset.Append(err, errors.New("ClientReceivedStartTimestamp cannot be in the future"))
}
if ts.Before(now.Add(-90 * 24 * time.Hour)) {
err = multierror.Append(err, errors.New("ClientReceivedStartTimestamp cannot be more than 90 days old"))
err = errorset.Append(err, errors.New("ClientReceivedStartTimestamp cannot be more than 90 days old"))
}

for _, attr := range r.Attributes {
if validateErr := validateAttribute(attr); validateErr != nil {
err = multierror.Append(err, validateErr)
err = errorset.Append(err, validateErr)
}
}

Expand Down
12 changes: 6 additions & 6 deletions analytics/recovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (
"os"
"path/filepath"

"github.com/apigee/apigee-remote-service-golib/v2/errorset"
"github.com/apigee/apigee-remote-service-golib/v2/log"
"github.com/hashicorp/go-multierror"
)

// crashRecovery cleans up the temp and staging dirs post-crash. This function
Expand All @@ -39,13 +39,13 @@ func (m *manager) crashRecovery() error {
tempDir := m.getTempDir(tenant)
tempFiles, err := os.ReadDir(tempDir)
if err != nil {
errs = multierror.Append(errs, err)
errs = errorset.Append(errs, err)
continue
}

err = m.prepTenant(tenant)
if err != nil {
errs = multierror.Append(errs, err)
errs = errorset.Append(errs, err)
continue
}
stageDir := m.getStagingDir(tenant)
Expand All @@ -66,13 +66,13 @@ func (m *manager) crashRecovery() error {

dest, err := os.Create(stageFile)
if err != nil {
errs = multierror.Append(errs, fmt.Errorf("create recovery file %s: %s", tempDir, err))
errs = errorset.Append(errs, fmt.Errorf("create recovery file %s: %s", tempDir, err))
continue
}
if err := m.recoverFile(tempFile, dest); err != nil {
errs = multierror.Append(errs, fmt.Errorf("recoverFile %s: %s", tempDir, err))
errs = errorset.Append(errs, fmt.Errorf("recoverFile %s: %s", tempDir, err))
if err := os.Remove(stageFile); err != nil {
errs = multierror.Append(errs, fmt.Errorf("remove stage file %s: %s", tempDir, err))
errs = errorset.Append(errs, fmt.Errorf("remove stage file %s: %s", tempDir, err))
}
continue
}
Expand Down
4 changes: 2 additions & 2 deletions analytics/staging.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import (
"path/filepath"
"sync"

"github.com/apigee/apigee-remote-service-golib/v2/errorset"
"github.com/apigee/apigee-remote-service-golib/v2/log"
"github.com/hashicorp/go-multierror"
"github.com/prometheus/client_golang/prometheus"
)

Expand Down Expand Up @@ -54,7 +54,7 @@ func (m *manager) getFilesInStaging() ([]string, error) {

stagedFiles, err := os.ReadDir(tenantDirPath)
if err != nil {
errs = multierror.Append(errs, fmt.Errorf("ls %s: %s", tenantDirPath, err))
errs = errorset.Append(errs, fmt.Errorf("ls %s: %s", tenantDirPath, err))
continue
}

Expand Down
70 changes: 70 additions & 0 deletions errorset/errorset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package errorset

import (
"fmt"
"strings"
)

func Append(err error, errs ...error) error {
es, ok := err.(*Error)
if !ok && err != nil {
es = es.append(err)
}
es = es.append(errs...)
if es.Len() == 0 {
return nil
}
return es
}

func Errors(err error) []error {
if errset, ok := err.(*Error); ok {
return errset.Errors
}
return []error{err}
}

type Error struct {
Errors []error
}

func (es *Error) append(errs ...error) *Error {
if es == nil {
es = &Error{}
}
for _, e := range errs {
if errset, ok := e.(*Error); ok { // unwrap
es.Errors = es.append(errset.Errors...).Errors
} else if e != nil {
es.Errors = append(es.Errors, e)
}
}
return es
}

func (es *Error) Error() string {
b := &strings.Builder{}
fmt.Fprintf(b, "Error(s):")
for _, e := range es.Errors {
fmt.Fprintf(b, "\n\t* %s", e.Error())
}
return b.String()
}

func (es *Error) Len() int {
return len(es.Errors)
}
125 changes: 125 additions & 0 deletions errorset/errorset_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package errorset

import (
"errors"
"testing"
)

func TestNils(t *testing.T) {
err := Append(nil)
if err != nil {
t.Errorf("should be nil")
}

err = Append(nil, nil)
if err != nil {
t.Errorf("should be nil")
}
}

func TestNilAppend(t *testing.T) {
want := "Error(s):\n\t* my error"
err := Append(nil, nil, errors.New("my error"))
if err == nil {
t.Fatalf("should not be nil")
}
got := err.Error()
if want != got {
t.Errorf("want: %s, got: %s", want, got)
}
if 1 != err.(*Error).Len() {
t.Errorf("want: %d, got: %d", 1, err.(*Error).Len())
}
}

func TestError(t *testing.T) {
want := "Error(s):\n\t* my error"
err := Append(errors.New("my error"))
if err == nil {
t.Errorf("should not be nil")
}
got := err.Error()
if want != got {
t.Errorf("want: %s, got: %s", want, err.Error())
}
if 1 != err.(*Error).Len() {
t.Errorf("want: %d, got: %d", 1, err.(*Error).Len())
}
}

func TestErrors(t *testing.T) {
want := "Error(s):\n\t* my error\n\t* my error2"
err1 := errors.New("my error")
err2 := errors.New("my error2")
err := Append(err1, err2)
if err == nil {
t.Errorf("should not be nil")
}
got := err.Error()
if want != got {
t.Errorf("want: %s, got: %s", want, err.Error())
}
if 2 != err.(*Error).Len() {
t.Errorf("want: %d, got: %d", 2, err.(*Error).Len())
}

errs := Errors(err1)
if err1 != errs[0] {
t.Errorf("want: %v, got: %v", err1, errs[0])
}

errs = Errors(err)
if err1 != errs[0] {
t.Errorf("want: %v, got: %v", err1, errs[0])
}
if err2 != errs[1] {
t.Errorf("want: %v, got: %v", err2, errs[1])
}
}

func TestMultiError(t *testing.T) {
want := "Error(s):\n\t* my error\n\t* my error2"
err := Append(errors.New("my error"))
err = Append(err, errors.New("my error2"))
if err == nil {
t.Errorf("should not be nil")
}
got := err.Error()
if want != got {
t.Errorf("want: %s, got: %s", want, err.Error())
}
if 2 != err.(*Error).Len() {
t.Errorf("want: %d, got: %d", 2, err.(*Error).Len())
}
}

func TestUnwrap(t *testing.T) {
want := "Error(s):\n\t* my error3\n\t* my error\n\t* my error2"
wrapped := Append(errors.New("my error"))
wrapped = Append(wrapped, errors.New("my error2"))
err := Append(errors.New("my error3"), wrapped)
if err == nil {
t.Errorf("should not be nil")
}
got := err.Error()
if want != got {
t.Errorf("want: %s, got: %s", want, err.Error())
}
if 3 != err.(*Error).Len() {
t.Errorf("want: %d, got: %d", 3, err.(*Error).Len())
}
}
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ go 1.16

require (
github.com/google/uuid v1.2.0
github.com/hashicorp/go-multierror v1.1.1
github.com/lestrrat-go/backoff/v2 v2.0.8
github.com/lestrrat-go/jwx v1.1.5
github.com/pkg/errors v0.9.1
Expand Down

0 comments on commit 9e03f80

Please sign in to comment.