Skip to content

Commit 5ea9a7c

Browse files
authored
feat: add better handler for part size (#214)
* feat: add better handler for part size fix: use local file fix: try with another path fix: use bytes chore: go back go back readme goback goback goback * chore: better handling * fix: typo readme * chore: wrong comparaison * fix: typo
1 parent bcffe0b commit 5ea9a7c

File tree

4 files changed

+34
-3
lines changed

4 files changed

+34
-3
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,15 @@ You can populate below template according to your requirements and use it as you
260260

261261
# AWS_STORAGE_CLASS="GLACIER"
262262

263+
# Setting this variable will change the S3 default part size for the copy step.
264+
# This value is useful when you want to upload large files.
265+
# NB : While using Scaleway as S3 provider, be aware that the parts counter is set to 1.000.
266+
# While Minio uses a hard coded value to 10.000. As a workaround, try to set a higher value.
267+
# Defaults to "16" (MB) if unset (from minio), you can set this value according to your needs.
268+
# The unit is in MB and an integer.
269+
270+
# AWS_PART_SIZE=16
271+
263272
# You can also backup files to any WebDAV server:
264273

265274
# The URL of the remote WebDAV server

cmd/backup/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type Config struct {
2828
AwsSecretAccessKey string `split_words:"true"`
2929
AwsSecretAccessKeyFile string `split_words:"true"`
3030
AwsIamRoleEndpoint string `split_words:"true"`
31+
AwsPartSize int64 `split_words:"true"`
3132
BackupSources string `split_words:"true" default:"/backup"`
3233
BackupFilename string `split_words:"true" default:"backup-%Y-%m-%dT%H-%M-%S.tar.gz"`
3334
BackupFilenameExpand bool `split_words:"true"`

cmd/backup/script.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ func newScript() (*script, error) {
142142
BucketName: s.c.AwsS3BucketName,
143143
StorageClass: s.c.AwsStorageClass,
144144
CACert: s.c.AwsEndpointCACert.Cert,
145+
PartSize: s.c.AwsPartSize,
145146
}
146147
if s3Backend, err := s3.NewStorageBackend(s3Config, logFunc); err != nil {
147148
return nil, err

internal/storage/s3/s3.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"crypto/x509"
99
"errors"
1010
"fmt"
11+
"os"
1112
"path"
1213
"path/filepath"
1314
"time"
@@ -22,6 +23,7 @@ type s3Storage struct {
2223
client *minio.Client
2324
bucket string
2425
storageClass string
26+
partSize int64
2527
}
2628

2729
// Config contains values that define the configuration of a S3 backend.
@@ -35,6 +37,7 @@ type Config struct {
3537
RemotePath string
3638
BucketName string
3739
StorageClass string
40+
PartSize int64
3841
CACert *x509.Certificate
3942
}
4043

@@ -89,6 +92,7 @@ func NewStorageBackend(opts Config, logFunc storage.Log) (storage.Backend, error
8992
client: mc,
9093
bucket: opts.BucketName,
9194
storageClass: opts.StorageClass,
95+
partSize: opts.PartSize,
9296
}, nil
9397
}
9498

@@ -100,16 +104,32 @@ func (v *s3Storage) Name() string {
100104
// Copy copies the given file to the S3/Minio storage backend.
101105
func (b *s3Storage) Copy(file string) error {
102106
_, name := path.Split(file)
103-
104-
if _, err := b.client.FPutObject(context.Background(), b.bucket, filepath.Join(b.DestinationPath, name), file, minio.PutObjectOptions{
107+
putObjectOptions := minio.PutObjectOptions{
105108
ContentType: "application/tar+gzip",
106109
StorageClass: b.storageClass,
107-
}); err != nil {
110+
}
111+
112+
if b.partSize > 0 {
113+
srcFileInfo, err := os.Stat(file)
114+
if err != nil {
115+
return fmt.Errorf("(*s3Storage).Copy: error reading the local file: %w", err)
116+
}
117+
118+
_, partSize, _, err := minio.OptimalPartInfo(srcFileInfo.Size(), uint64(b.partSize*1024*1024))
119+
if err != nil {
120+
return fmt.Errorf("(*s3Storage).Copy: error computing the optimal s3 part size: %w", err)
121+
}
122+
123+
putObjectOptions.PartSize = uint64(partSize)
124+
}
125+
126+
if _, err := b.client.FPutObject(context.Background(), b.bucket, filepath.Join(b.DestinationPath, name), file, putObjectOptions); err != nil {
108127
if errResp := minio.ToErrorResponse(err); errResp.Message != "" {
109128
return fmt.Errorf("(*s3Storage).Copy: error uploading backup to remote storage: [Message]: '%s', [Code]: %s, [StatusCode]: %d", errResp.Message, errResp.Code, errResp.StatusCode)
110129
}
111130
return fmt.Errorf("(*s3Storage).Copy: error uploading backup to remote storage: %w", err)
112131
}
132+
113133
b.Log(storage.LogLevelInfo, b.Name(), "Uploaded a copy of backup `%s` to bucket `%s`.", file, b.bucket)
114134

115135
return nil

0 commit comments

Comments
 (0)