mirror of
https://github.com/gofiber/storage.git
synced 2025-10-26 18:00:26 +08:00
minio: add support for context management
This commit is contained in:
@@ -18,7 +18,6 @@ import (
|
|||||||
type Storage struct {
|
type Storage struct {
|
||||||
minio *minio.Client
|
minio *minio.Client
|
||||||
cfg Config
|
cfg Config
|
||||||
ctx context.Context
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +40,7 @@ func New(config ...Config) *Storage {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
storage := &Storage{minio: minioClient, cfg: cfg, ctx: context.Background()}
|
storage := &Storage{minio: minioClient, cfg: cfg}
|
||||||
|
|
||||||
// Reset all entries if set to true
|
// Reset all entries if set to true
|
||||||
if cfg.Reset {
|
if cfg.Reset {
|
||||||
@@ -63,15 +62,14 @@ func New(config ...Config) *Storage {
|
|||||||
return storage
|
return storage
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get value by key
|
// GetWithContext value by key with context
|
||||||
func (s *Storage) Get(key string) ([]byte, error) {
|
func (s *Storage) GetWithContext(ctx context.Context, key string) ([]byte, error) {
|
||||||
|
|
||||||
if len(key) <= 0 {
|
if len(key) <= 0 {
|
||||||
return nil, errors.New("the key value is required")
|
return nil, errors.New("the key value is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
// get object
|
// get object
|
||||||
object, err := s.minio.GetObject(s.ctx, s.cfg.Bucket, key, s.cfg.GetObjectOptions)
|
object, err := s.minio.GetObject(ctx, s.cfg.Bucket, key, s.cfg.GetObjectOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -91,9 +89,13 @@ func (s *Storage) Get(key string) ([]byte, error) {
|
|||||||
return bb.Bytes(), nil
|
return bb.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set key with value
|
// Get value by key
|
||||||
func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
|
func (s *Storage) Get(key string) ([]byte, error) {
|
||||||
|
return s.GetWithContext(context.Background(), key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWithContext key with value with context
|
||||||
|
func (s *Storage) SetWithContext(ctx context.Context, key string, val []byte, exp time.Duration) error {
|
||||||
if len(key) <= 0 {
|
if len(key) <= 0 {
|
||||||
return errors.New("the key value is required")
|
return errors.New("the key value is required")
|
||||||
}
|
}
|
||||||
@@ -106,35 +108,43 @@ func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
|
|||||||
s.cfg.PutObjectOptions.ContentType = http.DetectContentType(val)
|
s.cfg.PutObjectOptions.ContentType = http.DetectContentType(val)
|
||||||
|
|
||||||
// put object
|
// put object
|
||||||
_, err := s.minio.PutObject(s.ctx, s.cfg.Bucket, key, file, file.Size(), s.cfg.PutObjectOptions)
|
_, err := s.minio.PutObject(ctx, s.cfg.Bucket, key, file, file.Size(), s.cfg.PutObjectOptions)
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set key with value
|
||||||
|
func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
|
||||||
|
return s.SetWithContext(context.Background(), key, val, exp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWithContext key with value with context
|
||||||
|
func (s *Storage) DeleteWithContext(ctx context.Context, key string) error {
|
||||||
|
if len(key) <= 0 {
|
||||||
|
return errors.New("the key value is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove
|
||||||
|
err := s.minio.RemoveObject(ctx, s.cfg.Bucket, key, s.cfg.RemoveObjectOptions)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Delete entry by key
|
// Delete entry by key
|
||||||
func (s *Storage) Delete(key string) error {
|
func (s *Storage) Delete(key string) error {
|
||||||
|
return s.DeleteWithContext(context.Background(), key)
|
||||||
if len(key) <= 0 {
|
|
||||||
return errors.New("the key value is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove
|
|
||||||
err := s.minio.RemoveObject(s.ctx, s.cfg.Bucket, key, s.cfg.RemoveObjectOptions)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset all entries, including unexpired
|
// ResetWithContext all keys with context
|
||||||
func (s *Storage) Reset() error {
|
func (s *Storage) ResetWithContext(ctx context.Context) error {
|
||||||
|
|
||||||
objectsCh := make(chan minio.ObjectInfo)
|
objectsCh := make(chan minio.ObjectInfo)
|
||||||
|
|
||||||
// Send object names that are needed to be removed to objectsCh
|
// Send object names that are needed to be removed to objectsCh
|
||||||
go func() {
|
go func() {
|
||||||
defer close(objectsCh)
|
defer close(objectsCh)
|
||||||
// List all objects from a bucket-name with a matching prefix.
|
// List all objects from a bucket-name with a matching prefix.
|
||||||
for object := range s.minio.ListObjects(s.ctx, s.cfg.Bucket, s.cfg.ListObjectsOptions) {
|
for object := range s.minio.ListObjects(ctx, s.cfg.Bucket, s.cfg.ListObjectsOptions) {
|
||||||
if object.Err != nil {
|
if object.Err != nil {
|
||||||
log.Println(object.Err)
|
log.Println(object.Err)
|
||||||
}
|
}
|
||||||
@@ -147,13 +157,17 @@ func (s *Storage) Reset() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var errs []error
|
var errs []error
|
||||||
for err := range s.minio.RemoveObjects(s.ctx, s.cfg.Bucket, objectsCh, opts) {
|
for err := range s.minio.RemoveObjects(ctx, s.cfg.Bucket, objectsCh, opts) {
|
||||||
errs = append(errs, err.Err)
|
errs = append(errs, err.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.Join(errs...)
|
return errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Storage) Reset() error {
|
||||||
|
return s.ResetWithContext(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
// Close the storage
|
// Close the storage
|
||||||
func (s *Storage) Close() error {
|
func (s *Storage) Close() error {
|
||||||
return nil
|
return nil
|
||||||
@@ -161,7 +175,7 @@ func (s *Storage) Close() error {
|
|||||||
|
|
||||||
// CheckBucket Check to see if bucket already exists
|
// CheckBucket Check to see if bucket already exists
|
||||||
func (s *Storage) CheckBucket() error {
|
func (s *Storage) CheckBucket() error {
|
||||||
exists, err := s.minio.BucketExists(s.ctx, s.cfg.Bucket)
|
exists, err := s.minio.BucketExists(context.Background(), s.cfg.Bucket)
|
||||||
if !exists || err != nil {
|
if !exists || err != nil {
|
||||||
return errors.New("the specified bucket does not exist")
|
return errors.New("the specified bucket does not exist")
|
||||||
}
|
}
|
||||||
@@ -170,12 +184,12 @@ func (s *Storage) CheckBucket() error {
|
|||||||
|
|
||||||
// CreateBucket Bucket not found so Make a new bucket
|
// CreateBucket Bucket not found so Make a new bucket
|
||||||
func (s *Storage) CreateBucket() error {
|
func (s *Storage) CreateBucket() error {
|
||||||
return s.minio.MakeBucket(s.ctx, s.cfg.Bucket, minio.MakeBucketOptions{Region: s.cfg.Region})
|
return s.minio.MakeBucket(context.Background(), s.cfg.Bucket, minio.MakeBucketOptions{Region: s.cfg.Region})
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveBucket Bucket remove if bucket is empty
|
// RemoveBucket Bucket remove if bucket is empty
|
||||||
func (s *Storage) RemoveBucket() error {
|
func (s *Storage) RemoveBucket() error {
|
||||||
return s.minio.RemoveBucket(s.ctx, s.cfg.Bucket)
|
return s.minio.RemoveBucket(context.Background(), s.cfg.Bucket)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conn Return minio client
|
// Conn Return minio client
|
||||||
|
|||||||
@@ -81,6 +81,25 @@ func Test_Get(t *testing.T) {
|
|||||||
require.Zero(t, len(result))
|
require.Zero(t, len(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_GetWithContext(t *testing.T) {
|
||||||
|
var (
|
||||||
|
key = "john"
|
||||||
|
val = []byte("doe")
|
||||||
|
)
|
||||||
|
|
||||||
|
testStore := newTestStore(t)
|
||||||
|
|
||||||
|
err := testStore.Set(key, val, 0)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
result, err := testStore.GetWithContext(ctx, key)
|
||||||
|
require.ErrorIs(t, err, context.Canceled)
|
||||||
|
require.Zero(t, len(result))
|
||||||
|
}
|
||||||
|
|
||||||
func Test_Get_Empty_Key(t *testing.T) {
|
func Test_Get_Empty_Key(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
key = ""
|
key = ""
|
||||||
@@ -137,6 +156,21 @@ func Test_Set(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_SetWithContext(t *testing.T) {
|
||||||
|
var (
|
||||||
|
key = "john"
|
||||||
|
val = []byte("doe")
|
||||||
|
)
|
||||||
|
|
||||||
|
testStore := newTestStore(t)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
err := testStore.SetWithContext(ctx, key, val, 0)
|
||||||
|
require.ErrorIs(t, err, context.Canceled)
|
||||||
|
}
|
||||||
|
|
||||||
func Test_Set_Empty_Key(t *testing.T) {
|
func Test_Set_Empty_Key(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
key = ""
|
key = ""
|
||||||
@@ -185,6 +219,28 @@ func Test_Delete(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_DeleteWithContext(t *testing.T) {
|
||||||
|
var (
|
||||||
|
key = "john"
|
||||||
|
val = []byte("doe")
|
||||||
|
)
|
||||||
|
|
||||||
|
testStore := newTestStore(t)
|
||||||
|
|
||||||
|
err := testStore.Set(key, val, 0)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
err = testStore.DeleteWithContext(ctx, key)
|
||||||
|
require.ErrorIs(t, err, context.Canceled)
|
||||||
|
|
||||||
|
valRet, err := testStore.Get(key)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, val, valRet)
|
||||||
|
}
|
||||||
|
|
||||||
func Test_Delete_Empty_Key(t *testing.T) {
|
func Test_Delete_Empty_Key(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
key = ""
|
key = ""
|
||||||
@@ -237,14 +293,35 @@ func Test_Reset(t *testing.T) {
|
|||||||
require.Zero(t, len(result))
|
require.Zero(t, len(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_ResetWithContext(t *testing.T) {
|
||||||
|
var (
|
||||||
|
val = []byte("doe")
|
||||||
|
)
|
||||||
|
|
||||||
|
testStore := newTestStore(t)
|
||||||
|
|
||||||
|
err := testStore.Set("john1", val, 0)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = testStore.Set("john2", val, 0)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
err = testStore.ResetWithContext(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
result, err := testStore.Get("john1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, val, result)
|
||||||
|
}
|
||||||
|
|
||||||
func Test_Reset_Not_Exists_Bucket(t *testing.T) {
|
func Test_Reset_Not_Exists_Bucket(t *testing.T) {
|
||||||
testStore := newTestStore(t)
|
testStore := newTestStore(t)
|
||||||
defer testStore.Close()
|
defer testStore.Close()
|
||||||
|
|
||||||
err := testStore.RemoveBucket()
|
err := testStore.RemoveBucket()
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = testStore.Reset()
|
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.EqualError(t, err, "The specified bucket does not exist")
|
require.EqualError(t, err, "The specified bucket does not exist")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user