This commit is contained in:
110
provider/redis/pool.go
Normal file
110
provider/redis/pool.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gitoa.ru/go-4devs/cache"
|
||||
)
|
||||
|
||||
type Conn interface {
|
||||
Do(commandName string, args ...interface{}) (reply interface{}, err error)
|
||||
Send(commandName string, args ...interface{}) error
|
||||
Flush() error
|
||||
Close() error
|
||||
}
|
||||
|
||||
// New creates new provider.
|
||||
func New(pool func(context.Context) (Conn, error)) cache.Provider {
|
||||
return func(ctx context.Context, operation string, item *cache.Item) error {
|
||||
conn, err := pool(ctx)
|
||||
if err != nil {
|
||||
return wrapErr(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
key := item.Key.String()
|
||||
|
||||
switch operation {
|
||||
case cache.OperationGet:
|
||||
data, ttl, err := get(conn, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
item.TTLInSecond(ttl)
|
||||
|
||||
return wrapErr(item.Unmarshal(data))
|
||||
case cache.OperationSet:
|
||||
data, err := item.Marshal()
|
||||
if err != nil {
|
||||
return wrapErr(err)
|
||||
}
|
||||
|
||||
return set(conn, key, data, int(item.TTL.Seconds()))
|
||||
case cache.OperationDelete:
|
||||
return del(conn, key)
|
||||
}
|
||||
|
||||
return wrapErr(cache.ErrOperationNotAllwed)
|
||||
}
|
||||
}
|
||||
|
||||
func get(conn Conn, key string) ([]byte, int64, error) {
|
||||
data, err := conn.Do("GET", key)
|
||||
if err != nil {
|
||||
return nil, 0, wrapErr(err)
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
return nil, 0, wrapErr(cache.ErrCacheMiss)
|
||||
}
|
||||
|
||||
v, ok := data.([]byte)
|
||||
if !ok {
|
||||
return nil, 0, wrapErr(cache.ErrSourceNotValid)
|
||||
}
|
||||
|
||||
expire, err := conn.Do("TTL", key)
|
||||
if err != nil {
|
||||
return v, 0, wrapErr(err)
|
||||
}
|
||||
|
||||
ex, _ := expire.(int64)
|
||||
|
||||
return v, ex, nil
|
||||
}
|
||||
|
||||
func set(conn Conn, key string, data []byte, ttl int) error {
|
||||
if err := conn.Send("SET", key, data); err != nil {
|
||||
return wrapErr(err)
|
||||
}
|
||||
|
||||
if ttl > 0 {
|
||||
if err := conn.Send("EXPIRE", key, ttl); err != nil {
|
||||
return wrapErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := conn.Flush(); err != nil {
|
||||
return fmt.Errorf("failed flush then set %s by %w", key, conn.Flush())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func del(conn Conn, key string) error {
|
||||
if _, err := conn.Do("DEL", key); err != nil {
|
||||
return wrapErr(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func wrapErr(err error) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: redis pool", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
14
provider/redis/pool_test.go
Normal file
14
provider/redis/pool_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package redis_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gitoa.ru/go-4devs/cache"
|
||||
"gitoa.ru/go-4devs/cache/provider/redis"
|
||||
"gitoa.ru/go-4devs/cache/test"
|
||||
)
|
||||
|
||||
func TestRedisPool(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.RunSute(t, redis.New(test.RedisClient()), test.WithExpire(cache.ErrCacheMiss))
|
||||
}
|
||||
20
provider/redis/redigo.go
Normal file
20
provider/redis/redigo.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gomodule/redigo/redis"
|
||||
)
|
||||
|
||||
// NewPool creates redigo pool.
|
||||
func NewPool(pool *redis.Pool) func(context.Context) (Conn, error) {
|
||||
return func(ctx context.Context) (Conn, error) {
|
||||
conn, err := pool.GetContext(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed get connect: %w", err)
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user