satellite/metabase: Classify pending object error

Create an error class for the "pending object error" for distinguishing
it from other errors for allowing to return it as a "Not Found" DRPC
status code instead an "Internal" status code.

"Internal" errors are logged in the satellite error so this was
polluting the server logs aside of returning an inappropriate status
code.

Change-Id: I10a81adfc887c030c08a228158adc8815834b23c
This commit is contained in:
Ivan Fraixedes 2022-05-09 17:11:36 +02:00 committed by Ivan Fraixedes
parent e4a4248337
commit 648d6bf0a7
4 changed files with 25 additions and 23 deletions

View File

@ -247,7 +247,7 @@ func (db *DB) BeginSegment(ctx context.Context, opts BeginSegment) (err error) {
opts.ProjectID, []byte(opts.BucketName), opts.ObjectKey, opts.Version, opts.StreamID).Scan(&value)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return Error.New("pending object missing")
return ErrPendingObjectMissing.New("")
}
return Error.New("unable to query object status: %w", err)
}
@ -363,7 +363,7 @@ func (db *DB) CommitSegment(ctx context.Context, opts CommitSegment) (err error)
)
if err != nil {
if code := pgerrcode.FromError(err); code == pgxerrcode.NotNullViolation {
return Error.New("pending object missing")
return ErrPendingObjectMissing.New("")
}
return Error.New("unable to insert segment: %w", err)
}
@ -449,7 +449,7 @@ func (db *DB) CommitInlineSegment(ctx context.Context, opts CommitInlineSegment)
)
if err != nil {
if code := pgerrcode.FromError(err); code == pgxerrcode.NotNullViolation {
return Error.New("pending object missing")
return ErrPendingObjectMissing.New("")
}
return Error.New("unable to insert segment: %w", err)
}
@ -542,12 +542,14 @@ func (db *DB) CommitObject(ctx context.Context, opts CommitObject) (object Objec
totalEncryptedSize += int64(seg.EncryptedSize)
}
args := []interface{}{opts.ProjectID, []byte(opts.BucketName), opts.ObjectKey, opts.Version, opts.StreamID,
args := []interface{}{
opts.ProjectID, []byte(opts.BucketName), opts.ObjectKey, opts.Version, opts.StreamID,
len(segments),
totalPlainSize,
totalEncryptedSize,
fixedSegmentSize,
encryptionParameters{&opts.Encryption}}
encryptionParameters{&opts.Encryption},
}
metadataColumns := ""
if opts.OverrideEncryptedMetadata {

View File

@ -881,8 +881,7 @@ func TestBeginSegment(t *testing.T) {
StorageNode: testrand.NodeID(),
}},
},
ErrClass: &metabase.Error,
ErrText: "pending object missing",
ErrClass: &metabase.ErrPendingObjectMissing,
}.Check(ctx, t, db)
metabasetest.Verify{}.Check(ctx, t, db)
})
@ -914,8 +913,7 @@ func TestBeginSegment(t *testing.T) {
StorageNode: testrand.NodeID(),
}},
},
ErrClass: &metabase.Error,
ErrText: "pending object missing",
ErrClass: &metabase.ErrPendingObjectMissing,
}.Check(ctx, t, db)
metabasetest.Verify{
@ -1476,8 +1474,7 @@ func TestCommitSegment(t *testing.T) {
PlainOffset: 0,
Redundancy: metabasetest.DefaultRedundancy,
},
ErrClass: &metabase.Error,
ErrText: "pending object missing",
ErrClass: &metabase.ErrPendingObjectMissing,
}.Check(ctx, t, db)
metabasetest.Verify{}.Check(ctx, t, db)
@ -1520,8 +1517,7 @@ func TestCommitSegment(t *testing.T) {
PlainOffset: 0,
Redundancy: metabasetest.DefaultRedundancy,
},
ErrClass: &metabase.Error,
ErrText: "pending object missing",
ErrClass: &metabase.ErrPendingObjectMissing,
}.Check(ctx, t, db)
metabasetest.Verify{
@ -1673,7 +1669,8 @@ func TestCommitSegment(t *testing.T) {
Pieces: pieces,
},
}}.Check(ctx, t, db)
},
}.Check(ctx, t, db)
})
})
}
@ -1937,8 +1934,7 @@ func TestCommitInlineSegment(t *testing.T) {
PlainSize: 512,
PlainOffset: 0,
},
ErrClass: &metabase.Error,
ErrText: "pending object missing",
ErrClass: &metabase.ErrPendingObjectMissing,
}.Check(ctx, t, db)
metabasetest.Verify{}.Check(ctx, t, db)
@ -1964,8 +1960,7 @@ func TestCommitInlineSegment(t *testing.T) {
PlainSize: 512,
PlainOffset: 0,
},
ErrClass: &metabase.Error,
ErrText: "pending object missing",
ErrClass: &metabase.ErrPendingObjectMissing,
}.Check(ctx, t, db)
metabasetest.Verify{

View File

@ -16,11 +16,14 @@ import (
"storj.io/common/uuid"
)
// Error is the default error for metabase.
var Error = errs.Class("metabase")
// ErrObjectAlreadyExists is used to indicate that object already exists.
var ErrObjectAlreadyExists = errs.Class("object already exists")
var (
// Error is the default error for metabase.
Error = errs.Class("metabase")
// ErrObjectAlreadyExists is used to indicate that object already exists.
ErrObjectAlreadyExists = errs.Class("object already exists")
// ErrPendingObjectMissing is used to indicate a pending object is no longer accessible.
ErrPendingObjectMissing = errs.Class("pending object missing")
)
// Common constants for segment keys.
const (

View File

@ -274,6 +274,8 @@ func (endpoint *Endpoint) convertMetabaseErr(err error) error {
return rpcstatus.Error(rpcstatus.InvalidArgument, err.Error())
case metabase.ErrObjectAlreadyExists.Has(err):
return rpcstatus.Error(rpcstatus.AlreadyExists, err.Error())
case metabase.ErrPendingObjectMissing.Has(err):
return rpcstatus.Error(rpcstatus.NotFound, err.Error())
default:
endpoint.log.Error("internal", zap.Error(err))
return rpcstatus.Error(rpcstatus.Internal, err.Error())