103 lines
2.1 KiB
Go
103 lines
2.1 KiB
Go
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
|
|
}
|