Files
ocdp-go/backend/internal/adapter/output/persistence/postgres/db.go
mangomqy c5e51ed069 ocdp v1
2025-11-13 02:54:06 +00:00

136 lines
3.5 KiB
Go

package postgres
import (
"database/sql"
"fmt"
"time"
_ "github.com/lib/pq"
)
// DB 数据库连接包装器
type DB struct {
conn *sql.DB
}
// NewDB 创建新的数据库连接
func NewDB(connString string) (*DB, error) {
if connString == "" {
return nil, fmt.Errorf("database connection string cannot be empty")
}
conn, err := sql.Open("postgres", connString)
if err != nil {
return nil, fmt.Errorf("failed to open database: %w", err)
}
// 配置连接池
conn.SetMaxOpenConns(25)
conn.SetMaxIdleConns(5)
conn.SetConnMaxLifetime(5 * time.Minute)
// 测试连接
if err := conn.Ping(); err != nil {
return nil, fmt.Errorf("failed to ping database: %w", err)
}
return &DB{conn: conn}, nil
}
// Close 关闭数据库连接
func (db *DB) Close() error {
if db.conn != nil {
return db.conn.Close()
}
return nil
}
// GetConn 获取底层连接(用于事务等高级操作)
func (db *DB) GetConn() *sql.DB {
return db.conn
}
// InitSchema 初始化数据库 schema
func (db *DB) InitSchema() error {
schema := `
-- Users 表
CREATE TABLE IF NOT EXISTS users (
id VARCHAR(36) PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
email VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
-- Clusters 表
CREATE TABLE IF NOT EXISTS clusters (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
host TEXT NOT NULL,
ca_data TEXT,
cert_data TEXT,
key_data TEXT,
token TEXT,
description TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_clusters_name ON clusters(name);
-- Registries 表
CREATE TABLE IF NOT EXISTS registries (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
url TEXT NOT NULL,
description TEXT,
username VARCHAR(255),
password TEXT,
insecure BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_registries_name ON registries(name);
-- Instances 表
CREATE TABLE IF NOT EXISTS instances (
id VARCHAR(36) PRIMARY KEY,
cluster_id VARCHAR(36) NOT NULL,
name VARCHAR(255) NOT NULL,
namespace VARCHAR(255) NOT NULL,
registry_id VARCHAR(36) NOT NULL,
repository TEXT NOT NULL,
chart VARCHAR(255) NOT NULL,
version VARCHAR(255) NOT NULL,
description TEXT,
values JSONB,
values_yaml TEXT,
status VARCHAR(50) NOT NULL,
status_reason TEXT,
last_operation VARCHAR(50),
last_error TEXT,
revision INTEGER NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_cluster FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE,
CONSTRAINT fk_registry FOREIGN KEY (registry_id) REFERENCES registries(id) ON DELETE CASCADE,
CONSTRAINT unique_cluster_name UNIQUE (cluster_id, name, namespace)
);
CREATE INDEX IF NOT EXISTS idx_instances_cluster ON instances(cluster_id);
CREATE INDEX IF NOT EXISTS idx_instances_registry ON instances(registry_id);
CREATE INDEX IF NOT EXISTS idx_instances_name ON instances(name);
`
_, err := db.conn.Exec(schema)
if err != nil {
return fmt.Errorf("failed to initialize schema: %w", err)
}
return nil
}