satellite/buckets: handle bucket exists better

In some rare cases when two entities are trying to create the same
bucket at the same time it's possible that we will return internal
error instead of `bucket already exists`. It's because we are not
handling correctly DB error about constraint error. This change checks
if while inserting bucket into DB we got constraint error and propagate
correct error to metainfo API.

Change-Id: Ie6fd2c943b864b4ea7d71e4a162e74dc3510e386
This commit is contained in:
Michal Niewrzal 2023-07-18 12:56:25 +02:00 committed by Storj Robot
parent 84ea80c1fd
commit 95a5cfe647
3 changed files with 10 additions and 0 deletions

View File

@ -25,6 +25,9 @@ var (
// ErrBucketNotFound is an error class for non-existing bucket.
ErrBucketNotFound = errs.Class("bucket not found")
// ErrBucketAlreadyExists is used to indicate that bucket already exists.
ErrBucketAlreadyExists = errs.Class("bucket already exists")
)
// Bucket contains information about a specific bucket.

View File

@ -114,6 +114,10 @@ func (endpoint *Endpoint) CreateBucket(ctx context.Context, req *pb.BucketCreate
bucket, err := endpoint.buckets.CreateBucket(ctx, bucketReq)
if err != nil {
if buckets.ErrBucketAlreadyExists.Has(err) {
return nil, rpcstatus.Error(rpcstatus.AlreadyExists, "bucket already exists")
}
endpoint.log.Error("error while creating bucket", zap.String("bucketName", bucketReq.Name), zap.Error(err))
return nil, rpcstatus.Error(rpcstatus.Internal, "unable to create bucket")
}

View File

@ -51,6 +51,9 @@ func (db *bucketsDB) CreateBucket(ctx context.Context, bucket buckets.Bucket) (_
optionalFields,
)
if err != nil {
if dbx.IsConstraintError(err) {
return buckets.Bucket{}, buckets.ErrBucketAlreadyExists.New("")
}
return buckets.Bucket{}, buckets.ErrBucket.Wrap(err)
}