Your Question

我想要通过注册中间件的方式实现对Gorm的限流器,但是我尝试了,实现Plugin接口并不能操作本次查询链路终止。

The document you expected this should be explained

// GormRateLimiter Gorm限流器
func GormRateLimiter(db *gorm.DB, r *rate.Limiter) {
    err := db.Callback().Query().Before("*").Register("RateLimitGormMiddleware", func(d *gorm.DB) {
        if !r.Allow() {
            d.AddError(GormToManyRequestError)
            global.Log.Error(GormToManyRequestError.Error())
            return
        }
    })
    if err != nil {
        panic(err)
    }
}

Expected answer

// 定义限流中间件结构体
type gormRateLimiter struct {
    limiter *rate.Limiter
}

func newGormLimiter(limiter *rate.Limiter) *gormRateLimiter {
    return &gormRateLimiter{limiter: limiter}
}

func (r *gormRateLimiter) Name() string {
    return "RateLimitMiddleware"
}

func (r *gormRateLimiter) Initialize(db *gorm.DB) (err error) {
    err = db.Callback().Query().Before("*").Register("RateLimitGormMiddleware", func(d *gorm.DB) {
        if !r.limiter.Allow() {
            d.AddError(GormToManyRequestError)
            global.Log.Error(GormToManyRequestError.Error())
            return
        }
    })
    return err
}

是不是应该把这种AOP方案做的更加完善和对开发者更友好一些呢?

Comment From: jinzhu

返回一下 Error 就好了,其它的Callback会判断有 error 不执行,不应该真正的 abort 防止事务未commit/rollback 等