mirror of
				https://github.com/gofiber/storage.git
				synced 2025-10-27 02:10:21 +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 | // 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 | ||||||
|   | |||||||
| @@ -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
	 Muhammed Efe Cetin
					Muhammed Efe Cetin