74 lines
1.8 KiB
Go
Executable File
74 lines
1.8 KiB
Go
Executable File
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"reflect"
|
|
"sync"
|
|
"time"
|
|
|
|
"git.wishpal.cn/wishpal_ironfan/xframe/component/logger"
|
|
"git.wishpal.cn/wishpal_ironfan/xframe/component/queue/asynq/internal/rate"
|
|
"git.wishpal.cn/wishpal_ironfan/xframe/component/queue/asynq/internal/utils"
|
|
"git.wishpal.cn/wishpal_ironfan/xframe/component/storage/redisrate"
|
|
"github.com/hibiken/asynq"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var handlers = map[string]IHandler{}
|
|
var lock sync.RWMutex
|
|
|
|
type IHandler interface {
|
|
NewParam() (reflect.Value, error)
|
|
Call(ctx context.Context, v reflect.Value, p reflect.Value) error
|
|
}
|
|
|
|
func getHandler(typ string) (IHandler, bool) {
|
|
typ = utils.TrimUnifiedPattern(typ)
|
|
lock.RLock()
|
|
h, ok := handlers[typ]
|
|
lock.RUnlock()
|
|
return h, ok
|
|
}
|
|
|
|
func GenHandlerFunc(ctrl *rate.RateCtrl, key string, limitPerSecond int) func(ctx context.Context, task *asynq.Task) error {
|
|
return func(ctx context.Context, task *asynq.Task) error {
|
|
err := ctrl.Allow(ctx, key, redisrate.Limit{
|
|
Rate: limitPerSecond,
|
|
Burst: limitPerSecond,
|
|
Period: time.Second,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return handleFunc(ctx, task)
|
|
}
|
|
}
|
|
|
|
func handleFunc(ctx context.Context, task *asynq.Task) (err error) {
|
|
start := time.Now()
|
|
defer func(ctx context.Context) {
|
|
if err == nil {
|
|
logger.WithContext(ctx).Infof("xcasynq handlefunc, use %v, task type %s, id %s, payload %s",
|
|
time.Since(start), task.Type(), task.ResultWriter().TaskID(), task.Payload())
|
|
}
|
|
}(ctx)
|
|
|
|
f, ok := getHandler(task.Type())
|
|
if !ok {
|
|
return errors.Errorf("no handler for %s", task.Type())
|
|
}
|
|
param, err := f.NewParam()
|
|
if err != nil {
|
|
err = errors.Wrap(err, "NewParam")
|
|
return err
|
|
}
|
|
err = json.Unmarshal(task.Payload(), param.Interface())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
p := reflect.ValueOf(f).FieldByName("Processor")
|
|
return f.Call(ctx, param, p)
|
|
}
|