mirror of
				https://github.com/gofiber/storage.git
				synced 2025-10-31 03:36:25 +08:00 
			
		
		
		
	dynamodb: add support for context management
This commit is contained in:
		| @@ -19,7 +19,6 @@ import ( | |||||||
| type Storage struct { | type Storage struct { | ||||||
| 	db    *awsdynamodb.Client | 	db    *awsdynamodb.Client | ||||||
| 	table string | 	table string | ||||||
| 	requestTimeout time.Duration |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // "k" is used as table column name for the key. | // "k" is used as table column name for the key. | ||||||
| @@ -77,11 +76,8 @@ func New(config Config) *Storage { | |||||||
| 	return store | 	return store | ||||||
| } | } | ||||||
|  |  | ||||||
| // 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) { | ||||||
| 	ctx, cancel := s.requestContext() |  | ||||||
| 	defer cancel() |  | ||||||
|  |  | ||||||
| 	k := make(map[string]types.AttributeValue) | 	k := make(map[string]types.AttributeValue) | ||||||
| 	k[keyAttrName] = &types.AttributeValueMemberS{ | 	k[keyAttrName] = &types.AttributeValueMemberS{ | ||||||
| 		Value: key, | 		Value: key, | ||||||
| @@ -108,11 +104,12 @@ func (s *Storage) Get(key string) ([]byte, error) { | |||||||
| 	return item.V, err | 	return item.V, err | ||||||
| } | } | ||||||
|  |  | ||||||
| // Set key with value | func (s *Storage) Get(key string) ([]byte, error) { | ||||||
| func (s *Storage) Set(key string, val []byte, exp time.Duration) error { | 	return s.GetWithContext(context.Background(), key) | ||||||
| 	ctx, cancel := s.requestContext() | } | ||||||
| 	defer cancel() |  | ||||||
|  |  | ||||||
|  | // Set key with value | ||||||
|  | func (s *Storage) SetWithContext(ctx context.Context, key string, val []byte, exp time.Duration) error { | ||||||
| 	// Ain't Nobody Got Time For That | 	// Ain't Nobody Got Time For That | ||||||
| 	if len(key) <= 0 || len(val) <= 0 { | 	if len(key) <= 0 || len(val) <= 0 { | ||||||
| 		return nil | 		return nil | ||||||
| @@ -134,11 +131,12 @@ func (s *Storage) Set(key string, val []byte, exp time.Duration) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| // Delete entry by key | func (s *Storage) Set(key string, val []byte, exp time.Duration) error { | ||||||
| func (s *Storage) Delete(key string) error { | 	return s.SetWithContext(context.Background(), key, val, exp) | ||||||
| 	ctx, cancel := s.requestContext() | } | ||||||
| 	defer cancel() |  | ||||||
|  |  | ||||||
|  | // Delete entry by key | ||||||
|  | func (s *Storage) DeleteWithContext(ctx context.Context, key string) error { | ||||||
| 	// Ain't Nobody Got Time For That | 	// Ain't Nobody Got Time For That | ||||||
| 	if len(key) <= 0 { | 	if len(key) <= 0 { | ||||||
| 		return nil | 		return nil | ||||||
| @@ -157,11 +155,12 @@ func (s *Storage) Delete(key string) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| // Reset all entries, including unexpired | func (s *Storage) Delete(key string) error { | ||||||
| func (s *Storage) Reset() error { | 	return s.DeleteWithContext(context.Background(), key) | ||||||
| 	ctx, cancel := s.requestContext() | } | ||||||
| 	defer cancel() |  | ||||||
|  |  | ||||||
|  | // Reset all entries, including unexpired | ||||||
|  | func (s *Storage) ResetWithContext(ctx context.Context) error { | ||||||
| 	deleteTableInput := awsdynamodb.DeleteTableInput{ | 	deleteTableInput := awsdynamodb.DeleteTableInput{ | ||||||
| 		TableName: &s.table, | 		TableName: &s.table, | ||||||
| 	} | 	} | ||||||
| @@ -169,14 +168,17 @@ func (s *Storage) Reset() error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (s *Storage) Reset() error { | ||||||
|  | 	return s.ResetWithContext(context.Background()) | ||||||
|  | } | ||||||
|  |  | ||||||
| // Close the database | // Close the database | ||||||
| func (s *Storage) Close() error { | func (s *Storage) Close() error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *Storage) createTable(cfg Config, describeTableInput awsdynamodb.DescribeTableInput) error { | func (s *Storage) createTable(cfg Config, describeTableInput awsdynamodb.DescribeTableInput) error { | ||||||
| 	ctx, cancel := s.requestContext() | 	ctx := context.Background() | ||||||
| 	defer cancel() |  | ||||||
|  |  | ||||||
| 	keyAttrType := "S" // For "string" | 	keyAttrType := "S" // For "string" | ||||||
| 	keyType := "HASH"  // As opposed to "RANGE" | 	keyType := "HASH"  // As opposed to "RANGE" | ||||||
| @@ -225,14 +227,6 @@ func (s *Storage) createTable(cfg Config, describeTableInput awsdynamodb.Describ | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // Context for making requests will timeout if a non-zero timeout is configured |  | ||||||
| func (s *Storage) requestContext() (context.Context, context.CancelFunc) { |  | ||||||
| 	if s.requestTimeout > 0 { |  | ||||||
| 		return context.WithTimeout(context.Background(), s.requestTimeout) |  | ||||||
| 	} |  | ||||||
| 	return context.Background(), func() {} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func returnAWSConfig(cfg Config) (aws.Config, error) { | func returnAWSConfig(cfg Config) (aws.Config, error) { | ||||||
| 	if cfg.Credentials != (Credentials{}) { | 	if cfg.Credentials != (Credentials{}) { | ||||||
| 		credentials := credentials.NewStaticCredentialsProvider(cfg.Credentials.AccessKey, cfg.Credentials.SecretAccessKey, "") | 		credentials := credentials.NewStaticCredentialsProvider(cfg.Credentials.AccessKey, cfg.Credentials.SecretAccessKey, "") | ||||||
|   | |||||||
| @@ -60,6 +60,19 @@ func Test_DynamoDB_Set(t *testing.T) { | |||||||
| 	require.NoError(t, err) | 	require.NoError(t, err) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func Test_DynamoDB_SetWithContext(t *testing.T) { | ||||||
|  | 	var ( | ||||||
|  | 		key = "john" | ||||||
|  | 		val = []byte("doe") | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	ctx, cancel := context.WithCancel(context.Background()) | ||||||
|  | 	cancel() | ||||||
|  |  | ||||||
|  | 	err := testStore.SetWithContext(ctx, key, val, 0) | ||||||
|  | 	require.ErrorIs(t, err, context.Canceled) | ||||||
|  | } | ||||||
|  |  | ||||||
| func Test_DynamoDB_Set_Override(t *testing.T) { | func Test_DynamoDB_Set_Override(t *testing.T) { | ||||||
| 	var ( | 	var ( | ||||||
| 		key = "john" | 		key = "john" | ||||||
| @@ -93,6 +106,19 @@ func Test_DynamoDB_Get(t *testing.T) { | |||||||
| 	require.Equal(t, val, result) | 	require.Equal(t, val, result) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func Test_DynamoDB_GetWithContext(t *testing.T) { | ||||||
|  | 	var ( | ||||||
|  | 		key = "john" | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	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_DynamoDB_Get_NotExist(t *testing.T) { | func Test_DynamoDB_Get_NotExist(t *testing.T) { | ||||||
| 	testStore := newTestStore(t) | 	testStore := newTestStore(t) | ||||||
| 	defer testStore.Close() | 	defer testStore.Close() | ||||||
| @@ -122,6 +148,26 @@ func Test_DynamoDB_Delete(t *testing.T) { | |||||||
| 	require.Zero(t, len(result)) | 	require.Zero(t, len(result)) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func Test_DynamoDB_DeleteWithContext(t *testing.T) { | ||||||
|  | 	var ( | ||||||
|  | 		key = "john" | ||||||
|  | 		val = []byte("doe") | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	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) | ||||||
|  |  | ||||||
|  | 	result, err := testStore.Get(key) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.Equal(t, val, result) | ||||||
|  | } | ||||||
|  |  | ||||||
| func Test_DynamoDB_Reset(t *testing.T) { | func Test_DynamoDB_Reset(t *testing.T) { | ||||||
| 	val := []byte("doe") | 	val := []byte("doe") | ||||||
|  |  | ||||||
| @@ -146,6 +192,30 @@ func Test_DynamoDB_Reset(t *testing.T) { | |||||||
| 	require.Zero(t, len(result)) | 	require.Zero(t, len(result)) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func Test_DynamoDB_ResetWithContext(t *testing.T) { | ||||||
|  | 	val := []byte("doe") | ||||||
|  |  | ||||||
|  | 	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.ErrorIs(t, err, context.Canceled) | ||||||
|  |  | ||||||
|  | 	result, err := testStore.Get("john1") | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.Equal(t, val, result) | ||||||
|  |  | ||||||
|  | 	result, err = testStore.Get("john2") | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.Equal(t, val, result) | ||||||
|  | } | ||||||
|  |  | ||||||
| func Test_DynamoDB_Close(t *testing.T) { | func Test_DynamoDB_Close(t *testing.T) { | ||||||
| 	testStore := newTestStore(t) | 	testStore := newTestStore(t) | ||||||
| 	require.Nil(t, testStore.Close()) | 	require.Nil(t, testStore.Close()) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Muhammed Efe Cetin
					Muhammed Efe Cetin