Skip to main content
Glama
conn.go4.92 kB
package dao import ( "fmt" "log" "os" "path/filepath" "sync" "time" "github.com/glebarez/sqlite" "github.com/weibaohui/k8m/pkg/flag" "gorm.io/driver/mysql" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" "k8s.io/klog/v2" ) // 定义全局变量 var ( once sync.Once dbInstance *gorm.DB dbErr error ) // connDB 初始化并返回全局唯一的 GORM 数据库连接实例。 // 若数据库文件不存在,则自动创建所需目录和文件,并设置最大连接数为 1。 // 返回数据库连接实例和初始化过程中遇到的错误。 func connDB() (*gorm.DB, error) { once.Do(func() { customLogger := logger.New( log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer logger.Config{ SlowThreshold: time.Second, // 慢 SQL 阈值 LogLevel: logger.Info, // 日志级别 IgnoreRecordNotFoundError: true, // 忽略记录未找到错误 Colorful: true, // 禁用彩色打印 }, ) cfg := flag.Init() if cfg.DBDriver == "sqlite" { dbInstance, dbErr = openSqliteDB(cfg, customLogger) return } else if cfg.DBDriver == "mysql" { dbInstance, dbErr = openMysqlDB(cfg, customLogger) return } else if cfg.DBDriver == "postgresql" { dbInstance, dbErr = openPostgresDB(cfg, customLogger) return } }) return dbInstance, dbErr } // openSqliteDB 负责初始化并返回sqlite数据库连接实例。 func openSqliteDB(cfg *flag.Config, customLogger logger.Interface) (*gorm.DB, error) { if _, err := os.Stat(cfg.SqlitePath); os.IsNotExist(err) { dir := filepath.Dir(cfg.SqlitePath) err := os.MkdirAll(dir, os.ModePerm) if err != nil { klog.Errorf("创建数据库文件[%s]失败: %v", dir, err.Error()) return nil, err } file, err := os.Create(cfg.SqlitePath) defer file.Close() if err != nil { klog.Errorf("创建数据库文件[%s]失败: %v", cfg.SqlitePath, err.Error()) return nil, err } } // 优先使用自定义DSN,如果未设置则使用默认配置 dsn := cfg.SqliteDSN if dsn == "" { // 使用 WAL 模式和 busy_timeout 以优化并发性能 dsn = fmt.Sprintf("file:%s?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)", cfg.SqlitePath) } db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{ Logger: customLogger, }) if err != nil { return nil, err } klog.V(4).Infof("已连接数据库[%s].", cfg.SqlitePath) s, err := db.DB() if err != nil { return nil, err } s.SetMaxOpenConns(1) return db, nil } // openMysqlDB 负责初始化并返回mysql数据库连接实例。 func openMysqlDB(cfg *flag.Config, customLogger logger.Interface) (*gorm.DB, error) { dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&collation=%s&%s", cfg.MysqlUser, cfg.MysqlPassword, cfg.MysqlHost, cfg.MysqlPort, cfg.MysqlDatabase, cfg.MysqlCharset, cfg.MysqlCollation, cfg.MysqlQuery, ) showDsn := fmt.Sprintf("%s:******@tcp(%s:%d)/%s?charset=%s&collation=%s&%s", cfg.MysqlUser, cfg.MysqlHost, cfg.MysqlPort, cfg.MysqlDatabase, cfg.MysqlCharset, cfg.MysqlCollation, cfg.MysqlQuery, ) db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ Logger: customLogger, DisableForeignKeyConstraintWhenMigrating: true, }) if err != nil { klog.Errorf("初始化mysql数据库异常: %v", err) return nil, err } if cfg.MysqlLogMode { db = db.Debug() } sqlDB, err := db.DB() if err != nil { return nil, err } sqlDB.SetMaxOpenConns(20) sqlDB.SetMaxIdleConns(10) sqlDB.SetConnMaxLifetime(time.Minute * 5) klog.V(2).Infof("初始化mysql数据库完成! dsn: %s", showDsn) return db, nil } // openPostgresDB 负责初始化并返回postgres数据库连接实例。 func openPostgresDB(cfg *flag.Config, customLogger logger.Interface) (*gorm.DB, error) { // 构建 PostgreSQL DSN dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", cfg.PgHost, cfg.PgUser, cfg.PgPassword, cfg.PgDatabase, cfg.PgPort, cfg.PgSSLMode, cfg.PgTimeZone, ) showDsn := fmt.Sprintf("host=%s user=%s password=****** dbname=%s port=%d sslmode=%s TimeZone=%s", cfg.PgHost, cfg.PgUser, cfg.PgDatabase, cfg.PgPort, cfg.PgSSLMode, cfg.PgTimeZone, ) db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ Logger: customLogger, }) if err != nil { klog.Errorf("初始化postgres数据库异常: %v", err) return nil, err } if cfg.PgLogMode { db = db.Debug() } sqlDB, err := db.DB() if err != nil { return nil, err } sqlDB.SetMaxOpenConns(20) sqlDB.SetMaxIdleConns(10) sqlDB.SetConnMaxLifetime(time.Minute * 5) klog.V(2).Infof("初始化postgres数据库完成! dsn: %s", showDsn) return db, nil } // DB 获取数据库连接实例 func DB() *gorm.DB { _, err := connDB() if err != nil { klog.Errorf("数据库连接失败:%v", err) } return dbInstance }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/weibaohui/k8m'

If you have feedback or need assistance with the MCP directory API, please join our Discord server