minio: add support for context management

This commit is contained in:
Muhammed Efe Cetin
2025-02-09 20:18:23 +03:00
parent a01135d48b
commit 134e774e80
2 changed files with 120 additions and 29 deletions

View File

@@ -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 // ResetWithContext all keys with context
err := s.minio.RemoveObject(s.ctx, s.cfg.Bucket, key, s.cfg.RemoveObjectOptions) func (s *Storage) ResetWithContext(ctx context.Context) error {
return err
}
// Reset all entries, including unexpired
func (s *Storage) Reset() 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

View File

@@ -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")
} }