-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add cache, token config, verify signature (#15)
* feat: add cache, token config, verify signature * bet
- Loading branch information
1 parent
7d9c1e9
commit 2a36653
Showing
12 changed files
with
1,115 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package cache | ||
|
||
import ( | ||
"github.com/dgraph-io/ristretto" | ||
"time" | ||
) | ||
|
||
type Cache interface { | ||
Set(key string, value interface{}, ttl time.Duration) error | ||
Get(key string, result any) error | ||
Del(key string) error | ||
} | ||
|
||
type CfgCache struct { | ||
*ristretto.Config | ||
Type string | ||
RedisUrl string | ||
} | ||
|
||
func NewCache(cfg *CfgCache) Cache { | ||
var cache Cache | ||
if cfg.Type == "redis" && cfg.RedisUrl != "" { | ||
cache = NewRedisCache(cfg.RedisUrl) | ||
} else { | ||
if cfg.Config == nil { | ||
cache, _ = NewRistrettoCacheDefault() | ||
} else { | ||
cache, _ = NewRistrettoCache(&ristretto.Config{ | ||
NumCounters: cfg.NumCounters, | ||
MaxCost: cfg.MaxCost, | ||
BufferItems: cfg.BufferItems, | ||
}) | ||
} | ||
} | ||
|
||
return cache | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
package cache_test | ||
|
||
import ( | ||
"github.com/KyberNetwork/kutils/cache" | ||
"github.com/stretchr/testify/require" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestCache(t *testing.T) { | ||
cacheTypes := []struct { | ||
name string | ||
config *cache.CfgCache | ||
}{ | ||
{"Ristretto", &cache.CfgCache{ | ||
Type: "ristretto", | ||
}}, | ||
{"Redis", &cache.CfgCache{ | ||
Type: "ristretto", | ||
RedisUrl: "localhost:6379", | ||
}}, | ||
} | ||
|
||
type example struct { | ||
Name string | ||
Age int | ||
Value uint64 | ||
} | ||
|
||
for _, ct := range cacheTypes { | ||
t.Run(ct.name, func(t *testing.T) { | ||
var err error | ||
|
||
sCache := cache.NewCache(ct.config) | ||
// Example usage | ||
key1 := "exampleKey" | ||
key2 := "exampleKey1" | ||
input1 := example{ | ||
Name: t.Name(), | ||
Value: 1, | ||
} | ||
input2 := "demo 123" | ||
ttl := 5 * time.Minute | ||
|
||
err = sCache.Set(key1, input1, ttl) | ||
require.NoError(t, err, "Error setting cache") | ||
err = sCache.Set(key2, input2, ttl) | ||
require.NoError(t, err, "Error setting cache") | ||
var res1 *example | ||
err = sCache.Get(key1, &res1) | ||
require.NoError(t, err, "Error getting cache") | ||
require.Equal(t, input1, *res1, "Error expected cache value") | ||
|
||
var res2 string | ||
err = sCache.Get(key2, &res2) | ||
require.NoError(t, err, "Error getting cache") | ||
require.Equal(t, input2, res2, "Error expected cache value") | ||
}) | ||
t.Run("Pointer Types", func(t *testing.T) { | ||
sCache := cache.NewCache(ct.config) | ||
key := "pointerTest" | ||
input := &example{Name: "pointer", Age: 25, Value: 100} | ||
err := sCache.Set(key, input, time.Minute) | ||
require.NoError(t, err) | ||
|
||
var result *example | ||
err = sCache.Get(key, &result) | ||
require.NoError(t, err) | ||
require.Equal(t, input, result) | ||
}) | ||
|
||
t.Run("Non-existent Key", func(t *testing.T) { | ||
sCache := cache.NewCache(ct.config) | ||
var result string | ||
err := sCache.Get("nonexistentKey", &result) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "key not found") | ||
}) | ||
|
||
t.Run("Type Mismatch", func(t *testing.T) { | ||
sCache := cache.NewCache(ct.config) | ||
key := "typeMismatch" | ||
err := sCache.Set(key, 42, time.Minute) | ||
require.NoError(t, err) | ||
|
||
var result string | ||
err = sCache.Get(key, &result) | ||
require.Error(t, err) | ||
}) | ||
|
||
t.Run("Nil Pointer", func(t *testing.T) { | ||
sCache := cache.NewCache(ct.config) | ||
key := "nilPointer" | ||
err := sCache.Set(key, "test", time.Minute) | ||
require.NoError(t, err) | ||
|
||
var result *string | ||
err = sCache.Get(key, result) // passing nil pointer | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "nil") | ||
}) | ||
|
||
t.Run("Non-existent Key", func(t *testing.T) { | ||
sCache := cache.NewCache(ct.config) | ||
var result string | ||
err := sCache.Get("nonexistentKey", &result) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "key not found") | ||
}) | ||
|
||
t.Run("Type Mismatch", func(t *testing.T) { | ||
sCache := cache.NewCache(ct.config) | ||
key := "typeMismatch" | ||
err := sCache.Set(key, 42, time.Minute) | ||
require.NoError(t, err) | ||
|
||
var result string | ||
err = sCache.Get(key, &result) | ||
require.Error(t, err) | ||
}) | ||
|
||
t.Run("Nil Pointer", func(t *testing.T) { | ||
sCache := cache.NewCache(ct.config) | ||
key := "nilPointer" | ||
err := sCache.Set(key, "test", time.Minute) | ||
require.NoError(t, err) | ||
|
||
var result *string | ||
err = sCache.Get(key, result) // passing nil pointer | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "nil") | ||
}) | ||
|
||
//t.Run("Complex Types", func(t *testing.T) { | ||
// sCache := cache.NewCache(ct.config) | ||
// key := "complexType" | ||
// input := map[string]interface{}{ | ||
// "name": "test", | ||
// "data": []int{1, 2, 3}, | ||
// } | ||
// err := sCache.Set(key, input, time.Minute) | ||
// require.NoError(t, err) | ||
// | ||
// var result *map[string]interface{} | ||
// err = sCache.Get(key, &result) | ||
// require.NoError(t, err) | ||
// require.Equal(t, input, *result) | ||
//}) | ||
} | ||
} | ||
|
||
func TestDelKey(t *testing.T) { | ||
cacheTypes := []struct { | ||
name string | ||
config *cache.CfgCache | ||
}{ | ||
{"Ristretto", &cache.CfgCache{ | ||
Type: "ristretto", | ||
}}, | ||
{"Redis", &cache.CfgCache{ | ||
Type: "ristretto", | ||
RedisUrl: "localhost:6379", | ||
}}, | ||
} | ||
for _, ct := range cacheTypes { | ||
t.Run(ct.name, func(t *testing.T) { | ||
sCache := cache.NewCache(ct.config) | ||
key := "test_key" | ||
value := "123test" | ||
err := sCache.Set(key, value, time.Minute) | ||
require.NoError(t, err) | ||
err = sCache.Del(key) | ||
require.NoError(t, err) | ||
|
||
var result string | ||
err = sCache.Get(key, &result) | ||
require.Error(t, err) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package cache | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/redis/go-redis/v9" | ||
) | ||
|
||
type RedisCache struct { | ||
client *redis.Client | ||
} | ||
|
||
func NewRedisCache(redisURL string) *RedisCache { | ||
client := redis.NewClient(&redis.Options{ | ||
Addr: redisURL, | ||
}) | ||
return &RedisCache{client: client} | ||
} | ||
|
||
func (r *RedisCache) Set(key string, value interface{}, ttl time.Duration) error { | ||
// Marshal the value to JSON | ||
jsonData, err := json.Marshal(value) | ||
if err != nil { | ||
return fmt.Errorf("failed to marshal value: %w", err) | ||
} | ||
return r.client.Set(context.Background(), key, jsonData, ttl).Err() | ||
} | ||
|
||
func (r *RedisCache) Get(key string, result any) error { | ||
value, err := r.client.Get(context.Background(), key).Result() | ||
if errors.Is(err, redis.Nil) { | ||
return fmt.Errorf("key not found") | ||
} | ||
err = json.Unmarshal([]byte(value), result) | ||
return err | ||
} | ||
|
||
func (r *RedisCache) Del(key string) error { | ||
return r.client.Del(context.Background(), key).Err() | ||
} |
Oops, something went wrong.