100 lines
2.3 KiB
Go
100 lines
2.3 KiB
Go
package objectstore
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"time"
|
|
|
|
"gitlab.com/gitlab-org/labkit/log"
|
|
"gocloud.dev/blob"
|
|
"gocloud.dev/gcerrors"
|
|
)
|
|
|
|
type GoCloudObject struct {
|
|
bucket *blob.Bucket
|
|
mux *blob.URLMux
|
|
bucketURL string
|
|
objectName string
|
|
*uploader
|
|
}
|
|
|
|
type GoCloudObjectParams struct {
|
|
Ctx context.Context
|
|
Mux *blob.URLMux
|
|
BucketURL string
|
|
ObjectName string
|
|
}
|
|
|
|
func NewGoCloudObject(p *GoCloudObjectParams) (*GoCloudObject, error) {
|
|
bucket, err := p.Mux.OpenBucket(p.Ctx, p.BucketURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
o := &GoCloudObject{
|
|
bucket: bucket,
|
|
mux: p.Mux,
|
|
bucketURL: p.BucketURL,
|
|
objectName: p.ObjectName,
|
|
}
|
|
|
|
o.uploader = newUploader(o)
|
|
return o, nil
|
|
}
|
|
|
|
func (o *GoCloudObject) Upload(ctx context.Context, r io.Reader) error {
|
|
defer o.bucket.Close()
|
|
|
|
writer, err := o.bucket.NewWriter(ctx, o.objectName, nil)
|
|
if err != nil {
|
|
log.ContextLogger(ctx).WithError(err).Error("error creating GoCloud bucket")
|
|
return err
|
|
}
|
|
|
|
if _, err = io.Copy(writer, r); err != nil {
|
|
log.ContextLogger(ctx).WithError(err).Error("error writing to GoCloud bucket")
|
|
writer.Close()
|
|
return err
|
|
}
|
|
|
|
if err := writer.Close(); err != nil {
|
|
log.ContextLogger(ctx).WithError(err).Error("error closing GoCloud bucket")
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (o *GoCloudObject) ETag() string {
|
|
return ""
|
|
}
|
|
|
|
func (o *GoCloudObject) Abort() {
|
|
o.Delete()
|
|
}
|
|
|
|
// Delete will always attempt to delete the temporary file.
|
|
// According to https://github.com/google/go-cloud/blob/7818961b5c9a112f7e092d3a2d8479cbca80d187/blob/azureblob/azureblob.go#L881-L883,
|
|
// if the writer is closed before any Write is called, Close will create an empty file.
|
|
func (o *GoCloudObject) Delete() {
|
|
if o.bucketURL == "" || o.objectName == "" {
|
|
return
|
|
}
|
|
|
|
// Note we can't use the request context because in a successful
|
|
// case, the original request has already completed.
|
|
deleteCtx, cancel := context.WithTimeout(context.Background(), 60*time.Second) // lint:allow context.Background
|
|
defer cancel()
|
|
|
|
bucket, err := o.mux.OpenBucket(deleteCtx, o.bucketURL)
|
|
if err != nil {
|
|
log.WithError(err).Error("error opening bucket for delete")
|
|
return
|
|
}
|
|
|
|
if err := bucket.Delete(deleteCtx, o.objectName); err != nil {
|
|
if gcerrors.Code(err) != gcerrors.NotFound {
|
|
log.WithError(err).Error("error deleting object")
|
|
}
|
|
}
|
|
}
|