add model t_uid
This commit is contained in:
parent
6f7e10aecb
commit
d13a1e4292
139
model/t_uid/t_uid.go
Normal file
139
model/t_uid/t_uid.go
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user