package mongos import ( "context" "time" "videoweb/pub/models/utils" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" ) const notFindMsg = "mongo: no documents in result" type lid struct { db *Collection // 数据库连接 businessId string // 业务id ch chan int64 // id缓冲池 min, max int64 // id段最小值,最大值 } // newLid 创建一个lid,db:数据库连接;businessId:业务id;len:缓冲池大小 func newLid(db *Collection, businessId string, len int) (*lid, error) { lid := lid{ db: db, businessId: businessId, ch: make(chan int64, len), } go lid.productId() return &lid, nil } // Get 获取自增id func (l *lid) Get() int64 { return <-l.ch } // productId 生产id func (l *lid) productId() { l.reset() for { if l.min >= l.max { l.reset() } l.min++ l.ch <- l.min } } // reset 不断尝试从数据库获取,直到成功 func (l *lid) reset() { for { err := l.getFromDB() if err == nil { return } time.Sleep(time.Second) continue } } func (l *lid) getFromDB() error { var ( max_id int64 step int64 //idModel IdModel idModel utils.GenerateId ) businessIdfilter := bson.M{utils.FN.GenerateId.BusinessId: l.businessId} txErr := Shop.Transaction(context.Background(), func(sctx mongo.SessionContext) (err error) { err = l.db.FindOneEx(sctx, &idModel, businessIdfilter) if err != nil { if err == mongo.ErrNoDocuments { idModel.MaxId = 10000 _, err = l.db.InsertOne(sctx, bson.M{ utils.FN.GenerateId.BusinessId: l.businessId, utils.FN.GenerateId.MaxId: 0, utils.FN.GenerateId.Step: 10, utils.FN.GenerateId.Desc: "id自增器", utils.FN.GenerateId.CreateAt: time.Now(), utils.FN.GenerateId.UpdateAt: time.Now()}) if err != nil { return } } else { return } } max_id = idModel.MaxId step = idModel.Step _, err = l.db.UpdateOne(sctx, businessIdfilter, bson.M{"$set": bson.M{utils.FN.GenerateId.MaxId: max_id + step}}) if err != nil { return } l.min = max_id l.max = max_id + step return }) return txErr }