Files
bl/cool/func.go

104 lines
2.6 KiB
Go
Raw Normal View History

2025-06-20 17:13:51 +08:00
package cool
import (
"time"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gstr"
)
type CoolFunc interface {
// Func handler
Func(ctx g.Ctx, param string) (err error)
// IsSingleton 是否单例,当为true时只能有一个任务在执行,在注意函数为计划任务时使用
IsSingleton() bool
// IsAllWorker 是否所有worker都执行
IsAllWorker() bool
}
// FuncMap 函数列表
var FuncMap = make(map[string]CoolFunc)
// RegisterFunc 注册函数
func RegisterFunc(name string, f CoolFunc) {
FuncMap[name] = f
}
// GetFunc 获取函数
func GetFunc(name string) CoolFunc {
return FuncMap[name]
}
// RunFunc 运行函数
func RunFunc(ctx g.Ctx, funcstring string) (err error) {
funcName := gstr.SubStr(funcstring, 0, gstr.Pos(funcstring, "("))
funcParam := gstr.SubStr(funcstring, gstr.Pos(funcstring, "(")+1, gstr.Pos(funcstring, ")")-gstr.Pos(funcstring, "(")-1)
if _, ok := FuncMap[funcName]; !ok {
err = gerror.New("函数不存在:" + funcName)
return
}
if !FuncMap[funcName].IsAllWorker() {
// 检查当前是否为主进程, 如果不是主进程, 则不执行
if ProcessFlag != CacheManager.MustGetOrSet(ctx, "cool:masterflag", ProcessFlag, 60*time.Second).String() {
g.Log().Debug(ctx, "当前进程不是主进程, 不执行单例函数", funcName)
return
}
}
err = FuncMap[funcName].Func(ctx, funcParam)
return
}
// ClusterRunFunc 集群运行函数,如果是单机模式, 则直接运行函数
func ClusterRunFunc(ctx g.Ctx, funcstring string) (err error) {
if IsRedisMode {
conn, err := g.Redis("cool").Conn(ctx)
if err != nil {
return err
}
defer conn.Close(ctx)
_, err = conn.Do(ctx, "publish", "cool:func", funcstring)
return err
} else {
return RunFunc(ctx, funcstring)
}
}
// ListenFunc 监听函数
func ListenFunc(ctx g.Ctx) {
if IsRedisMode {
conn, err := g.Redis("cool").Conn(ctx)
if err != nil {
panic(err)
}
defer conn.Close(ctx)
_, err = conn.Do(ctx, "subscribe", "cool:func")
if err != nil {
panic(err)
}
for {
data, err := conn.Receive(ctx)
if err != nil {
g.Log().Error(ctx, err)
time.Sleep(10 * time.Second)
continue
}
if data != nil {
dataMap := data.MapStrStr()
if dataMap["Kind"] == "subscribe" {
continue
}
if dataMap["Channel"] == "cool:func" {
g.Log().Debug(ctx, "执行函数", dataMap["Payload"])
err := RunFunc(ctx, dataMap["Payload"])
if err != nil {
g.Log().Error(ctx, "执行函数失败", err)
}
}
}
}
} else {
panic(gerror.New("集群模式下, 请使用Redis作为缓存"))
}
}