package svc import ( "bytes" "errors" "math/rand" "net/rpc" "sync" "github.com/globalsign/mgo" "github.com/globalsign/mgo/bson" "mongo.games.com/game/dbproxy/mongo" "mongo.games.com/game/model" ) /* 邀请码生成规则 1. 邀请码长度为8位,由数字和字母组成 2. 0-9,a-z,A-Z随机组合 */ var ( InviteCodeDBName = "user" InviteCodeCollName = "user_icode" InviteCodeColError = errors.New("InviteCode collection open failed") InviteCodeMutex = sync.Mutex{} ) func InviteCodeCollection(plt string) *mongo.Collection { s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, InviteCodeDBName) if s != nil { c, first := s.DB().C(InviteCodeCollName) if first { c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Unique: true, Background: true, Sparse: true}) c.EnsureIndex(mgo.Index{Key: []string{"code"}, Unique: true, Background: true, Sparse: true}) } return c } return nil } func GetInviteCode(plt string, snid int32) (string, error) { c := InviteCodeCollection(plt) if c == nil { return "", InviteCodeColError } col := new(model.InviteCode) err := c.Find(bson.M{"snid": snid}).One(col) notFound := errors.Is(err, mgo.ErrNotFound) if err != nil && !notFound { return "", err } if notFound || col.Code == "" { InviteCodeMutex.Lock() defer InviteCodeMutex.Unlock() // 创建 var n int for i := 0; i < 100; i++ { code := getInviteCode(8) n, err = c.Find(bson.M{"code": code}).Count() if err != nil { return "", err } if n > 0 { continue } col.Id = bson.NewObjectId() col.SnId = snid col.Code = code _, err = c.Upsert(bson.M{"snid": snid}, col) break } } return col.Code, err } const StringList = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" func getInviteCode(n int) string { b := bytes.NewBuffer(make([]byte, 0, n)) for i := 0; i < n; i++ { b.WriteByte(StringList[rand.Intn(len(StringList))]) } return b.String() } type InviteCodeSvc struct { } func (i *InviteCodeSvc) GetSnIdByCode(req *model.InviteSnIdReq, ret *model.InviteSnIdRet) error { c := InviteCodeCollection(req.Platform) if c == nil { return InviteCodeColError } col := new(model.InviteCode) err := c.Find(bson.M{"code": req.Code}).One(col) if err != nil && !errors.Is(err, mgo.ErrNotFound) { return err } ret.SnId = col.SnId return nil } func GetCodeBySnId(platform string, snid int32) (string, error) { c := InviteCodeCollection(platform) if c == nil { return "", InviteCodeColError } col := new(model.InviteCode) err := c.Find(bson.M{"snid": snid}).One(col) if err != nil && !errors.Is(err, mgo.ErrNotFound) { return "", err } return col.Code, err } func init() { rpc.Register(new(InviteCodeSvc)) }