Skip to content

Commit

Permalink
Delete S3 Object when deleting S3 Bucket
Browse files Browse the repository at this point in the history
  • Loading branch information
nao1215 committed Jan 14, 2024
1 parent 097ec15 commit 8eb56bf
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ localstack
/spare
/cfn
.envrc
/t-rec*
Binary file removed t-rec.gif
Binary file not shown.
Binary file removed t-rec.mp4
Binary file not shown.
Binary file removed t-rec_1.gif
Binary file not shown.
Binary file removed t-rec_1.mp4
Binary file not shown.
Binary file removed t-rec_2.gif
Binary file not shown.
Binary file removed t-rec_2.mp4
Binary file not shown.
61 changes: 58 additions & 3 deletions ui/s3hub/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package s3hub
import (
"context"
"crypto/rand"
"fmt"
"math/big"
"time"

Expand All @@ -11,6 +12,8 @@ import (
"github.com/nao1215/rainbow/app/domain/model"
"github.com/nao1215/rainbow/app/usecase"
"github.com/nao1215/rainbow/ui"
"golang.org/x/sync/errgroup"
"golang.org/x/sync/semaphore"
)

// fetchS3BucketMsg is the message that is sent when the user wants to fetch the list of the S3 buckets.
Expand All @@ -36,16 +39,54 @@ type deleteS3BucketMsg struct {
}

// deleteS3BucketCmd deletes the S3 bucket.
// TODO: refactor
func deleteS3BucketCmd(ctx context.Context, app *di.S3App, bucket model.Bucket) tea.Cmd {
d, err := rand.Int(rand.Reader, big.NewInt(500))
if err != nil {
// エラーのハンドリング
return tea.Quit
return func() tea.Msg {
return ui.ErrMsg(fmt.Errorf("failed to start deleting s3 bucket: %w", err))
}
}
delay := time.Millisecond * time.Duration(d.Int64())

return tea.Tick(delay, func(t time.Time) tea.Msg {
_, err := app.S3BucketDeleter.DeleteS3Bucket(ctx, &usecase.S3BucketDeleterInput{
output, err := app.S3ObjectsLister.ListS3Objects(ctx, &usecase.S3ObjectsListerInput{
Bucket: bucket,
})
if err != nil {
return err
}

if len(output.Objects) != 0 {
eg, ctx := errgroup.WithContext(ctx)
sem := semaphore.NewWeighted(model.MaxS3DeleteObjectsParallelsCount)
chunks := divideIntoChunks(output.Objects, model.S3DeleteObjectChunksSize)

for _, chunk := range chunks {
chunk := chunk // Create a new variable to avoid concurrency issues
// Acquire semaphore to control the number of concurrent goroutines
if err := sem.Acquire(ctx, 1); err != nil {
return err
}

eg.Go(func() error {
defer sem.Release(1)
if _, err := app.S3ObjectsDeleter.DeleteS3Objects(ctx, &usecase.S3ObjectsDeleterInput{
Bucket: bucket,
S3ObjectSets: chunk,
}); err != nil {
return err
}
return nil
})
}

if err := eg.Wait(); err != nil {
return err
}
}

_, err = app.S3BucketDeleter.DeleteS3Bucket(ctx, &usecase.S3BucketDeleterInput{
Bucket: bucket,
})
if err != nil {
Expand All @@ -56,3 +97,17 @@ func deleteS3BucketCmd(ctx context.Context, app *di.S3App, bucket model.Bucket)
}
})
}

// divideIntoChunks divides a slice into chunks of the specified size.
func divideIntoChunks(slice []model.S3ObjectIdentifier, chunkSize int) [][]model.S3ObjectIdentifier {
var chunks [][]model.S3ObjectIdentifier

for i := 0; i < len(slice); i += chunkSize {
end := i + chunkSize
if end > len(slice) {
end = len(slice)
}
chunks = append(chunks, slice[i:end])
}
return chunks
}

0 comments on commit 8eb56bf

Please sign in to comment.