增加 redis client
This commit is contained in:
217
middleware/redis/clent.go
Normal file
217
middleware/redis/clent.go
Normal file
@ -0,0 +1,217 @@
|
||||
// Package redis ...
|
||||
//
|
||||
// Description : redis 客户端
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 2021-02-27 4:49 下午
|
||||
package redis
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-developer/gopkg/convert"
|
||||
|
||||
"github.com/go-developer/gopkg/logger"
|
||||
redisInstance "github.com/go-redis/redis/v8"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Options 连接选项,百分之百兼容第三方包的选项
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 4:57 下午 2021/2/27
|
||||
type Options struct {
|
||||
Conf *redisInstance.Options // 第三方包的选项
|
||||
Logger *LoggerConfig // 日志的配置
|
||||
LoggerFieldConfig *LogFieldConfig // 日志字段的配置
|
||||
}
|
||||
|
||||
// RealClient 包装好的 redis client
|
||||
type RealClient struct {
|
||||
Flag string // redis 标识
|
||||
Instance *redisInstance.Client // redis 实例
|
||||
Logger *zap.Logger // 日志实例
|
||||
LoggerFieldConfig *LogFieldConfig // 日志字段的配置
|
||||
}
|
||||
|
||||
// NewClient 获取redis client实例
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 5:05 下午 2021/2/27
|
||||
func NewClient(config map[string]Options) (*Client, error) {
|
||||
c := &Client{
|
||||
instanceTable: make(map[string]*RealClient),
|
||||
confTable: config,
|
||||
}
|
||||
return c, c.init()
|
||||
}
|
||||
|
||||
// Client 包装的redis client
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 4:52 下午 2021/2/27
|
||||
type Client struct {
|
||||
instanceTable map[string]*RealClient // redis 实例
|
||||
confTable map[string]Options // redis 配置
|
||||
}
|
||||
|
||||
// init 初始化redis连接
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 5:31 下午 2021/2/27
|
||||
func (c *Client) init() error {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
for flag, conf := range c.confTable {
|
||||
c.instanceTable[flag] = &RealClient{
|
||||
Flag: flag,
|
||||
Instance: redisInstance.NewClient(conf.Conf),
|
||||
Logger: nil,
|
||||
LoggerFieldConfig: conf.LoggerFieldConfig,
|
||||
}
|
||||
if c.instanceTable[flag].Logger, err = c.getLogger(conf.Logger); nil != err {
|
||||
return LoggerInitFail(flag, err)
|
||||
}
|
||||
if nil == c.instanceTable[flag].LoggerFieldConfig {
|
||||
c.instanceTable[flag].LoggerFieldConfig = &LogFieldConfig{
|
||||
Message: "",
|
||||
UsedTimeField: "",
|
||||
CommandField: "",
|
||||
FlagField: "",
|
||||
}
|
||||
}
|
||||
if len(c.instanceTable[flag].LoggerFieldConfig.Message) == 0 {
|
||||
c.instanceTable[flag].LoggerFieldConfig.Message = defaultMessage
|
||||
}
|
||||
if len(c.instanceTable[flag].LoggerFieldConfig.CommandField) == 0 {
|
||||
c.instanceTable[flag].LoggerFieldConfig.CommandField = defaultCommandField
|
||||
}
|
||||
if len(c.instanceTable[flag].LoggerFieldConfig.UsedTimeField) == 9 {
|
||||
c.instanceTable[flag].LoggerFieldConfig.UsedTimeField = defaultUsedTimeField
|
||||
}
|
||||
if len(c.instanceTable[flag].LoggerFieldConfig.FlagField) == 0 {
|
||||
c.instanceTable[flag].LoggerFieldConfig.FlagField = defaultFlagField
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getLogger ...
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 7:07 下午 2021/2/27
|
||||
func (c *Client) getLogger(conf *LoggerConfig) (*zap.Logger, error) {
|
||||
if nil == conf || nil == conf.SplitConfig {
|
||||
return nil, nil
|
||||
}
|
||||
return logger.NewLogger(
|
||||
conf.LoggerLevel,
|
||||
conf.ConsoleOutput,
|
||||
conf.Encoder,
|
||||
conf.SplitConfig,
|
||||
)
|
||||
}
|
||||
|
||||
// GetRedisClient 获取redis实例
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 5:16 下午 2021/2/27
|
||||
func (c *Client) GetRedisClient(flag string) (*RealClient, error) {
|
||||
redisClient, exist := c.instanceTable[flag]
|
||||
if !exist {
|
||||
return nil, FlagNotFound(flag)
|
||||
}
|
||||
return redisClient, nil
|
||||
}
|
||||
|
||||
// log 记录redis请求日志
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 8:52 下午 2021/2/27
|
||||
func (c *Client) log(ctx *Context, realClient *RealClient, cmdResult redisInstance.Cmder, startTime int64, finishTime int64) {
|
||||
if nil == realClient || nil == realClient.Logger {
|
||||
return
|
||||
}
|
||||
realClient.Logger.Info(
|
||||
"执行redis命令日志记录",
|
||||
zap.Any(ctx.RequestIDField, ctx.RequestID), // 上下文串联的requestID
|
||||
zap.String(realClient.LoggerFieldConfig.CommandField, cmdResult.String()), // 执行的命令
|
||||
zap.Float64(realClient.LoggerFieldConfig.UsedTimeField, float64(finishTime-startTime)/1e6), // 耗时,单位: ms
|
||||
zap.Error(cmdResult.Err()), // 异常信息
|
||||
)
|
||||
}
|
||||
|
||||
// CommandProxy 执行命令的代理
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 9:41 下午 2021/2/27
|
||||
func (c *Client) CommandProxy(ctx *Context, flag string, cmd string, param ...interface{}) (interface{}, error) {
|
||||
var (
|
||||
realClient *RealClient
|
||||
err error
|
||||
)
|
||||
if len(cmd) == 0 {
|
||||
return nil, EmptyCmd()
|
||||
}
|
||||
if realClient, err = c.GetRedisClient(ctx.Flag); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
redisCmd := append([]interface{}{cmd}, param...)
|
||||
startTime := time.Now().Unix()
|
||||
cmdResult := realClient.Instance.Do(ctx.Ctx, redisCmd...)
|
||||
go c.log(ctx, realClient, cmdResult, startTime, time.Now().UnixNano())
|
||||
return cmdResult.Val(), cmdResult.Err()
|
||||
}
|
||||
|
||||
// CommandProxyWithReceiver 执行命令,并解析结果
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 10:00 下午 2021/2/27
|
||||
func (c *Client) CommandProxyWithReceiver(ctx *Context, flag string, receiver interface{}, cmd string, param ...interface{}) error {
|
||||
if nil == receiver {
|
||||
return ReceiverISNIL()
|
||||
}
|
||||
var (
|
||||
err error
|
||||
result interface{}
|
||||
)
|
||||
|
||||
if result, err = c.CommandProxy(ctx, flag, cmd, param); nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
return ResultConvertFail(convert.ConvertAssign(receiver, result))
|
||||
}
|
||||
|
||||
// Set set 命令
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 8:18 下午 2021/2/27
|
||||
func (c *Client) Set(ctx *Context, key string, value interface{}, expiration time.Duration) error {
|
||||
var (
|
||||
realClient *RealClient
|
||||
err error
|
||||
statusCmd *redisInstance.StatusCmd
|
||||
)
|
||||
if realClient, err = c.GetRedisClient(ctx.Flag); nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
startTime := time.Now().UnixNano()
|
||||
statusCmd = realClient.Instance.Set(ctx.Ctx, key, value, expiration)
|
||||
go c.log(ctx, realClient, statusCmd, startTime, time.Now().UnixNano())
|
||||
return statusCmd.Err()
|
||||
}
|
141
middleware/redis/context.go
Normal file
141
middleware/redis/context.go
Normal file
@ -0,0 +1,141 @@
|
||||
// Package redis...
|
||||
//
|
||||
// Description : redis...
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 2021-02-27 8:22 下午
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-developer/gopkg/easymap"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
// 默认的 request_id 字段名
|
||||
defaultRequestIDField = "request_id"
|
||||
// 默认的message
|
||||
defaultMessage = "执行redis命令日志记录"
|
||||
// 耗时字段
|
||||
defaultUsedTimeField = "used_field"
|
||||
// 默认的命令字段
|
||||
defaultCommandField = "command"
|
||||
// 默认记录 redis标识的字段
|
||||
defaultFlagField = "flag"
|
||||
)
|
||||
|
||||
// Context 请求上下文
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 8:25 下午 2021/2/27
|
||||
type Context struct {
|
||||
Flag string // 哪个模块的上下文
|
||||
Ctx context.Context // ctx
|
||||
GinCtx *gin.Context // http 请求绑定的gin.context
|
||||
RequestIDField string // requestID 字段名
|
||||
RequestID string // requestID 此字段有值, 直接使用此值,无值, 去GinCtx 中读取 RequestIDField
|
||||
Extra easymap.EasyMap // 扩展信息
|
||||
}
|
||||
|
||||
// NewContext 生成一个上下文
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 8:26 下午 2021/2/27
|
||||
func NewContext(flag string, of ...SetContextFunc) *Context {
|
||||
ctx := &Context{
|
||||
Flag: flag,
|
||||
Ctx: nil,
|
||||
GinCtx: nil,
|
||||
RequestIDField: "",
|
||||
RequestID: "",
|
||||
Extra: nil,
|
||||
}
|
||||
for _, f := range of {
|
||||
f(ctx)
|
||||
}
|
||||
if nil == ctx.Ctx {
|
||||
ctx.Ctx = context.Background()
|
||||
}
|
||||
if len(ctx.RequestIDField) == 0 {
|
||||
ctx.RequestIDField = defaultRequestIDField
|
||||
}
|
||||
if nil == ctx.Extra {
|
||||
ctx.Extra = easymap.NewNormal(true)
|
||||
}
|
||||
// requestID 填充
|
||||
if len(ctx.RequestID) == 0 {
|
||||
// 先从 gin 读
|
||||
if nil != ctx.Ctx {
|
||||
ctx.RequestID = ctx.GinCtx.GetString(ctx.RequestIDField)
|
||||
}
|
||||
// 再从extra读取
|
||||
if len(ctx.RequestID) == 0 {
|
||||
ctx.RequestID, _ = ctx.Extra.GetString(ctx.RequestID)
|
||||
}
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
// SetContextFunc 设置context参数
|
||||
type SetContextFunc func(rc *Context)
|
||||
|
||||
// WithCtx 设置context
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 8:30 下午 2021/2/27
|
||||
func WithCtx(ctx context.Context) SetContextFunc {
|
||||
return func(rc *Context) {
|
||||
rc.Ctx = ctx
|
||||
}
|
||||
}
|
||||
|
||||
// WithGinCtx 设置gin上下文
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 8:34 下午 2021/2/27
|
||||
func WithGinCtx(ginCtx *gin.Context) SetContextFunc {
|
||||
return func(rc *Context) {
|
||||
rc.GinCtx = ginCtx
|
||||
}
|
||||
}
|
||||
|
||||
// WithExtra 设置扩展信息
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 8:36 下午 2021/2/27
|
||||
func WithExtra(extra easymap.EasyMap) SetContextFunc {
|
||||
return func(rc *Context) {
|
||||
rc.Extra = extra
|
||||
}
|
||||
}
|
||||
|
||||
// WithRequestIDField 设置request_id参数名
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 8:41 下午 2021/2/27
|
||||
func WithRequestIDField(requestIDField string) SetContextFunc {
|
||||
return func(rc *Context) {
|
||||
rc.RequestIDField = requestIDField
|
||||
}
|
||||
}
|
||||
|
||||
// WithRequestID ...
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 8:42 下午 2021/2/27
|
||||
func WithRequestID(requestID string) SetContextFunc {
|
||||
return func(rc *Context) {
|
||||
rc.RequestID = requestID
|
||||
}
|
||||
}
|
64
middleware/redis/error.go
Normal file
64
middleware/redis/error.go
Normal file
@ -0,0 +1,64 @@
|
||||
// Package redis...
|
||||
//
|
||||
// Description : redis...
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 2021-02-27 5:13 下午
|
||||
package redis
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
|
||||
// FlagNotFound flag不存在异常
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 5:15 下午 2021/2/27
|
||||
func FlagNotFound(flag string) error {
|
||||
return errors.Errorf("标识为 %s 的redis未找到", flag)
|
||||
}
|
||||
|
||||
// LoggerInitFail 日志初始化失败
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 7:30 下午 2021/2/27
|
||||
func LoggerInitFail(flag string, err error) error {
|
||||
return errors.Wrapf(err, "标识为 %s 的redis日志初始化失败", flag)
|
||||
}
|
||||
|
||||
// EmptyCmd 未设置要执行的命令
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 9:46 下午 2021/2/27
|
||||
func EmptyCmd() error {
|
||||
return errors.Errorf("未设置要执行的命令")
|
||||
}
|
||||
|
||||
// CommandExecuteFail 命令执行失败
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 9:58 下午 2021/2/27
|
||||
func CommandExecuteFail(err error) error {
|
||||
return errors.Wrapf(err, "命令执行异常")
|
||||
}
|
||||
|
||||
// ReceiverISNIL 数据接收者是空指针
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 10:05 下午 2021/2/27
|
||||
func ReceiverISNIL() error {
|
||||
return errors.Errorf("数据接收者指针为空")
|
||||
}
|
||||
|
||||
// ResultConvertFail 数据结果解析失败
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 10:07 下午 2021/2/27
|
||||
func ResultConvertFail(err error) error {
|
||||
return errors.Wrapf(err, "数据结果解析失败")
|
||||
}
|
39
middleware/redis/logger.go
Normal file
39
middleware/redis/logger.go
Normal file
@ -0,0 +1,39 @@
|
||||
// Package redis...
|
||||
//
|
||||
// Description : redis...
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 2021-02-27 5:26 下午
|
||||
package redis
|
||||
|
||||
import (
|
||||
"github.com/go-developer/gopkg/logger"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// LoggerConfig 日志配置
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 5:26 下午 2021/2/27
|
||||
type LoggerConfig struct {
|
||||
LoggerPath string
|
||||
LoggerFile string
|
||||
LoggerLevel zapcore.Level
|
||||
ConsoleOutput bool
|
||||
Encoder zapcore.Encoder
|
||||
SplitConfig *logger.RotateLogConfig
|
||||
}
|
||||
|
||||
// LogFieldConfig 日志字段配置
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 9:20 下午 2021/2/27
|
||||
type LogFieldConfig struct {
|
||||
Message string
|
||||
UsedTimeField string
|
||||
CommandField string
|
||||
FlagField string
|
||||
}
|
Reference in New Issue
Block a user