add model t_uid

This commit is contained in:
bryanqiu 2022-12-02 11:49:26 +08:00
parent 6f7e10aecb
commit d13a1e4292

139
model/t_uid/t_uid.go Normal file
View File

@ -0,0 +1,139 @@
package t_uid
import (
"fmt"
"time"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"qoobing.com/gomod/log"
)
type t_uid struct {
F_id int64 `gorm:"column:F_id;primaryKey"` // ID范围id
F_pid int64 `gorm:"column:F_pid"` // ID范围的前一个范围id
F_type string `gorm:"column:F_type"` // ID类型
F_prefix string `gorm:"column:F_prefix"` // ID前缀(type+prefix+range_start唯一)
F_range_start int64 `gorm:"column:F_range_start"` // ID范围的起始id
F_range_length int `gorm:"column:F_range_length"` // ID范围的长度
F_range_owner string `gorm:"column:F_range_owner"` // ID范围的拥有者一般是机器id
F_create_time time.Time `gorm:"column:F_create_time"` // 记录创建时间
}
type typeInfo struct {
Name string //type name
RangeLength int //Range length
}
var table string = "t_uid" // id range table name
var typeSupported = map[string]typeInfo{
"TXID": typeInfo{
Name: "TXID",
RangeLength: 3,
},
"USERID": typeInfo{
Name: "USERID",
RangeLength: 3,
},
}
func Init(tablename string) {
table = tablename
}
func (id *t_uid) TableName() string {
return table
}
func (id *t_uid) BeforeCreate(db *gorm.DB) error {
id.F_create_time = time.Now()
return nil
}
func (id *t_uid) BeforeUpdate(db *gorm.DB) (err error) {
return nil
}
func CreateIdRange(db *gorm.DB, typ, prefix string) (start int64, length int, err error) {
// Step 1. init variables
if t, ok := typeSupported[typ]; !ok {
panic(fmt.Sprintf("id type [%s] not supported yet", typ))
} else {
length = t.RangeLength
}
var (
lock = clause.Locking{Strength: "UPDATE"}
root = t_uid{}
rootcond = map[string]interface{}{
"F_type": fmt.Sprintf("%s#ROOT", typ),
"F_prefix": prefix,
"F_pid": 0,
}
rootattr = map[string]interface{}{
"F_range_start": -length,
"F_range_length": length,
"F_range_owner": "0",
}
selfid = "TODO"
)
// Step 2. get lastid && lock root(type+prefix)
var tx = db.Begin()
var txsuccess = false
defer func() {
if !txsuccess {
tx.Rollback()
}
}()
txr := tx.Clauses(lock).
Where(rootcond).
Attrs(rootattr).
FirstOrCreate(&root)
if txr.Error != nil {
return 0, 0, txr.Error
}
if root.F_range_owner == "0" {
// for new created root we set owner to itself.
root.F_range_owner = fmt.Sprintf("%d", root.F_id)
}
log.PrintPretty("root:", root)
// Step 3. insert new range. [can DELETE this for perfermance]
var newrange = t_uid{
F_type: typ,
F_prefix: prefix,
F_range_start: root.F_range_start + int64(length),
F_range_length: length,
F_range_owner: selfid,
}
if n, e := fmt.Sscanf(root.F_range_owner, "%d", &newrange.F_pid); e != nil {
log.Debugf("sscanf F_range_owner(%s) failed: '%s'", root.F_range_owner, e)
return 0, 0, fmt.Errorf("range_owner error")
} else if n != 1 {
log.Debugf("sscanf F_range_owner(%s) failed: n=%d", root.F_range_owner, n)
return 0, 0, fmt.Errorf("range_owner error")
}
if txr := tx.Create(&newrange); txr.Error != nil {
log.PrintPretty("newrange:", newrange)
return 0, 0, txr.Error
}
// Step 4. update root
root.F_range_start = newrange.F_range_start
root.F_range_length = newrange.F_range_length
root.F_range_owner = fmt.Sprintf("%d", newrange.F_id)
if txr := tx.Save(&root); txr.Error != nil {
return 0, 0, txr.Error
}
// Step 5. commit and return
if txr := tx.Commit(); txr.Error != nil {
return 0, 0, txr.Error
}
txsuccess = true
start = newrange.F_range_start
length = newrange.F_range_length
log.Infof("create range success:(%s, %s, %d, %d)", typ, prefix, start, length)
return start, length, nil
}