mirror of
https://github.com/gofiber/storage.git
synced 2025-10-05 00:33:03 +08:00
Add DragonflyDB info to Redis README and remove DragonflyDB file
- Added DragonflyDB usage details to Redis README - Removed the DragonflyDB file - No extra tests were added for DragonflyDB; existing Redis tests work for it
This commit is contained in:
@@ -1,198 +0,0 @@
|
||||
---
|
||||
id: dragonfly
|
||||
title: Dragonfly
|
||||
---
|
||||
|
||||

|
||||
[](https://gofiber.io/discord)
|
||||

|
||||

|
||||

|
||||
|
||||
A Dragonfly storage driver using [go-redis/redis](https://github.com/go-redis/redis). (Dragonfly is a redis-like database)
|
||||
|
||||
**Note: Requires Go 1.21 and above**
|
||||
|
||||
### Table of Contents
|
||||
- [Signatures](../dragonfly/README.md#signatures)
|
||||
- [Installation](../dragonfly/README.md#installation)
|
||||
- [Examples](../dragonfly/README.md#examples)
|
||||
- [Config](../dragonfly/README.md#config)
|
||||
- [Default Config](../dragonfly/README.md#default-config)
|
||||
|
||||
### Signatures
|
||||
```go
|
||||
func New(config ...Config) *Storage
|
||||
func (s *Storage) Get(key string) ([]byte, error)
|
||||
func (s *Storage) Set(key string, val []byte, exp time.Duration) error
|
||||
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
|
||||
Dragonfly 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:
|
||||
```bash
|
||||
go mod init github.com/<user>/<repo>
|
||||
```
|
||||
And then install the dragonfly implementation:
|
||||
```bash
|
||||
go get github.com/gofiber/storage/dragonfly
|
||||
```
|
||||
|
||||
### Examples
|
||||
Import the storage package.
|
||||
```go
|
||||
import "github.com/gofiber/storage/dragonfly"
|
||||
```
|
||||
|
||||
You can use the one of the following options to create a Dragonfly Storage:
|
||||
```go
|
||||
// Initialize default config
|
||||
store := dragonfly.New()
|
||||
|
||||
// Initialize custom config
|
||||
store := dragonfly.New(dragonfly.Config{
|
||||
Host: "127.0.0.1",
|
||||
Port: 6379,
|
||||
Username: "",
|
||||
Password: "",
|
||||
Database: 0,
|
||||
Reset: false,
|
||||
TLSConfig: nil,
|
||||
PoolSize: 10 * runtime.GOMAXPROCS(0),
|
||||
})
|
||||
|
||||
// Initialize Dragonfly Failover Client
|
||||
store := dragonfly.New(dragonfly.Config{
|
||||
MasterName: "master-name",
|
||||
Addrs: []string{":6379"},
|
||||
})
|
||||
|
||||
// Initialize Dragonfly Cluster Client
|
||||
store := dragonfly.New(dragonfly.Config{
|
||||
Addrs: []string{":6379", ":6380"},
|
||||
})
|
||||
|
||||
// Create a client with support for TLS
|
||||
cer, err := tls.LoadX509KeyPair("./client.crt", "./client.key")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
tlsCfg := &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: true,
|
||||
Certificates: []tls.Certificate{cer},
|
||||
}
|
||||
store = dragonfly.New(dragonfly.Config{
|
||||
URL: "redis://<user>:<pass>@127.0.0.1:6379/<db>", // Accepts URLs starting with Dragonfly redis
|
||||
TLSConfig: tlsCfg,
|
||||
Reset: false,
|
||||
})
|
||||
|
||||
// "Dragonfly is a key-value store that supports the Redis protocol and is compatible with Redis clients."
|
||||
// Create a client with a Dragonfly URL with all information.
|
||||
store = dragonfly.New(dragonfly.Config{
|
||||
URL: "redis://<user>:<pass>@127.0.0.1:6379/<db>", // Accepts URLs starting with Dragonfly redis
|
||||
Reset: false,
|
||||
})
|
||||
```
|
||||
|
||||
### Config
|
||||
```go
|
||||
type Config struct {
|
||||
// Host name where the DB is hosted
|
||||
//
|
||||
// Optional. Default is "127.0.0.1"
|
||||
Host string
|
||||
|
||||
// Port where the DB is listening on
|
||||
//
|
||||
// Optional. Default is 6379
|
||||
Port int
|
||||
|
||||
// Server username
|
||||
//
|
||||
// Optional. Default is ""
|
||||
Username string
|
||||
|
||||
// Server password
|
||||
//
|
||||
// Optional. Default is ""
|
||||
Password string
|
||||
|
||||
// Database to be selected after connecting to the server.
|
||||
//
|
||||
// Optional. Default is 0
|
||||
Database int
|
||||
|
||||
// URL standard format Dragonfly URL. If this is set all other config options, Host, Port, Username, Password, Database have no effect.
|
||||
//
|
||||
// Example: redis://<user>:<pass>@localhost:6379/<db>
|
||||
// Optional. Default is ""
|
||||
URL string
|
||||
|
||||
// Either a single address or a seed list of host:port addresses, this enables FailoverClient and ClusterClient
|
||||
//
|
||||
// Optional. Default is []string{}
|
||||
Addrs []string
|
||||
|
||||
// MasterName is the sentinel master's name
|
||||
//
|
||||
// Optional. Default is ""
|
||||
MasterName string
|
||||
|
||||
// ClientName will execute the `CLIENT SETNAME ClientName` command for each conn.
|
||||
//
|
||||
// Optional. Default is ""
|
||||
ClientName string
|
||||
|
||||
// SentinelUsername
|
||||
//
|
||||
// Optional. Default is ""
|
||||
SentinelUsername string
|
||||
|
||||
// SentinelPassword
|
||||
//
|
||||
// Optional. Default is ""
|
||||
SentinelPassword string
|
||||
|
||||
// Reset clears any existing keys in existing Collection
|
||||
//
|
||||
// Optional. Default is false
|
||||
Reset bool
|
||||
|
||||
// TLS Config to use. When set TLS will be negotiated.
|
||||
//
|
||||
// Optional. Default is nil
|
||||
TLSConfig *tls.Config
|
||||
|
||||
// Maximum number of socket connections.
|
||||
//
|
||||
// Optional. Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS.
|
||||
PoolSize int
|
||||
}
|
||||
```
|
||||
|
||||
### Default Config
|
||||
```go
|
||||
var ConfigDefault = Config{
|
||||
Host: "127.0.0.1",
|
||||
Port: 6379,
|
||||
Username: "",
|
||||
Password: "",
|
||||
URL: "",
|
||||
Database: 0,
|
||||
Reset: false,
|
||||
TLSConfig: nil,
|
||||
PoolSize: 10 * runtime.GOMAXPROCS(0),
|
||||
Addrs: []string{},
|
||||
MasterName: "",
|
||||
ClientName: "",
|
||||
SentinelUsername: "",
|
||||
SentinelPassword: "",
|
||||
}
|
||||
```
|
||||
|
@@ -1,126 +0,0 @@
|
||||
package dragonfly
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"runtime"
|
||||
|
||||
redis "github.com/gofiber/storage/redis/v3"
|
||||
)
|
||||
|
||||
// Config defines the config for storage.
|
||||
type Config struct {
|
||||
// Host name where the DB is hosted
|
||||
//
|
||||
// Optional. Default is "127.0.0.1"
|
||||
Host string
|
||||
|
||||
// Port where the DB is listening on
|
||||
//
|
||||
// Optional. Default is 6379
|
||||
Port int
|
||||
|
||||
// Server username
|
||||
//
|
||||
// Optional. Default is ""
|
||||
Username string
|
||||
|
||||
// Server password
|
||||
//
|
||||
// Optional. Default is ""
|
||||
Password string
|
||||
|
||||
// Database to be selected after connecting to the server.
|
||||
//
|
||||
// Optional. Default is 0
|
||||
Database int
|
||||
|
||||
// URL standard format Redis URL. If this is set all other config options, Host, Port, Username, Password, Database have no effect.
|
||||
//
|
||||
// Example: redis://<user>:<pass>@localhost:6379/<db>
|
||||
// Optional. Default is ""
|
||||
URL string
|
||||
|
||||
// Either a single address or a seed list of host:port addresses, this enables FailoverClient and ClusterClient
|
||||
//
|
||||
// Optional. Default is []string{}
|
||||
Addrs []string
|
||||
|
||||
// MasterName is the sentinel master's name
|
||||
//
|
||||
// Optional. Default is ""
|
||||
MasterName string
|
||||
|
||||
// ClientName will execute the `CLIENT SETNAME ClientName` command for each conn.
|
||||
//
|
||||
// Optional. Default is ""
|
||||
ClientName string
|
||||
|
||||
// SentinelUsername
|
||||
//
|
||||
// Optional. Default is ""
|
||||
SentinelUsername string
|
||||
|
||||
// SentinelPassword
|
||||
//
|
||||
// Optional. Default is ""
|
||||
SentinelPassword string
|
||||
|
||||
// Reset clears any existing keys in existing Collection
|
||||
//
|
||||
// Optional. Default is false
|
||||
Reset bool
|
||||
|
||||
// TLS Config to use. When set TLS will be negotiated.
|
||||
//
|
||||
// Optional. Default is nil
|
||||
TLSConfig *tls.Config
|
||||
|
||||
// Maximum number of socket connections.
|
||||
//
|
||||
// Optional. Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS.
|
||||
PoolSize int
|
||||
}
|
||||
|
||||
// ConfigDefault is the default config
|
||||
var ConfigDefault = Config{
|
||||
Host: "127.0.0.1",
|
||||
Port: 6379,
|
||||
Username: "",
|
||||
Password: "",
|
||||
URL: "",
|
||||
Database: 0,
|
||||
Reset: false,
|
||||
TLSConfig: nil,
|
||||
PoolSize: 10 * runtime.GOMAXPROCS(0),
|
||||
Addrs: []string{},
|
||||
MasterName: "",
|
||||
ClientName: "",
|
||||
SentinelUsername: "",
|
||||
SentinelPassword: "",
|
||||
}
|
||||
|
||||
// Helper function to set default values
|
||||
func configDefault(config ...Config) redis.Config {
|
||||
// Return default config if nothing provided
|
||||
if len(config) < 1 {
|
||||
return redis.ConfigDefault
|
||||
}
|
||||
|
||||
// Override default config
|
||||
cfg := config[0]
|
||||
|
||||
// Set default values
|
||||
if cfg.Host == "" {
|
||||
cfg.Host = ConfigDefault.Host
|
||||
}
|
||||
if cfg.Port <= 0 {
|
||||
cfg.Port = ConfigDefault.Port
|
||||
}
|
||||
return redis.Config{
|
||||
Host: cfg.Host,
|
||||
Port: cfg.Port,
|
||||
Username: cfg.Username,
|
||||
Password: cfg.Password,
|
||||
Database: cfg.Database,
|
||||
}
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
package dragonfly
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
redisStore "github.com/gofiber/storage/redis/v3"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
type Storage struct {
|
||||
rstorage *redisStore.Storage
|
||||
}
|
||||
|
||||
func New(config ...Config) *Storage {
|
||||
|
||||
cfg := configDefault(config...)
|
||||
s := redisStore.New(cfg)
|
||||
|
||||
return &Storage{
|
||||
rstorage: s,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
|
||||
return s.rstorage.Set(key, val, exp)
|
||||
}
|
||||
|
||||
func (s *Storage) Get(key string) ([]byte, error) {
|
||||
return s.rstorage.Get(key)
|
||||
}
|
||||
|
||||
func (s *Storage) Delete(key string) error {
|
||||
return s.rstorage.Delete(key)
|
||||
}
|
||||
|
||||
func (s *Storage) Reset() error {
|
||||
return s.rstorage.Reset()
|
||||
}
|
||||
|
||||
func (s *Storage) Close() error {
|
||||
return s.rstorage.Close()
|
||||
}
|
||||
|
||||
// Return all the keys
|
||||
func (s *Storage) Keys() ([][]byte, error) {
|
||||
return s.rstorage.Keys()
|
||||
}
|
||||
|
||||
func (s *Storage) Conn() redis.UniversalClient {
|
||||
return s.rstorage.Conn()
|
||||
}
|
@@ -1,475 +0,0 @@
|
||||
package dragonfly
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_Dragonfly_Set(t *testing.T) {
|
||||
var (
|
||||
testStore = New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
key = "john"
|
||||
val = []byte("doe")
|
||||
)
|
||||
|
||||
err := testStore.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Set_Override(t *testing.T) {
|
||||
var (
|
||||
testStore = New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
key = "john"
|
||||
val = []byte("doe")
|
||||
)
|
||||
|
||||
err := testStore.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
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_Dragonfly_Get(t *testing.T) {
|
||||
var (
|
||||
testStore = New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
key = "john"
|
||||
val = []byte("doe")
|
||||
)
|
||||
|
||||
err := testStore.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
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_Dragonfly_Expiration(t *testing.T) {
|
||||
var (
|
||||
testStore = New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
key = "john"
|
||||
val = []byte("doe")
|
||||
exp = 1 * time.Second
|
||||
)
|
||||
|
||||
err := testStore.Set(key, val, exp)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(1100 * time.Millisecond)
|
||||
|
||||
result, err := testStore.Get(key)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, len(result))
|
||||
|
||||
keys, err := testStore.Keys()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, keys)
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Get_NotExist(t *testing.T) {
|
||||
testStore := New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
result, err := testStore.Get("notexist")
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, len(result))
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Delete(t *testing.T) {
|
||||
var (
|
||||
testStore = New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
key = "john"
|
||||
val = []byte("doe")
|
||||
)
|
||||
|
||||
err := testStore.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = testStore.Delete(key)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := testStore.Get(key)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, len(result))
|
||||
|
||||
keys, err := testStore.Keys()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, keys)
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Reset(t *testing.T) {
|
||||
testStore := New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
val := []byte("doe")
|
||||
|
||||
err := testStore.Set("john1", val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
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)
|
||||
|
||||
result, err := testStore.Get("john1")
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, len(result))
|
||||
|
||||
result, err = testStore.Get("john2")
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, len(result))
|
||||
|
||||
keys, err = testStore.Keys()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, keys)
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Close(t *testing.T) {
|
||||
testStore := New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
require.Nil(t, testStore.Close())
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Conn(t *testing.T) {
|
||||
testStore := New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
require.True(t, testStore.Conn() != nil)
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Initalize_WithURL(t *testing.T) {
|
||||
testStoreUrl := New(Config{
|
||||
URL: "redis://localhost:6379", // Accepts URLs starting with Dragonfly redis
|
||||
})
|
||||
var (
|
||||
key = "clark"
|
||||
val = []byte("kent")
|
||||
)
|
||||
|
||||
err := testStoreUrl.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := testStoreUrl.Get(key)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, val, result)
|
||||
|
||||
err = testStoreUrl.Delete(key)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Nil(t, testStoreUrl.Close())
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Initalize_WithURL_TLS(t *testing.T) {
|
||||
cer, err := tls.LoadX509KeyPair("/home/runner/work/storage/storage/tls/client.crt", "/home/runner/work/storage/storage/tls/client.key")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
tlsCfg := &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
|
||||
InsecureSkipVerify: true,
|
||||
Certificates: []tls.Certificate{cer},
|
||||
CipherSuites: []uint16{
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
},
|
||||
}
|
||||
|
||||
testStoreUrl := New(Config{
|
||||
URL: "redis://localhost:6380", // Accepts URLs starting with Dragonfly redis
|
||||
TLSConfig: tlsCfg,
|
||||
})
|
||||
|
||||
var (
|
||||
key = "clark"
|
||||
val = []byte("kent")
|
||||
)
|
||||
|
||||
err = testStoreUrl.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := testStoreUrl.Get(key)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, val, result)
|
||||
|
||||
err = testStoreUrl.Delete(key)
|
||||
require.NoError(t, err)
|
||||
|
||||
keys, err := testStoreUrl.Keys()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, keys)
|
||||
|
||||
require.Nil(t, testStoreUrl.Close())
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Initalize_WithURL_TLS_Verify(t *testing.T) {
|
||||
cer, err := tls.LoadX509KeyPair("/home/runner/work/storage/storage/tls/client.crt", "/home/runner/work/storage/storage/tls/client.key")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
tlsCfg := &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
|
||||
InsecureSkipVerify: false,
|
||||
Certificates: []tls.Certificate{cer},
|
||||
CipherSuites: []uint16{
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
},
|
||||
}
|
||||
|
||||
testStoreUrl := New(Config{
|
||||
URL: "redis://localhost:6380", // Accepts URLs starting with Dragonfly redis
|
||||
TLSConfig: tlsCfg,
|
||||
})
|
||||
|
||||
var (
|
||||
key = "clark"
|
||||
val = []byte("kent")
|
||||
)
|
||||
|
||||
err = testStoreUrl.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := testStoreUrl.Get(key)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, val, result)
|
||||
|
||||
err = testStoreUrl.Delete(key)
|
||||
require.NoError(t, err)
|
||||
|
||||
keys, err := testStoreUrl.Keys()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, keys)
|
||||
|
||||
require.Nil(t, testStoreUrl.Close())
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Initalize_With_Secure_URL(t *testing.T) {
|
||||
testStoreUrl := New(Config{
|
||||
URL: "rediss://localhost:16380", // Accepts URLs starting with Dragonfly redis
|
||||
})
|
||||
|
||||
var (
|
||||
key = "clark"
|
||||
val = []byte("kent")
|
||||
)
|
||||
|
||||
err := testStoreUrl.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := testStoreUrl.Get(key)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, val, result)
|
||||
|
||||
err = testStoreUrl.Delete(key)
|
||||
require.NoError(t, err)
|
||||
|
||||
keys, err := testStoreUrl.Keys()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, keys)
|
||||
|
||||
require.Nil(t, testStoreUrl.Close())
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Universal_Addrs(t *testing.T) {
|
||||
// This should failover and create a Single Node connection.
|
||||
testStoreUniversal := New(Config{
|
||||
Addrs: []string{"localhost:6379"},
|
||||
})
|
||||
|
||||
var (
|
||||
key = "bruce"
|
||||
val = []byte("wayne")
|
||||
)
|
||||
|
||||
err := testStoreUniversal.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := testStoreUniversal.Get(key)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, val, result)
|
||||
|
||||
err = testStoreUniversal.Delete(key)
|
||||
require.NoError(t, err)
|
||||
|
||||
keys, err := testStoreUniversal.Keys()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, keys)
|
||||
|
||||
require.Nil(t, testStoreUniversal.Close())
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Universal_With_URL_Undefined(t *testing.T) {
|
||||
testStoreUniversal := New(Config{
|
||||
URL: "",
|
||||
Addrs: []string{"localhost:6379"},
|
||||
})
|
||||
|
||||
var (
|
||||
key = "bruce"
|
||||
val = []byte("wayne")
|
||||
)
|
||||
|
||||
err := testStoreUniversal.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := testStoreUniversal.Get(key)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, val, result)
|
||||
|
||||
err = testStoreUniversal.Delete(key)
|
||||
require.NoError(t, err)
|
||||
|
||||
keys, err := testStoreUniversal.Keys()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, keys)
|
||||
|
||||
require.Nil(t, testStoreUniversal.Close())
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Universal_With_URL_Defined(t *testing.T) {
|
||||
|
||||
testStoreUniversal := New(Config{
|
||||
URL: "redis://localhost:6379",
|
||||
Addrs: []string{"localhost:6355"},
|
||||
})
|
||||
|
||||
var (
|
||||
key = "bruce"
|
||||
val = []byte("wayne")
|
||||
)
|
||||
|
||||
err := testStoreUniversal.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := testStoreUniversal.Get(key)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, val, result)
|
||||
|
||||
err = testStoreUniversal.Delete(key)
|
||||
require.NoError(t, err)
|
||||
|
||||
keys, err := testStoreUniversal.Keys()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, keys)
|
||||
|
||||
require.Nil(t, testStoreUniversal.Close())
|
||||
}
|
||||
|
||||
func Test_Dragonfly_Cluster(t *testing.T) {
|
||||
testStoreUniversal := New(Config{
|
||||
Addrs: []string{
|
||||
"localhost:7000",
|
||||
"localhost:7001",
|
||||
"localhost:7002",
|
||||
"localhost:7003",
|
||||
"localhost:7004",
|
||||
"localhost:7005",
|
||||
},
|
||||
})
|
||||
|
||||
var (
|
||||
key = "bruce"
|
||||
val = []byte("wayne")
|
||||
)
|
||||
|
||||
err := testStoreUniversal.Set(key, val, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := testStoreUniversal.Get(key)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, val, result)
|
||||
|
||||
err = testStoreUniversal.Delete(key)
|
||||
require.NoError(t, err)
|
||||
|
||||
keys, err := testStoreUniversal.Keys()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, keys)
|
||||
|
||||
require.Nil(t, testStoreUniversal.Close())
|
||||
}
|
||||
|
||||
func Benchmark_Dragonfly_Set(b *testing.B) {
|
||||
testStore := New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
var err error
|
||||
for i := 0; i < b.N; i++ {
|
||||
err = testStore.Set("john", []byte("doe"), 0)
|
||||
}
|
||||
|
||||
require.NoError(b, err)
|
||||
}
|
||||
|
||||
func Benchmark_Dragonfly_Get(b *testing.B) {
|
||||
testStore := New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
err := testStore.Set("john", []byte("doe"), 0)
|
||||
require.NoError(b, err)
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err = testStore.Get("john")
|
||||
}
|
||||
|
||||
require.NoError(b, err)
|
||||
}
|
||||
|
||||
func Benchmark_Dragonfly_SetAndDelete(b *testing.B) {
|
||||
testStore := New(Config{
|
||||
Reset: true,
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
var err error
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = testStore.Set("john", []byte("doe"), 0)
|
||||
err = testStore.Delete("john")
|
||||
}
|
||||
|
||||
require.NoError(b, err)
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
module github.com/gofiber/storage/dragonfly
|
||||
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/gofiber/storage/redis/v3 v3.1.0
|
||||
github.com/redis/go-redis/v9 v9.5.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.10.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
@@ -1,23 +0,0 @@
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/gofiber/storage/redis/v3 v3.1.0 h1:URly7BB1TVz15vPy2R1Q6vBqI53cDiD6p5qKZX/hpog=
|
||||
github.com/gofiber/storage/redis/v3 v3.1.0/go.mod h1:HQ2wqleiIwb0Fbssq2T3v5DBiNlDZsCihWOuVmguIbg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=
|
||||
github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@@ -33,6 +33,12 @@ 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:
|
||||
|
||||
> **Note:** You can also use [DragonflyDB](https://dragonflydb.io/) as a Redis replacement.
|
||||
> Since DragonflyDB is fully compatible with the Redis API, you can use it exactly like Redis **without any code changes**.
|
||||
> [Example](#example-using-dragonflydb)
|
||||
|
||||
|
||||
```bash
|
||||
go mod init github.com/<user>/<repo>
|
||||
```
|
||||
@@ -194,3 +200,7 @@ var ConfigDefault = Config{
|
||||
SentinelPassword: "",
|
||||
}
|
||||
```
|
||||
|
||||
### Example: Using DragonflyDB
|
||||
> **Note:** You can use [DragonflyDB](https://dragonflydb.io/) in the same way as Redis.
|
||||
> Simply start a DragonflyDB server and configure it just like Redis. Then, call `New()` and use it exactly as you would with Redis.
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
)
|
||||
|
||||
// Config defines the config for storage.
|
||||
//
|
||||
// Dragonfly and Redis share the same config
|
||||
type Config struct {
|
||||
// Host name where the DB is hosted
|
||||
//
|
||||
|
@@ -13,7 +13,11 @@ type Storage struct {
|
||||
db redis.UniversalClient
|
||||
}
|
||||
|
||||
// New creates a new redis storage
|
||||
// New creates a new Redis storage instance.
|
||||
//
|
||||
// DragonflyDB is fully compatible with the Redis API, meaning it can be used as a drop-in replacement for Redis.
|
||||
//
|
||||
// Because of this compatibility, DragonflyDB can also be initialized through this function.
|
||||
func New(config ...Config) *Storage {
|
||||
// Set default config
|
||||
cfg := configDefault(config...)
|
||||
|
Reference in New Issue
Block a user