Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions contrib/nosql/redis/redis_operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,33 @@ func (r *Redis) Conn(ctx context.Context) (gredis.Conn, error) {
redis: r,
}, nil
}

// Client returns the underlying redis client instance.
// This method provides access to the raw redis client for advanced operations
// that are not covered by the standard Redis interface.
//
// Example usage with type assertion:
//
// import goredis "github.com/redis/go-redis/v9"
//
// func ExampleUsage(ctx context.Context, redis *Redis) error {
// client := redis.Client()
// universalClient, ok := client.(goredis.UniversalClient)
// if !ok {
// return errors.New("failed to assert to UniversalClient")
// }
//
// // Use universalClient for advanced operations like Pipeline
// pipe := universalClient.Pipeline()
// pipe.Set(ctx, "key1", "value1", 0)
// pipe.Set(ctx, "key2", "value2", 0)
// results, err := pipe.Exec(ctx)
// if err != nil {
// return err
// }
// // ... handle results
// return nil
// }
func (r *Redis) Client() gredis.RedisRawClient {
return r.client
}
69 changes: 69 additions & 0 deletions contrib/nosql/redis/redis_z_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"testing"
"time"

goredis "github.com/redis/go-redis/v9"

"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/database/gredis"
"github.com/gogf/gf/v2/frame/g"
Expand All @@ -31,6 +33,73 @@ func Test_NewClose(t *testing.T) {
})
}

func Test_Client(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)

// Test getting the client
client := redis.Client()
t.AssertNE(client, nil)

// Test type assertion to goredis.UniversalClient
universalClient, ok := client.(goredis.UniversalClient)
t.Assert(ok, true)
t.AssertNE(universalClient, nil)

// Test that we can use the client directly for redis operations
// This demonstrates that the returned client is properly configured
result := universalClient.Set(ctx, "test-client-key", "test-value", 0)
t.AssertNil(result.Err())

getResult := universalClient.Get(ctx, "test-client-key")
t.AssertNil(getResult.Err())
t.Assert(getResult.Val(), "test-value")

// Clean up
delResult := universalClient.Del(ctx, "test-client-key")
t.AssertNil(delResult.Err())

// Test Pipeline functionality
pipe := universalClient.Pipeline()
t.AssertNE(pipe, nil)

// Add multiple commands to the pipeline
pipe.Set(ctx, "pipeline-key1", "value1", 0)
pipe.Set(ctx, "pipeline-key2", "value2", 0)
pipe.Set(ctx, "pipeline-key3", "value3", 0)
pipe.Get(ctx, "pipeline-key1")
pipe.Get(ctx, "pipeline-key2")
pipe.Get(ctx, "pipeline-key3")

// Execute the pipeline
results, err := pipe.Exec(ctx)
t.AssertNil(err)
t.Assert(len(results), 6) // 3 SET commands + 3 GET commands

// Verify the SET results
for i := range 3 {
t.AssertNil(results[i].Err())
}

// Verify the GET results
getResults := results[3:]
t.Assert(getResults[0].(*goredis.StringCmd).Val(), "value1")
t.Assert(getResults[1].(*goredis.StringCmd).Val(), "value2")
t.Assert(getResults[2].(*goredis.StringCmd).Val(), "value3")

// Clean up pipeline test keys
cleanupPipe := universalClient.Pipeline()
cleanupPipe.Del(ctx, "pipeline-key1")
cleanupPipe.Del(ctx, "pipeline-key2")
cleanupPipe.Del(ctx, "pipeline-key3")
_, err = cleanupPipe.Exec(ctx)
t.AssertNil(err)
})
}

func Test_Do(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
_, err := redis.Do(ctx, "SET", "k", "v")
Expand Down
9 changes: 9 additions & 0 deletions database/gredis/gredis_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ type AdapterGroup interface {
GroupString() IGroupString
}

// RedisRawClient is a type alias for any, representing the raw underlying redis client.
// Implementations should return their concrete client type as this interface.
type RedisRawClient any

// AdapterOperation is the core operation functions for redis.
// These functions can be easily overwritten by custom implements.
type AdapterOperation interface {
Expand All @@ -43,6 +47,11 @@ type AdapterOperation interface {

// Close closes current redis client, closes its connection pool and releases all its related resources.
Close(ctx context.Context) (err error)

// Client returns the underlying redis client instance.
// This method provides access to the raw redis client for advanced operations
// that are not covered by the standard redis adapter interface.
Client() RedisRawClient
}

// Conn is an interface of a connection from universal redis client.
Expand Down
Loading