diff --git a/s3/replica_client.go b/s3/replica_client.go index 6e6696b..6940789 100644 --- a/s3/replica_client.go +++ b/s3/replica_client.go @@ -207,10 +207,14 @@ func (c *ReplicaClient) DeleteGeneration(ctx context.Context, generation string) n = len(objIDs) } - if _, err := c.s3.DeleteObjectsWithContext(ctx, &s3.DeleteObjectsInput{ + out, err := c.s3.DeleteObjectsWithContext(ctx, &s3.DeleteObjectsInput{ Bucket: aws.String(c.Bucket), Delete: &s3.Delete{Objects: objIDs[:n], Quiet: aws.Bool(true)}, - }); err != nil { + }) + if err != nil { + return err + } + if err := deleteOutputError(out); err != nil { return err } internal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, "DELETE").Inc() @@ -297,10 +301,14 @@ func (c *ReplicaClient) DeleteSnapshot(ctx context.Context, generation string, i key := path.Join(c.Path, "generations", generation, "snapshots", litestream.FormatIndex(index)+".snapshot.lz4") - if _, err := c.s3.DeleteObjectsWithContext(ctx, &s3.DeleteObjectsInput{ + out, err := c.s3.DeleteObjectsWithContext(ctx, &s3.DeleteObjectsInput{ Bucket: aws.String(c.Bucket), Delete: &s3.Delete{Objects: []*s3.ObjectIdentifier{{Key: &key}}, Quiet: aws.Bool(true)}, - }); err != nil { + }) + if err != nil { + return err + } + if err := deleteOutputError(out); err != nil { return err } @@ -397,13 +405,16 @@ func (c *ReplicaClient) DeleteWALSegments(ctx context.Context, a []litestream.Po } // Delete S3 objects in bulk. - if _, err := c.s3.DeleteObjectsWithContext(ctx, &s3.DeleteObjectsInput{ + out, err := c.s3.DeleteObjectsWithContext(ctx, &s3.DeleteObjectsInput{ Bucket: aws.String(c.Bucket), Delete: &s3.Delete{Objects: objIDs[:n], Quiet: aws.Bool(true)}, - }); err != nil { + }) + if err != nil { + return err + } + if err := deleteOutputError(out); err != nil { return err } - internal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, "DELETE").Inc() a = a[n:] @@ -446,10 +457,14 @@ func (c *ReplicaClient) DeleteAll(ctx context.Context) error { n = len(objIDs) } - if _, err := c.s3.DeleteObjectsWithContext(ctx, &s3.DeleteObjectsInput{ + out, err := c.s3.DeleteObjectsWithContext(ctx, &s3.DeleteObjectsInput{ Bucket: aws.String(c.Bucket), Delete: &s3.Delete{Objects: objIDs[:n], Quiet: aws.Bool(true)}, - }); err != nil { + }) + if err != nil { + return err + } + if err := deleteOutputError(out); err != nil { return err } internal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, "DELETE").Inc() @@ -749,3 +764,15 @@ func isNotExists(err error) bool { return false } } + +func deleteOutputError(out *s3.DeleteObjectsOutput) error { + switch len(out.Errors) { + case 0: + return nil + case 1: + return fmt.Errorf("deleting object %s: %s - %s", *out.Errors[0].Key, *out.Errors[0].Code, *out.Errors[0].Message) + default: + return fmt.Errorf("%d errors occured deleting objects, %s: %s - (%s (and %d others)", + len(out.Errors), *out.Errors[0].Key, *out.Errors[0].Code, *out.Errors[0].Message, len(out.Errors)-1) + } +}