2026-05-30 19:26:27 +08:00
|
|
|
package redis
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"errors"
|
2026-06-10 12:04:34 +08:00
|
|
|
"strings"
|
2026-05-30 19:26:27 +08:00
|
|
|
|
2026-05-30 19:44:31 +08:00
|
|
|
"apigo.cc/go/id"
|
2026-05-30 19:26:27 +08:00
|
|
|
"apigo.cc/go/jsmod"
|
2026-06-20 22:08:56 +08:00
|
|
|
"apigo.cc/go/log"
|
2026-05-30 19:26:27 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
|
jsmod.Register("redis", map[string]any{
|
2026-06-10 12:04:34 +08:00
|
|
|
// 入口:支持别名获取,不传则默认 "default"
|
2026-06-21 10:34:06 +08:00
|
|
|
"Get": jsGet,
|
2026-06-10 12:04:34 +08:00
|
|
|
|
|
|
|
|
// 默认快捷调用 (面向 "default" 实例)
|
2026-06-21 10:34:06 +08:00
|
|
|
"Do": jsDo,
|
|
|
|
|
"MakeID": jsMakeID,
|
2026-05-30 19:26:27 +08:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-21 10:34:06 +08:00
|
|
|
func jsGet(ctx context.Context, name *string) (*jsRedis, error) {
|
|
|
|
|
target := "default"
|
|
|
|
|
if name != nil {
|
|
|
|
|
target = *name
|
|
|
|
|
}
|
|
|
|
|
rd := GetRedis(target, nil)
|
|
|
|
|
if rd.Error != nil {
|
|
|
|
|
return nil, jsmod.MakeError(rd.Error)
|
|
|
|
|
}
|
|
|
|
|
return &jsRedis{rd: rd, ctx: ctx}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func jsDo(ctx context.Context, cmd string, args ...any) (*Result, error) {
|
|
|
|
|
jr := getDefaultRedisForJS(ctx)
|
|
|
|
|
if jr.rd.Error != nil {
|
|
|
|
|
return nil, jsmod.MakeError(jr.rd.Error)
|
|
|
|
|
}
|
|
|
|
|
res := jr.Do(cmd, args...)
|
|
|
|
|
if res != nil && res.Error != nil {
|
|
|
|
|
return res, jsmod.MakeError(res.Error)
|
|
|
|
|
}
|
|
|
|
|
return res, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func jsMakeID(ctx context.Context, size int, forDB *string) string {
|
|
|
|
|
jr := getDefaultRedisForJS(ctx)
|
|
|
|
|
if jr.rd.Error != nil {
|
|
|
|
|
return id.MakeID(size)
|
|
|
|
|
}
|
|
|
|
|
return jr.MakeID(size, forDB)
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-30 19:26:27 +08:00
|
|
|
type jsRedis struct {
|
2026-05-30 19:44:31 +08:00
|
|
|
rd *Redis
|
|
|
|
|
ctx context.Context
|
|
|
|
|
idMaker *id.IDMaker
|
2026-05-30 19:26:27 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-20 22:08:56 +08:00
|
|
|
var defaultRedisForJS *jsRedis
|
|
|
|
|
|
|
|
|
|
func getDefaultRedisForJS(ctx context.Context) *jsRedis {
|
|
|
|
|
if defaultRedisForJS == nil {
|
2026-06-21 20:31:07 +08:00
|
|
|
var logger *log.Logger
|
|
|
|
|
if l := jsmod.Get(ctx, "Logger"); l != nil {
|
|
|
|
|
logger = l.(*log.Logger)
|
|
|
|
|
}
|
|
|
|
|
defaultRedisForJS = &jsRedis{rd: GetRedis("default", logger), ctx: ctx}
|
2026-06-20 22:08:56 +08:00
|
|
|
}
|
|
|
|
|
return defaultRedisForJS
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-30 19:44:31 +08:00
|
|
|
var errSafeMode = errors.New("redis operation is restricted in safe mode")
|
2026-05-30 19:26:27 +08:00
|
|
|
|
2026-06-21 20:31:07 +08:00
|
|
|
// 危险指令集,安全模式下禁止执行
|
|
|
|
|
var dangerousCommands = map[string]bool{
|
|
|
|
|
"FLUSHDB": true,
|
|
|
|
|
"FLUSHALL": true,
|
2026-06-10 12:04:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (jr *jsRedis) checkSafe(cmd string) error {
|
2026-05-30 19:26:27 +08:00
|
|
|
if jsmod.IsSafeMode(jr.ctx) {
|
2026-06-21 20:31:07 +08:00
|
|
|
if dangerousCommands[strings.ToUpper(cmd)] {
|
2026-06-10 12:04:34 +08:00
|
|
|
return errSafeMode
|
|
|
|
|
}
|
2026-05-30 19:26:27 +08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-30 19:44:31 +08:00
|
|
|
func (jr *jsRedis) Do(cmd string, args ...any) *Result {
|
2026-06-10 12:04:34 +08:00
|
|
|
if err := jr.checkSafe(cmd); err != nil {
|
2026-06-21 10:34:06 +08:00
|
|
|
return &Result{Error: jsmod.MakeError(err)}
|
|
|
|
|
}
|
|
|
|
|
res := jr.rd.Do(cmd, args...)
|
|
|
|
|
if res != nil && res.Error != nil {
|
|
|
|
|
resCopy := *res
|
|
|
|
|
resCopy.Error = jsmod.MakeError(res.Error)
|
|
|
|
|
return &resCopy
|
2026-05-30 19:26:27 +08:00
|
|
|
}
|
2026-06-21 10:34:06 +08:00
|
|
|
return res
|
2026-05-30 19:26:27 +08:00
|
|
|
}
|
2026-05-30 19:44:31 +08:00
|
|
|
|
2026-06-10 12:04:34 +08:00
|
|
|
// ID Generation
|
|
|
|
|
func (jr *jsRedis) MakeID(size int, forDB *string) string {
|
2026-05-30 19:44:31 +08:00
|
|
|
if jr.idMaker == nil {
|
|
|
|
|
jr.idMaker = NewIDMaker(jr.rd)
|
2026-05-30 19:26:27 +08:00
|
|
|
}
|
2026-06-10 12:04:34 +08:00
|
|
|
dbType := ""
|
|
|
|
|
if forDB != nil {
|
|
|
|
|
dbType = strings.ToLower(*forDB)
|
|
|
|
|
}
|
|
|
|
|
switch dbType {
|
|
|
|
|
case "mysql":
|
|
|
|
|
return jr.idMaker.GetForMysql(size)
|
|
|
|
|
case "postgres", "pg", "pgsql":
|
|
|
|
|
return jr.idMaker.GetForPostgreSQL(size)
|
|
|
|
|
default:
|
|
|
|
|
return jr.idMaker.Get(size)
|
|
|
|
|
}
|
2026-05-30 19:26:27 +08:00
|
|
|
}
|