Skip to content

Commit d69df72

Browse files
authored
Merge pull request thanos-io#103 from thanos-io/do-not-return-error-when-expected
Metric bucket should not return error when error is expected
2 parents 8d266b9 + 238812f commit d69df72

6 files changed

+118
-20
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,6 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re
6868
- [#71](https://github.com/thanos-io/objstore/pull/71) Replace method `IsCustomerManagedKeyError` for a more generic `IsAccessDeniedErr` on the bucket interface.
6969
- [#89](https://github.com/thanos-io/objstore/pull/89) GCS: Upgrade cloud.google.com/go/storage version to `v1.35.1`.
7070
- [#123](https://github.com/thanos-io/objstore/pull/123) *: Upgrade minio-go version to `v7.0.71`.
71+
- [#103](https://github.com/thanos-io/objstore/pull/103) *: Don't return error in metric bucket if the error is expected.
72+
7173
### Removed

objstore.go

+24-8
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,9 @@ func (b *metricBucket) Iter(ctx context.Context, dir string, f func(string) erro
633633

634634
err := b.bkt.Iter(ctx, dir, f, options...)
635635
if err != nil {
636-
if !b.metrics.isOpFailureExpected(err) && ctx.Err() != context.Canceled {
636+
if b.metrics.isOpFailureExpected(err) {
637+
err = nil
638+
} else if ctx.Err() != context.Canceled {
637639
b.metrics.opsFailures.WithLabelValues(op).Inc()
638640
}
639641
}
@@ -649,7 +651,9 @@ func (b *metricBucket) IterWithAttributes(ctx context.Context, dir string, f fun
649651

650652
err := b.bkt.IterWithAttributes(ctx, dir, f, options...)
651653
if err != nil {
652-
if !b.metrics.isOpFailureExpected(err) && ctx.Err() != context.Canceled {
654+
if b.metrics.isOpFailureExpected(err) {
655+
err = nil
656+
} else if ctx.Err() != context.Canceled {
653657
b.metrics.opsFailures.WithLabelValues(op).Inc()
654658
}
655659
}
@@ -668,7 +672,9 @@ func (b *metricBucket) Attributes(ctx context.Context, name string) (ObjectAttri
668672
start := time.Now()
669673
attrs, err := b.bkt.Attributes(ctx, name)
670674
if err != nil {
671-
if !b.metrics.isOpFailureExpected(err) && ctx.Err() != context.Canceled {
675+
if b.metrics.isOpFailureExpected(err) {
676+
err = nil
677+
} else if ctx.Err() != context.Canceled {
672678
b.metrics.opsFailures.WithLabelValues(op).Inc()
673679
}
674680
return attrs, err
@@ -685,7 +691,9 @@ func (b *metricBucket) Get(ctx context.Context, name string) (io.ReadCloser, err
685691

686692
rc, err := b.bkt.Get(ctx, name)
687693
if err != nil {
688-
if !b.metrics.isOpFailureExpected(err) && ctx.Err() != context.Canceled {
694+
if b.metrics.isOpFailureExpected(err) {
695+
err = nil
696+
} else if ctx.Err() != context.Canceled {
689697
b.metrics.opsFailures.WithLabelValues(op).Inc()
690698
}
691699
b.metrics.opsDuration.WithLabelValues(op).Observe(time.Since(start).Seconds())
@@ -712,7 +720,9 @@ func (b *metricBucket) GetRange(ctx context.Context, name string, off, length in
712720

713721
rc, err := b.bkt.GetRange(ctx, name, off, length)
714722
if err != nil {
715-
if !b.metrics.isOpFailureExpected(err) && ctx.Err() != context.Canceled {
723+
if b.metrics.isOpFailureExpected(err) {
724+
err = nil
725+
} else if ctx.Err() != context.Canceled {
716726
b.metrics.opsFailures.WithLabelValues(op).Inc()
717727
}
718728
b.metrics.opsDuration.WithLabelValues(op).Observe(time.Since(start).Seconds())
@@ -738,7 +748,9 @@ func (b *metricBucket) Exists(ctx context.Context, name string) (bool, error) {
738748
start := time.Now()
739749
ok, err := b.bkt.Exists(ctx, name)
740750
if err != nil {
741-
if !b.metrics.isOpFailureExpected(err) && ctx.Err() != context.Canceled {
751+
if b.metrics.isOpFailureExpected(err) {
752+
err = nil
753+
} else if ctx.Err() != context.Canceled {
742754
b.metrics.opsFailures.WithLabelValues(op).Inc()
743755
}
744756
return false, err
@@ -767,7 +779,9 @@ func (b *metricBucket) Upload(ctx context.Context, name string, r io.Reader) err
767779
defer trc.Close()
768780
err := b.bkt.Upload(ctx, name, trc)
769781
if err != nil {
770-
if !b.metrics.isOpFailureExpected(err) && ctx.Err() != context.Canceled {
782+
if b.metrics.isOpFailureExpected(err) {
783+
err = nil
784+
} else if ctx.Err() != context.Canceled {
771785
b.metrics.opsFailures.WithLabelValues(op).Inc()
772786
}
773787
return err
@@ -783,7 +797,9 @@ func (b *metricBucket) Delete(ctx context.Context, name string) error {
783797

784798
start := time.Now()
785799
if err := b.bkt.Delete(ctx, name); err != nil {
786-
if !b.metrics.isOpFailureExpected(err) && ctx.Err() != context.Canceled {
800+
if b.metrics.isOpFailureExpected(err) {
801+
err = nil
802+
} else if ctx.Err() != context.Canceled {
787803
b.metrics.opsFailures.WithLabelValues(op).Inc()
788804
}
789805
return err

objstore_test.go

+77-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestMetricBucket_Close(t *testing.T) {
2828
testutil.Equals(t, 7, promtest.CollectAndCount(bkt.metrics.opsFailures))
2929
testutil.Equals(t, 7, promtest.CollectAndCount(bkt.metrics.opsDuration))
3030

31-
AcceptanceTest(t, bkt.WithExpectedErrs(bkt.IsObjNotFoundErr))
31+
AcceptanceTest(t, bkt.WithExpectedErrs(bkt.IsObjNotFoundErr), true)
3232
testutil.Equals(t, float64(9), promtest.ToFloat64(bkt.metrics.ops.WithLabelValues(OpIter)))
3333
testutil.Equals(t, float64(2), promtest.ToFloat64(bkt.metrics.ops.WithLabelValues(OpAttributes)))
3434
testutil.Equals(t, float64(3), promtest.ToFloat64(bkt.metrics.ops.WithLabelValues(OpGet)))
@@ -51,7 +51,7 @@ func TestMetricBucket_Close(t *testing.T) {
5151

5252
// Clear bucket, but don't clear metrics to ensure we use same.
5353
bkt.bkt = NewInMemBucket()
54-
AcceptanceTest(t, bkt)
54+
AcceptanceTestWithoutNotFoundErr(t, bkt)
5555
testutil.Equals(t, float64(18), promtest.ToFloat64(bkt.metrics.ops.WithLabelValues(OpIter)))
5656
testutil.Equals(t, float64(4), promtest.ToFloat64(bkt.metrics.ops.WithLabelValues(OpAttributes)))
5757
testutil.Equals(t, float64(6), promtest.ToFloat64(bkt.metrics.ops.WithLabelValues(OpGet)))
@@ -537,6 +537,54 @@ func TestDownloadDir_CleanUp(t *testing.T) {
537537
testutil.Assert(t, os.IsNotExist(err))
538538
}
539539

540+
func TestBucketExpectedErrNoReturnError(t *testing.T) {
541+
expectedErr := errors.New("test error")
542+
543+
bucket := WrapWithMetrics(&mockBucket{
544+
get: func(_ context.Context, _ string) (io.ReadCloser, error) {
545+
return nil, expectedErr
546+
},
547+
getRange: func(ctx context.Context, name string, off, length int64) (io.ReadCloser, error) {
548+
return nil, expectedErr
549+
},
550+
upload: func(ctx context.Context, name string, r io.Reader) error {
551+
return expectedErr
552+
},
553+
iter: func(ctx context.Context, dir string, f func(string) error, options ...IterOption) error {
554+
return expectedErr
555+
},
556+
attributes: func(ctx context.Context, name string) (ObjectAttributes, error) {
557+
return ObjectAttributes{}, expectedErr
558+
},
559+
exists: func(ctx context.Context, name string) (bool, error) {
560+
return false, expectedErr
561+
},
562+
}, nil, "").WithExpectedErrs(func(err error) bool {
563+
return errors.Is(err, expectedErr)
564+
})
565+
566+
// Expect no error to be returned since the error is expected.
567+
_, err := bucket.Get(context.Background(), "")
568+
testutil.Ok(t, err)
569+
570+
_, err = bucket.GetRange(context.Background(), "", 1, 2)
571+
testutil.Ok(t, err)
572+
573+
err = bucket.Upload(context.Background(), "", nil)
574+
testutil.Ok(t, err)
575+
576+
err = bucket.Iter(context.Background(), "", func(s string) error {
577+
return nil
578+
})
579+
testutil.Ok(t, err)
580+
581+
_, err = bucket.Exists(context.Background(), "")
582+
testutil.Ok(t, err)
583+
584+
_, err = bucket.Attributes(context.Background(), "")
585+
testutil.Ok(t, err)
586+
}
587+
540588
// unreliableBucket implements Bucket and returns an error on every n-th Get.
541589
type unreliableBucket struct {
542590
Bucket
@@ -570,9 +618,12 @@ func (r *mockReader) Close() error {
570618
type mockBucket struct {
571619
Bucket
572620

573-
upload func(ctx context.Context, name string, r io.Reader) error
574-
get func(ctx context.Context, name string) (io.ReadCloser, error)
575-
getRange func(ctx context.Context, name string, off, length int64) (io.ReadCloser, error)
621+
upload func(ctx context.Context, name string, r io.Reader) error
622+
get func(ctx context.Context, name string) (io.ReadCloser, error)
623+
getRange func(ctx context.Context, name string, off, length int64) (io.ReadCloser, error)
624+
iter func(ctx context.Context, dir string, f func(string) error, options ...IterOption) error
625+
attributes func(ctx context.Context, name string) (ObjectAttributes, error)
626+
exists func(ctx context.Context, name string) (bool, error)
576627
}
577628

578629
func (b *mockBucket) Upload(ctx context.Context, name string, r io.Reader) error {
@@ -596,6 +647,27 @@ func (b *mockBucket) GetRange(ctx context.Context, name string, off, length int6
596647
return nil, errors.New("GetRange has not been mocked")
597648
}
598649

650+
func (b *mockBucket) Iter(ctx context.Context, dir string, f func(string) error, options ...IterOption) error {
651+
if b.iter != nil {
652+
return b.iter(ctx, dir, f, options...)
653+
}
654+
return errors.New("Iter has not been mocked")
655+
}
656+
657+
func (b *mockBucket) Exists(ctx context.Context, name string) (bool, error) {
658+
if b.exists != nil {
659+
return b.exists(ctx, name)
660+
}
661+
return false, errors.New("Exists has not been mocked")
662+
}
663+
664+
func (b *mockBucket) Attributes(ctx context.Context, name string) (ObjectAttributes, error) {
665+
if b.attributes != nil {
666+
return b.attributes(ctx, name)
667+
}
668+
return ObjectAttributes{}, errors.New("Attributes has not been mocked")
669+
}
670+
599671
func Test_TryToGetSizeLimitedReader(t *testing.T) {
600672
b := &bytes.Buffer{}
601673
r := io.LimitReader(b, 1024)

objtesting/acceptance_e2e_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ import (
1414
// NOTE: This test assumes strong consistency, but in the same way it does not guarantee that if it passes, the
1515
// used object store is strongly consistent.
1616
func TestObjStore_AcceptanceTest_e2e(t *testing.T) {
17-
ForeachStore(t, objstore.AcceptanceTest)
17+
ForeachStore(t, objstore.AcceptanceTestWithoutNotFoundErr)
1818
}

prefixed_bucket_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func TestPrefixedBucket_Acceptance(t *testing.T) {
2323
"someprefix"}
2424

2525
for _, prefix := range prefixes {
26-
AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix))
26+
AcceptanceTestWithoutNotFoundErr(t, NewPrefixedBucket(NewInMemBucket(), prefix))
2727
UsesPrefixTest(t, NewInMemBucket(), prefix)
2828
}
2929
}

testing.go

+13-5
Original file line numberDiff line numberDiff line change
@@ -80,24 +80,32 @@ func (b noopInstrumentedBucket) ReaderWithExpectedErrs(IsOpFailureExpectedFunc)
8080
return b
8181
}
8282

83-
func AcceptanceTest(t *testing.T, bkt Bucket) {
83+
func AcceptanceTestWithoutNotFoundErr(t *testing.T, bkt Bucket) {
84+
AcceptanceTest(t, bkt, false)
85+
}
86+
87+
func AcceptanceTest(t *testing.T, bkt Bucket, expectedNotFoundErr bool) {
8488
ctx := context.Background()
8589

8690
_, err := bkt.Get(ctx, "")
8791
testutil.NotOk(t, err)
8892
testutil.Assert(t, !bkt.IsObjNotFoundErr(err), "expected user error got not found %s", err)
8993

9094
_, err = bkt.Get(ctx, "id1/obj_1.some")
91-
testutil.NotOk(t, err)
92-
testutil.Assert(t, bkt.IsObjNotFoundErr(err), "expected not found error got %s", err)
95+
if !expectedNotFoundErr {
96+
testutil.NotOk(t, err)
97+
testutil.Assert(t, bkt.IsObjNotFoundErr(err), "expected not found error got %s", err)
98+
}
9399

94100
ok, err := bkt.Exists(ctx, "id1/obj_1.some")
95101
testutil.Ok(t, err)
96102
testutil.Assert(t, !ok, "expected not exits")
97103

98104
_, err = bkt.Attributes(ctx, "id1/obj_1.some")
99-
testutil.NotOk(t, err)
100-
testutil.Assert(t, bkt.IsObjNotFoundErr(err), "expected not found error but got %s", err)
105+
if !expectedNotFoundErr {
106+
testutil.NotOk(t, err)
107+
testutil.Assert(t, bkt.IsObjNotFoundErr(err), "expected not found error got %s", err)
108+
}
101109

102110
// Upload first object.
103111
testutil.Ok(t, bkt.Upload(ctx, "id1/obj_1.some", strings.NewReader("@test-data@")))

0 commit comments

Comments
 (0)