Files
stat_center/common/genId/lid/lid.go
T
2026-05-20 16:13:58 +08:00

103 lines
2.3 KiB
Go

package lid
import (
"context"
"stat/common/mongos"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
const notFindMsg = "mongo: no documents in result"
type IdModel struct {
BusinessId string `bson:"business_id"` //业务id
Step int64 `bson:"step"` //步长
MaxId int64 `bson:"max_id"` //最大id
Description string `bson:"description"` //描述
CreatedAt time.Time `bson:"createdAt"` //创建时间
UpdatedAt time.Time `bson:"updatedAt"` //更改时间
}
type Lid struct {
db *mongo.Collection // 数据库连接
businessId string // 业务id
ch chan int64 // id缓冲池
min, max int64 // id段最小值,最大值
}
// NewLid 创建一个lid,db:数据库连接;businessId:业务id;len:缓冲池大小
func NewLid(db *mongo.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
}
}
// getFromDB 从数据库获取id段
func (l *Lid) getFromDB() error {
var (
maxId int64
step int64
idModel IdModel
)
txErr := mongos.Transaction(context.Background(), func(sctx mongo.SessionContext) (err error) {
err = l.db.FindOne(sctx, bson.M{"business_id": l.businessId}).Decode(&idModel)
if err != nil {
if err.Error() == notFindMsg {
_, err = l.db.InsertOne(sctx, bson.M{"business_id": l.businessId, "max_id": 0, "step": 10, "description": "id自增器", "createdAt": time.Now(), "updatedAt": time.Now()})
if err != nil {
return
}
} else {
return
}
}
maxId = idModel.MaxId
step = idModel.Step
_, err = l.db.UpdateOne(sctx, bson.M{"business_id": l.businessId}, bson.M{"$set": bson.M{"max_id": maxId + step}})
if err != nil {
return
}
l.min = maxId
l.max = maxId + step
return
})
return txErr
}