package hashid import ( "context" "joybuywork/internal/app" "joybuywork/internal/consts/ckey" "fmt" "gorm.io/gen/field" "time" ) type IDbId interface { TableName() string GetFieldByName(fieldName string) (field.OrderExpr, bool) } // IncrDbId 借助redis来做自增主键 func IncrDbId(ctx context.Context, table IDbId, pks ...string) (id int64, err error) { key := fmt.Sprintf("joybuywork:dbid:%s", table.TableName()) defer func() { if err != nil { return } id, err = app.Redis.Incr(ctx, key) }() exist, _ := app.Redis.Exists(ctx, key) if exist { return } lc := app.NewFollower(ctx, ckey.ForLock(key)).Lock() defer lc.Release() if lc.Error() != nil { err = lc.Error() return } exist, _ = app.Redis.Exists(ctx, key) if exist { return } var MaxId struct { Id int64 `json:"id"` } var pkField = "id" for _, pk := range pks { _, ok := table.GetFieldByName(pk) if ok { pkField = pk break } } err = app.DB.Client.WithContext(ctx).Table(table.TableName()).Select(fmt.Sprintf("MAX(%s) as id", pkField)).Scan(&MaxId).Error if err != nil { return } err = app.Redis.Cache.IncrBy(ctx, key, MaxId.Id).Err() app.Redis.Cache.ExpireAt(ctx, key, time.Now().AddDate(0, 6, 0)) return }