fix(idgen): retry snowflake generation and error on negative ID

NextUint64ID now retries up to 3 times when Int64() is negative, then
returns an error instead of 0 or Fatalf. All call sites propagate the
error to avoid GORM omitting zero-value primary keys.
This commit is contained in:
ryan
2026-06-17 13:08:00 +08:00
parent a27113feb2
commit 92dc6a59c0
11 changed files with 145 additions and 44 deletions
+1
View File
@@ -5,6 +5,7 @@ package model
const (
errRegistrationDisabled = "注册已关闭"
errInvalidUserID = "用户 ID 生成失败"
errDatabaseNotInitialized = "database not initialized"
errUsernameExists = "用户名已存在"
errEmailAlreadyBound = "该邮箱已被其他账号绑定"
+5 -1
View File
@@ -60,7 +60,11 @@ func (TaskExecution) TableName() string {
// CreateTaskExecution 创建任务执行记录
func CreateTaskExecution(ctx context.Context, execution *TaskExecution) error {
execution.ID = idgen.NextUint64ID()
id, err := idgen.NextUint64ID()
if err != nil {
return err
}
execution.ID = id
return db.DB(ctx).Create(execution).Error
}
+22 -2
View File
@@ -12,6 +12,7 @@ import (
"time"
"github.com/Rain-kl/Wavelet/internal/common"
"github.com/Rain-kl/Wavelet/internal/db/idgen"
"github.com/Rain-kl/Wavelet/pkg/util"
"gorm.io/gorm"
)
@@ -44,7 +45,7 @@ func (u *OAuthUserInfo) GetID() uint64 {
// User 用户表实体
type User struct {
ID uint64 `json:"id" gorm:"primaryKey"`
ID uint64 `json:"id,string" gorm:"primaryKey;not null"`
Username string `json:"username" gorm:"size:64;uniqueIndex"`
Password string `json:"password,omitempty" gorm:"size:255"`
Nickname string `json:"nickname" gorm:"size:255"`
@@ -129,6 +130,18 @@ func (u *User) CheckActive() error {
return nil
}
func (u *User) assignIDIfMissing() error {
if u.ID != 0 {
return nil
}
id, err := idgen.NextUint64ID()
if err != nil {
return errors.New(errInvalidUserID)
}
u.ID = id
return nil
}
// CreateUser 创建新用户(用于 OAuth/OIDC 自动注册,含底层权限校验)
func (u *User) CreateUser(ctx context.Context, tx *gorm.DB, oauthInfo *OAuthUserInfo) error {
enabled, err := GetBoolByKey(ctx, ConfigKeyRegistrationEnabled)
@@ -137,8 +150,9 @@ func (u *User) CreateUser(ctx context.Context, tx *gorm.DB, oauthInfo *OAuthUser
}
now := time.Now()
userID := oauthInfo.GetID()
newUser := User{
ID: oauthInfo.GetID(),
ID: userID,
Username: oauthInfo.Username,
Nickname: oauthInfo.Name,
Email: oauthInfo.Email,
@@ -147,6 +161,9 @@ func (u *User) CreateUser(ctx context.Context, tx *gorm.DB, oauthInfo *OAuthUser
LastLoginAt: now,
IsAdmin: false,
}
if err := newUser.assignIDIfMissing(); err != nil {
return err
}
if err := tx.Create(&newUser).Error; err != nil {
return err
}
@@ -182,6 +199,9 @@ func (u *User) RegisterUser(ctx context.Context, tx *gorm.DB) error {
}
}
if err := u.assignIDIfMissing(); err != nil {
return err
}
if err := tx.Create(u).Error; err != nil {
return err
}