You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
4.6 KiB
Go

package logic
import (
"context"
"joybuywork/internal/app"
"joybuywork/internal/plugins/jsonm"
"joybuywork/internal/repository/dao"
"joybuywork/internal/service/provider/fissionaction"
"joybuywork/internal/service/provider/operatelog"
"joybuywork/internal/utils/merr"
"joybuywork/proto/go_proto/workerr"
"fmt"
"time"
grds "github.com/go-redis/redis/v8"
"gits.branchcn.com/backend/microcode/plugins/derivative/lock"
"go-micro.dev/v4/errors"
)
type afterRunFunc func() (err error)
type afterRuns struct {
runs []afterRunFunc
errRuns []afterRunFunc
mustRuns []afterRunFunc
}
type errNotify struct {
eqCode []int32
neqCode map[int32]struct{}
}
type once struct {
key string
lock *lock.RedisLock
}
type Logic struct {
Context
cache *grds.Client
stop bool
afterRuns afterRuns
afterErr []error
once *once // 锁
errNotify errNotify // 错误通知
markPoint *fissionaction.MarkPoint // 埋点
ol *operatelog.OperateLog // 操作日志
errData jsonm.JsonM
}
// Dao 获取初始化的dao
func (l *Logic) Dao() *dao.Query {
return l.dao
}
// GetCache 获取cache
func (l *Logic) GetCache() *grds.Client {
return l.cache
}
// Init 初始化一个逻辑类
func (l *Logic) Init(ctx context.Context, opts ...Option) {
l.Context.Init(ctx, dao.Q, merr.NewBE(ctx))
l.cache = app.Redis.Cache
for _, opt := range opts {
opt(l)
}
}
// AddAfterRun 追加运行完之后要执行的方法
func (l *Logic) AddAfterRun(fn afterRunFunc) {
l.afterRuns.runs = append(l.afterRuns.runs, fn)
}
// AddErrRun 追加错误运行之后要执行的方法
func (l *Logic) AddErrRun(fn afterRunFunc) {
l.afterRuns.errRuns = append(l.afterRuns.errRuns, fn)
}
// AddMustRun 追加运行之后必须要执行的方法
func (l *Logic) AddMustRun(fn afterRunFunc) {
l.afterRuns.mustRuns = append(l.afterRuns.mustRuns, fn)
}
// After 执行逻辑后要处理的东西
func (l *Logic) After(err error) {
l.release()
// 必须执行
for _, fn := range l.afterRuns.mustRuns {
frr := fn()
if frr == nil {
continue
}
if l.stop {
return
}
l.afterErr = append(l.afterErr, frr)
}
// 出错了要执行的
if err != nil {
for _, fn := range l.afterRuns.errRuns {
frr := fn()
if frr == nil {
continue
}
if l.stop {
return
}
l.afterErr = append(l.afterErr, frr)
}
return
}
// 没有错误要执行的
for _, fn := range l.afterRuns.runs {
frr := fn()
if frr == nil {
continue
}
if l.stop {
return
}
l.afterErr = append(l.afterErr, frr)
}
if l.markPoint != nil {
l.markPoint.Push()
}
if l.ol != nil {
l.ol.InDB()
}
if l.fnTimer != nil {
l.fnTimer.Push()
}
return
}
// CacheSet 缓存设置
func (l *Logic) CacheSet(key string, value any, exp time.Duration) error {
return l.cacheDone(func() error {
return l.cache.Set(l.Ctx, key, value, exp).Err()
})
}
// CacheDel 删除缓存
func (l *Logic) CacheDel(keys ...string) error {
return l.cacheDone(func() error {
return l.cache.Del(l.Ctx, keys...).Err()
})
}
// 缓存操作
func (l *Logic) cacheDone(fn func() error) error {
if !l.withTran {
return fn()
}
l.AddAfterRun(func() error {
if err := fn(); err != nil {
return workerr.InternalServerError(err.Error())
}
return nil
})
return nil
}
// 锁操作
func (l *Logic) lock() (err error) {
//不需要锁,或者锁成功了
if l.once == nil || l.once.lock.SoftLock() {
return
}
return workerr.OnceLockError
}
// 解锁
func (l *Logic) release() {
if l.once != nil {
l.once.lock.Release()
}
return
}
// Before 执行之前
func (l *Logic) Before() (err error) {
//先锁任务
err = l.lock()
if err != nil {
return
}
return
}
// GetAfterErr 获取执行错误
func (l *Logic) GetAfterErr() []error {
return l.afterErr
}
func (l *Logic) Data() (data jsonm.JsonM) {
return l.errData
}
// PushErr 推送错误
func (l *Logic) PushErr(data jsonm.JsonM, err error) {
wrr, ok := errors.As(err)
if !ok {
app.Logger.Error(l.Ctx, fmt.Sprintf("逻辑处理未定义错误: %v, 数据: %s", err, data.ToString()))
return
}
if len(l.errNotify.eqCode) > 0 {
for _, v := range l.errNotify.eqCode {
if wrr.GetCode() == v {
app.Logger.Error(l.Ctx, fmt.Sprintf("逻辑处理错误: %v, 数据: %s", err, data.ToString()))
return
}
}
}
if len(l.errNotify.neqCode) > 0 {
if _, ok1 := l.errNotify.neqCode[wrr.GetCode()]; !ok1 {
app.Logger.Error(l.Ctx, fmt.Sprintf("逻辑处理错误: %v, 数据: %s", err, data.ToString()))
return
}
}
}
// MP 埋点
func (l *Logic) MP() *fissionaction.MarkPoint {
return l.markPoint
}
// OL 操作记录
func (l *Logic) OL() *operatelog.OperateLog {
return l.ol
}