Files
new-api/model/main.go

277 lines
6.0 KiB
Go
Raw Normal View History

2023-04-22 20:39:27 +08:00
package model
import (
"github.com/glebarez/sqlite"
2023-04-22 20:39:27 +08:00
"gorm.io/driver/mysql"
2023-08-12 19:20:12 +08:00
"gorm.io/driver/postgres"
2023-04-22 20:39:27 +08:00
"gorm.io/gorm"
2024-03-04 19:32:59 +08:00
"log"
2023-04-22 21:14:09 +08:00
"one-api/common"
2023-04-22 20:39:27 +08:00
"os"
2023-08-12 19:20:12 +08:00
"strings"
2024-03-04 19:32:59 +08:00
"sync"
"time"
2023-04-22 20:39:27 +08:00
)
2024-12-30 17:10:48 +08:00
var groupCol string
var keyCol string
2024-12-31 02:06:30 +08:00
func initCol() {
2024-12-30 17:10:48 +08:00
if common.UsingPostgreSQL {
groupCol = `"group"`
keyCol = `"key"`
} else {
groupCol = "`group`"
keyCol = "`key`"
}
}
2023-04-22 20:39:27 +08:00
var DB *gorm.DB
2024-08-13 10:29:55 +08:00
var LOG_DB *gorm.DB
2023-04-22 20:39:27 +08:00
func createRootAccountIfNeed() error {
var user User
//if user.Status != common.UserStatusEnabled {
if err := DB.First(&user).Error; err != nil {
common.SysLog("no user exists, create a root user for you: username is root, password is 123456")
hashedPassword, err := common.Password2Hash("123456")
if err != nil {
return err
}
rootUser := User{
Username: "root",
Password: hashedPassword,
Role: common.RoleRootUser,
Status: common.UserStatusEnabled,
DisplayName: "Root User",
AccessToken: nil,
2023-05-21 10:05:34 +08:00
Quota: 100000000,
2023-04-22 20:39:27 +08:00
}
DB.Create(&rootUser)
}
return nil
}
2024-08-13 10:29:55 +08:00
func chooseDB(envName string) (*gorm.DB, error) {
2024-12-31 02:06:30 +08:00
defer func() {
initCol()
}()
2024-08-13 10:29:55 +08:00
dsn := os.Getenv(envName)
if dsn != "" {
2023-08-12 19:20:12 +08:00
if strings.HasPrefix(dsn, "postgres://") {
// Use PostgreSQL
common.SysLog("using PostgreSQL as database")
common.UsingPostgreSQL = true
2023-08-12 19:20:12 +08:00
return gorm.Open(postgres.New(postgres.Config{
DSN: dsn,
PreferSimpleProtocol: true, // disables implicit prepared statement usage
}), &gorm.Config{
PrepareStmt: true, // precompile SQL
})
}
2024-08-13 10:29:55 +08:00
if strings.HasPrefix(dsn, "local") {
common.SysLog("SQL_DSN not set, using SQLite as database")
common.UsingSQLite = true
return gorm.Open(sqlite.Open(common.SQLitePath), &gorm.Config{
PrepareStmt: true, // precompile SQL
})
}
2023-04-22 20:39:27 +08:00
// Use MySQL
2023-06-22 01:12:28 +08:00
common.SysLog("using MySQL as database")
2023-12-27 15:33:35 +08:00
// check parseTime
if !strings.Contains(dsn, "parseTime") {
2023-12-27 16:47:32 +08:00
if strings.Contains(dsn, "?") {
dsn += "&parseTime=true"
} else {
dsn += "?parseTime=true"
}
2023-12-27 15:33:35 +08:00
}
2024-03-12 00:35:12 +08:00
common.UsingMySQL = true
2023-08-12 19:20:12 +08:00
return gorm.Open(mysql.Open(dsn), &gorm.Config{
2023-04-22 20:39:27 +08:00
PrepareStmt: true, // precompile SQL
})
}
2023-08-12 19:20:12 +08:00
// Use SQLite
common.SysLog("SQL_DSN not set, using SQLite as database")
common.UsingSQLite = true
return gorm.Open(sqlite.Open(common.SQLitePath), &gorm.Config{
PrepareStmt: true, // precompile SQL
})
}
func InitDB() (err error) {
2024-08-13 10:29:55 +08:00
db, err := chooseDB("SQL_DSN")
2023-04-22 20:39:27 +08:00
if err == nil {
if common.DebugEnabled {
db = db.Debug()
}
2023-04-22 20:39:27 +08:00
DB = db
sqlDB, err := DB.DB()
if err != nil {
return err
}
2024-06-27 19:30:17 +08:00
sqlDB.SetMaxIdleConns(common.GetEnvOrDefault("SQL_MAX_IDLE_CONNS", 100))
sqlDB.SetMaxOpenConns(common.GetEnvOrDefault("SQL_MAX_OPEN_CONNS", 1000))
sqlDB.SetConnMaxLifetime(time.Second * time.Duration(common.GetEnvOrDefault("SQL_MAX_LIFETIME", 60)))
if !common.IsMasterNode {
return nil
}
if common.UsingMySQL {
_, _ = sqlDB.Exec("ALTER TABLE channels MODIFY model_mapping TEXT;") // TODO: delete this line when most users have upgraded
}
2023-10-02 12:13:30 +08:00
common.SysLog("database migration started")
2024-08-13 10:29:55 +08:00
err = migrateDB()
return err
} else {
common.FatalLog(err)
}
return err
}
func InitLogDB() (err error) {
if os.Getenv("LOG_SQL_DSN") == "" {
LOG_DB = DB
return
}
db, err := chooseDB("LOG_SQL_DSN")
if err == nil {
if common.DebugEnabled {
db = db.Debug()
2023-08-14 22:16:32 +08:00
}
2024-08-13 10:29:55 +08:00
LOG_DB = db
sqlDB, err := LOG_DB.DB()
2024-01-07 18:31:14 +08:00
if err != nil {
return err
}
2024-08-13 10:29:55 +08:00
sqlDB.SetMaxIdleConns(common.GetEnvOrDefault("SQL_MAX_IDLE_CONNS", 100))
sqlDB.SetMaxOpenConns(common.GetEnvOrDefault("SQL_MAX_OPEN_CONNS", 1000))
sqlDB.SetConnMaxLifetime(time.Second * time.Duration(common.GetEnvOrDefault("SQL_MAX_LIFETIME", 60)))
if !common.IsMasterNode {
return nil
}
2024-08-13 10:29:55 +08:00
//if common.UsingMySQL {
// _, _ = sqlDB.Exec("DROP INDEX idx_channels_key ON channels;") // TODO: delete this line when most users have upgraded
// _, _ = sqlDB.Exec("ALTER TABLE midjourneys MODIFY action VARCHAR(40);") // TODO: delete this line when most users have upgraded
// _, _ = sqlDB.Exec("ALTER TABLE midjourneys MODIFY progress VARCHAR(30);") // TODO: delete this line when most users have upgraded
// _, _ = sqlDB.Exec("ALTER TABLE midjourneys MODIFY status VARCHAR(20);") // TODO: delete this line when most users have upgraded
//}
common.SysLog("database migration started")
err = migrateLOGDB()
2023-04-22 20:39:27 +08:00
return err
} else {
common.FatalLog(err)
}
return err
}
2024-08-13 10:29:55 +08:00
func migrateDB() error {
err := DB.AutoMigrate(&Channel{})
if err != nil {
return err
}
err = DB.AutoMigrate(&Token{})
if err != nil {
return err
}
err = DB.AutoMigrate(&User{})
if err != nil {
return err
}
err = DB.AutoMigrate(&Option{})
if err != nil {
return err
}
err = DB.AutoMigrate(&Redemption{})
if err != nil {
return err
}
err = DB.AutoMigrate(&Ability{})
if err != nil {
return err
}
err = DB.AutoMigrate(&Log{})
if err != nil {
return err
}
err = DB.AutoMigrate(&Midjourney{})
if err != nil {
return err
}
err = DB.AutoMigrate(&TopUp{})
if err != nil {
return err
}
err = DB.AutoMigrate(&QuotaData{})
if err != nil {
return err
}
err = DB.AutoMigrate(&Task{})
if err != nil {
return err
}
common.SysLog("database migrated")
err = createRootAccountIfNeed()
return err
}
func migrateLOGDB() error {
var err error
if err = LOG_DB.AutoMigrate(&Log{}); err != nil {
return err
}
return nil
}
func closeDB(db *gorm.DB) error {
sqlDB, err := db.DB()
2023-04-22 20:39:27 +08:00
if err != nil {
return err
}
err = sqlDB.Close()
return err
}
2024-03-04 19:32:59 +08:00
2024-08-13 10:29:55 +08:00
func CloseDB() error {
if LOG_DB != DB {
err := closeDB(LOG_DB)
if err != nil {
return err
}
}
return closeDB(DB)
}
2024-03-04 19:32:59 +08:00
var (
lastPingTime time.Time
pingMutex sync.Mutex
)
func PingDB() error {
pingMutex.Lock()
defer pingMutex.Unlock()
if time.Since(lastPingTime) < time.Second*10 {
return nil
}
sqlDB, err := DB.DB()
if err != nil {
log.Printf("Error getting sql.DB from GORM: %v", err)
return err
}
err = sqlDB.Ping()
if err != nil {
log.Printf("Error pinging DB: %v", err)
return err
}
lastPingTime = time.Now()
common.SysLog("Database pinged successfully")
return nil
}