From 3b5d81397c349c5e02e3248ecad6179dd3efdc43 Mon Sep 17 00:00:00 2001 From: Juan Calderon-Perez Date: Sun, 29 Oct 2023 20:01:23 -0400 Subject: [PATCH 1/4] Add support for Keys() to Redis Driver --- redis/README.md | 1 + redis/redis.go | 31 +++++++++++++++++++-- redis/redis_test.go | 66 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/redis/README.md b/redis/README.md index f546d21b..aae925bc 100644 --- a/redis/README.md +++ b/redis/README.md @@ -29,6 +29,7 @@ func (s *Storage) Delete(key string) error func (s *Storage) Reset() error func (s *Storage) Close() error func (s *Storage) Conn() redis.UniversalClient +func (s *Storage) Keys() ([][]byte, error) ``` ### Installation Redis is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet: diff --git a/redis/redis.go b/redis/redis.go index c61f37c7..576a417e 100644 --- a/redis/redis.go +++ b/redis/redis.go @@ -74,8 +74,6 @@ func New(config ...Config) *Storage { } } -// ... - // Get value by key func (s *Storage) Get(key string) ([]byte, error) { if len(key) <= 0 { @@ -118,3 +116,32 @@ func (s *Storage) Close() error { func (s *Storage) Conn() redis.UniversalClient { return s.db } + +// Return all the keys +func (s *Storage) Keys() ([][]byte, error) { + var keys [][]byte + var cursor uint64 + + for { + var batch []string + var err error + batch, cursor, err = s.db.Scan(context.Background(), cursor, "*", 10).Result() + if err != nil { + return nil, err + } + + for _, key := range batch { + keys = append(keys, []byte(key)) + } + + if cursor == 0 { + break + } + } + + if len(keys) == 0 { + return nil, nil + } + + return keys, nil +} diff --git a/redis/redis_test.go b/redis/redis_test.go index 42aca367..13b11abe 100644 --- a/redis/redis_test.go +++ b/redis/redis_test.go @@ -34,6 +34,10 @@ func Test_Redis_Set_Override(t *testing.T) { err = testStore.Set(key, val, 0) require.NoError(t, err) + + keys, err := testStore.Keys() + require.NoError(t, err) + require.Len(t, keys, 1) } func Test_Redis_Get(t *testing.T) { @@ -48,9 +52,13 @@ func Test_Redis_Get(t *testing.T) { result, err := testStore.Get(key) require.NoError(t, err) require.Equal(t, val, result) + + keys, err := testStore.Keys() + require.NoError(t, err) + require.Len(t, keys, 1) } -func Test_Redis_Set_Expiration(t *testing.T) { +func Test_Redis_Expiration(t *testing.T) { var ( key = "john" val = []byte("doe") @@ -61,14 +69,14 @@ func Test_Redis_Set_Expiration(t *testing.T) { require.NoError(t, err) time.Sleep(1100 * time.Millisecond) -} - -func Test_Redis_Get_Expired(t *testing.T) { - key := "john" result, err := testStore.Get(key) require.NoError(t, err) require.Zero(t, len(result)) + + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) } func Test_Redis_Get_NotExist(t *testing.T) { @@ -92,6 +100,10 @@ func Test_Redis_Delete(t *testing.T) { result, err := testStore.Get(key) require.NoError(t, err) require.Zero(t, len(result)) + + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) } func Test_Redis_Reset(t *testing.T) { @@ -103,6 +115,10 @@ func Test_Redis_Reset(t *testing.T) { err = testStore.Set("john2", val, 0) require.NoError(t, err) + keys, err := testStore.Keys() + require.NoError(t, err) + require.Len(t, keys, 2) + err = testStore.Reset() require.NoError(t, err) @@ -113,6 +129,10 @@ func Test_Redis_Reset(t *testing.T) { result, err = testStore.Get("john2") require.NoError(t, err) require.Zero(t, len(result)) + + keys, err = testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) } func Test_Redis_Close(t *testing.T) { @@ -184,6 +204,10 @@ func Test_Redis_Initalize_WithURL_TLS(t *testing.T) { err = testStoreUrl.Delete(key) require.NoError(t, err) + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) + require.Nil(t, testStoreUrl.Close()) } @@ -226,6 +250,10 @@ func Test_Redis_Initalize_WithURL_TLS_Verify(t *testing.T) { err = testStoreUrl.Delete(key) require.NoError(t, err) + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) + require.Nil(t, testStoreUrl.Close()) } @@ -249,6 +277,10 @@ func Test_Redis_Initalize_With_Secure_URL(t *testing.T) { err = testStoreUrl.Delete(key) require.NoError(t, err) + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) + require.Nil(t, testStoreUrl.Close()) } @@ -273,6 +305,10 @@ func Test_Redis_Universal_Addrs(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) + require.Nil(t, testStoreUniversal.Close()) } @@ -299,6 +335,10 @@ func Test_Redis_Universal_With_URL_Undefined(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) + require.Nil(t, testStoreUniversal.Close()) } @@ -325,6 +365,10 @@ func Test_Redis_Universal_With_URL_Defined(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) + require.Nil(t, testStoreUniversal.Close()) } @@ -352,6 +396,10 @@ func Test_Redis_Universal_With_HostPort(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) + require.Nil(t, testStoreUniversal.Close()) } @@ -380,6 +428,10 @@ func Test_Redis_Universal_With_HostPort_And_URL(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) + require.Nil(t, testStoreUniversal.Close()) } @@ -410,6 +462,10 @@ func Test_Redis_Cluster(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) + keys, err := testStore.Keys() + require.NoError(t, err) + require.Zero(t, keys) + require.Nil(t, testStoreUniversal.Close()) } From 2143a67c8d737ca5ea641ce3167736c99547c129 Mon Sep 17 00:00:00 2001 From: Juan Calderon-Perez Date: Sun, 29 Oct 2023 20:06:45 -0400 Subject: [PATCH 2/4] Add sleep after creating Redis Cluster --- .github/workflows/test-redis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test-redis.yml b/.github/workflows/test-redis.yml index a4e58b6f..f95852fb 100644 --- a/.github/workflows/test-redis.yml +++ b/.github/workflows/test-redis.yml @@ -66,6 +66,9 @@ jobs: slave3-port: 7005 sleep-duration: 10 + - name: Wait for Redis to Start + run: sleep 15 + - name: Install Go uses: actions/setup-go@v4 with: From 0b9f4aebc8b4e7c2d8bbfbfdc50449b319ffbb33 Mon Sep 17 00:00:00 2001 From: Juan Calderon-Perez Date: Sun, 29 Oct 2023 20:24:11 -0400 Subject: [PATCH 3/4] Create a testStore per test --- redis/redis.go | 6 ++--- redis/redis_test.go | 58 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/redis/redis.go b/redis/redis.go index 576a417e..eff32227 100644 --- a/redis/redis.go +++ b/redis/redis.go @@ -121,12 +121,12 @@ func (s *Storage) Conn() redis.UniversalClient { func (s *Storage) Keys() ([][]byte, error) { var keys [][]byte var cursor uint64 + var err error for { var batch []string - var err error - batch, cursor, err = s.db.Scan(context.Background(), cursor, "*", 10).Result() - if err != nil { + + if batch, cursor, err = s.db.Scan(context.Background(), cursor, "*", 10).Result(); err != nil { return nil, err } diff --git a/redis/redis_test.go b/redis/redis_test.go index 13b11abe..1d1685a9 100644 --- a/redis/redis_test.go +++ b/redis/redis_test.go @@ -9,12 +9,11 @@ import ( "github.com/stretchr/testify/require" ) -var testStore = New(Config{ - Reset: true, -}) - func Test_Redis_Set(t *testing.T) { var ( + testStore = New(Config{ + Reset: true, + }) key = "john" val = []byte("doe") ) @@ -25,6 +24,9 @@ func Test_Redis_Set(t *testing.T) { func Test_Redis_Set_Override(t *testing.T) { var ( + testStore = New(Config{ + Reset: true, + }) key = "john" val = []byte("doe") ) @@ -42,6 +44,9 @@ func Test_Redis_Set_Override(t *testing.T) { func Test_Redis_Get(t *testing.T) { var ( + testStore = New(Config{ + Reset: true, + }) key = "john" val = []byte("doe") ) @@ -60,6 +65,9 @@ func Test_Redis_Get(t *testing.T) { func Test_Redis_Expiration(t *testing.T) { var ( + testStore = New(Config{ + Reset: true, + }) key = "john" val = []byte("doe") exp = 1 * time.Second @@ -80,6 +88,9 @@ func Test_Redis_Expiration(t *testing.T) { } func Test_Redis_Get_NotExist(t *testing.T) { + testStore := New(Config{ + Reset: true, + }) result, err := testStore.Get("notexist") require.NoError(t, err) require.Zero(t, len(result)) @@ -87,6 +98,9 @@ func Test_Redis_Get_NotExist(t *testing.T) { func Test_Redis_Delete(t *testing.T) { var ( + testStore = New(Config{ + Reset: true, + }) key = "john" val = []byte("doe") ) @@ -107,6 +121,9 @@ func Test_Redis_Delete(t *testing.T) { } func Test_Redis_Reset(t *testing.T) { + testStore := New(Config{ + Reset: true, + }) val := []byte("doe") err := testStore.Set("john1", val, 0) @@ -136,10 +153,16 @@ func Test_Redis_Reset(t *testing.T) { } func Test_Redis_Close(t *testing.T) { + testStore := New(Config{ + Reset: true, + }) require.Nil(t, testStore.Close()) } func Test_Redis_Conn(t *testing.T) { + testStore := New(Config{ + Reset: true, + }) require.True(t, testStore.Conn() != nil) } @@ -204,7 +227,7 @@ func Test_Redis_Initalize_WithURL_TLS(t *testing.T) { err = testStoreUrl.Delete(key) require.NoError(t, err) - keys, err := testStore.Keys() + keys, err := testStoreUrl.Keys() require.NoError(t, err) require.Zero(t, keys) @@ -250,7 +273,7 @@ func Test_Redis_Initalize_WithURL_TLS_Verify(t *testing.T) { err = testStoreUrl.Delete(key) require.NoError(t, err) - keys, err := testStore.Keys() + keys, err := testStoreUrl.Keys() require.NoError(t, err) require.Zero(t, keys) @@ -277,7 +300,7 @@ func Test_Redis_Initalize_With_Secure_URL(t *testing.T) { err = testStoreUrl.Delete(key) require.NoError(t, err) - keys, err := testStore.Keys() + keys, err := testStoreUrl.Keys() require.NoError(t, err) require.Zero(t, keys) @@ -305,7 +328,7 @@ func Test_Redis_Universal_Addrs(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) - keys, err := testStore.Keys() + keys, err := testStoreUniversal.Keys() require.NoError(t, err) require.Zero(t, keys) @@ -335,7 +358,7 @@ func Test_Redis_Universal_With_URL_Undefined(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) - keys, err := testStore.Keys() + keys, err := testStoreUniversal.Keys() require.NoError(t, err) require.Zero(t, keys) @@ -365,7 +388,7 @@ func Test_Redis_Universal_With_URL_Defined(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) - keys, err := testStore.Keys() + keys, err := testStoreUniversal.Keys() require.NoError(t, err) require.Zero(t, keys) @@ -396,7 +419,7 @@ func Test_Redis_Universal_With_HostPort(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) - keys, err := testStore.Keys() + keys, err := testStoreUniversal.Keys() require.NoError(t, err) require.Zero(t, keys) @@ -428,7 +451,7 @@ func Test_Redis_Universal_With_HostPort_And_URL(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) - keys, err := testStore.Keys() + keys, err := testStoreUniversal.Keys() require.NoError(t, err) require.Zero(t, keys) @@ -462,7 +485,7 @@ func Test_Redis_Cluster(t *testing.T) { err = testStoreUniversal.Delete(key) require.NoError(t, err) - keys, err := testStore.Keys() + keys, err := testStoreUniversal.Keys() require.NoError(t, err) require.Zero(t, keys) @@ -470,6 +493,9 @@ func Test_Redis_Cluster(t *testing.T) { } func Benchmark_Redis_Set(b *testing.B) { + testStore := New(Config{ + Reset: true, + }) b.ReportAllocs() b.ResetTimer() @@ -482,6 +508,9 @@ func Benchmark_Redis_Set(b *testing.B) { } func Benchmark_Redis_Get(b *testing.B) { + testStore := New(Config{ + Reset: true, + }) err := testStore.Set("john", []byte("doe"), 0) require.NoError(b, err) @@ -496,6 +525,9 @@ func Benchmark_Redis_Get(b *testing.B) { } func Benchmark_Redis_SetAndDelete(b *testing.B) { + testStore := New(Config{ + Reset: true, + }) b.ReportAllocs() b.ResetTimer() From 50bea20332adbe284e0cb03a4eedcf6e216d3aef Mon Sep 17 00:00:00 2001 From: Juan Calderon-Perez Date: Sun, 29 Oct 2023 21:04:03 -0400 Subject: [PATCH 4/4] Update empty check, value should be Nil --- redis/redis_test.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/redis/redis_test.go b/redis/redis_test.go index 1d1685a9..96beaa5e 100644 --- a/redis/redis_test.go +++ b/redis/redis_test.go @@ -84,7 +84,7 @@ func Test_Redis_Expiration(t *testing.T) { keys, err := testStore.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) } func Test_Redis_Get_NotExist(t *testing.T) { @@ -117,7 +117,7 @@ func Test_Redis_Delete(t *testing.T) { keys, err := testStore.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) } func Test_Redis_Reset(t *testing.T) { @@ -149,7 +149,7 @@ func Test_Redis_Reset(t *testing.T) { keys, err = testStore.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) } func Test_Redis_Close(t *testing.T) { @@ -229,7 +229,7 @@ func Test_Redis_Initalize_WithURL_TLS(t *testing.T) { keys, err := testStoreUrl.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) require.Nil(t, testStoreUrl.Close()) } @@ -275,7 +275,7 @@ func Test_Redis_Initalize_WithURL_TLS_Verify(t *testing.T) { keys, err := testStoreUrl.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) require.Nil(t, testStoreUrl.Close()) } @@ -302,7 +302,7 @@ func Test_Redis_Initalize_With_Secure_URL(t *testing.T) { keys, err := testStoreUrl.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) require.Nil(t, testStoreUrl.Close()) } @@ -330,7 +330,7 @@ func Test_Redis_Universal_Addrs(t *testing.T) { keys, err := testStoreUniversal.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) require.Nil(t, testStoreUniversal.Close()) } @@ -360,7 +360,7 @@ func Test_Redis_Universal_With_URL_Undefined(t *testing.T) { keys, err := testStoreUniversal.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) require.Nil(t, testStoreUniversal.Close()) } @@ -390,7 +390,7 @@ func Test_Redis_Universal_With_URL_Defined(t *testing.T) { keys, err := testStoreUniversal.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) require.Nil(t, testStoreUniversal.Close()) } @@ -421,7 +421,7 @@ func Test_Redis_Universal_With_HostPort(t *testing.T) { keys, err := testStoreUniversal.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) require.Nil(t, testStoreUniversal.Close()) } @@ -453,7 +453,7 @@ func Test_Redis_Universal_With_HostPort_And_URL(t *testing.T) { keys, err := testStoreUniversal.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) require.Nil(t, testStoreUniversal.Close()) } @@ -487,7 +487,7 @@ func Test_Redis_Cluster(t *testing.T) { keys, err := testStoreUniversal.Keys() require.NoError(t, err) - require.Zero(t, keys) + require.Nil(t, keys) require.Nil(t, testStoreUniversal.Close()) }