refactor: deprecate int32 (#7025)

* refactor: deprecate int32

* fix(db): reject legacy user quota schemas at startup

* fix(quota): enforce wallet bounds and saturating billing conversions

* fix(rate-limit): keep count*duration from wrapping int64

* fix: error message
This commit is contained in:
Seefs
2026-08-26 20:57:54 +08:00
committed by GitHub
parent 2d8e50bf36
commit a073f74b38
35 changed files with 445 additions and 116 deletions
+49
View File
@@ -186,6 +186,9 @@ func InitDB() (err error) {
panic(err)
}
}
if err := ensureUserQuotaColumns(DB, common.MainDatabaseType()); err != nil {
return err
}
sqlDB, err := DB.DB()
if err != nil {
return err
@@ -250,6 +253,52 @@ func InitLogDB() (err error) {
return err
}
var userQuotaColumns = []string{"quota", "used_quota", "aff_quota", "aff_history"}
// ensureUserQuotaColumns rejects a legacy 32-bit wallet schema before any
// migrations run. The 64-bit-only build intentionally does not auto-upgrade
// an existing wallet; operators must migrate it explicitly before starting.
func ensureUserQuotaColumns(db *gorm.DB, dbType common.DatabaseType) error {
if common.GetEnvOrDefaultBool("SKIP_64BIT_QUOTA_SCHEMA_CHECK", false) {
common.SysLog("SKIP_64BIT_QUOTA_SCHEMA_CHECK=true; skipping user quota schema check")
return nil
}
if db == nil || dbType == common.DatabaseTypeSQLite {
return nil
}
if !db.Migrator().HasTable(&User{}) {
return nil
}
columnTypes, err := db.Migrator().ColumnTypes(&User{})
if err != nil {
return fmt.Errorf("failed to inspect users schema: %w", err)
}
for _, expected := range userQuotaColumns {
for _, actual := range columnTypes {
if !strings.EqualFold(actual.Name(), expected) {
continue
}
dataType := actual.DatabaseTypeName()
if !is64BitIntegerType(dbType, dataType) {
return fmt.Errorf("users.%s uses %s; 32-bit is not supported", expected, dataType)
}
}
}
return nil
}
func is64BitIntegerType(dbType common.DatabaseType, dataType string) bool {
normalized := strings.ToLower(strings.TrimSpace(dataType))
switch dbType {
case common.DatabaseTypeMySQL:
return normalized == "bigint" || normalized == "unsigned bigint" || normalized == "bigint unsigned"
case common.DatabaseTypePostgreSQL:
return normalized == "bigint" || normalized == "int8"
default:
return false
}
}
func migrateDB() error {
// Migrate price_amount column from float/double to decimal for existing tables
migrateSubscriptionPlanPriceAmount()