feat: 支持 UserPromptSubmit 事件,将 prompt 存入 MySQL
- 新增 db.go:MySQL 连接管理、自动建表、兼容旧表 ALTER - handler.go:处理 UserPromptSubmit,从 cwd 提取项目名称 - main.go:可选初始化 MySQL,优雅关闭释放连接 - config.go:新增 MYSQL_DSN 配置项 - 表结构:session_id + project_name + prompt + created_at
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
type PromptDB struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
// NewPromptDB 创建 MySQL 连接并自动建表
|
||||
// dsn 格式: user:password@tcp(host:port)/dbname?parseTime=true
|
||||
func NewPromptDB(dsn string) (*PromptDB, error) {
|
||||
db, err := sql.Open("mysql", dsn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open mysql: %w", err)
|
||||
}
|
||||
|
||||
// 连接池配置
|
||||
db.SetMaxOpenConns(10)
|
||||
db.SetMaxIdleConns(5)
|
||||
db.SetConnMaxLifetime(5 * time.Minute)
|
||||
|
||||
// 等待连接就绪
|
||||
if err := db.Ping(); err != nil {
|
||||
return nil, fmt.Errorf("failed to ping mysql: %w", err)
|
||||
}
|
||||
|
||||
// 自动建表
|
||||
if err := migrate(db); err != nil {
|
||||
return nil, fmt.Errorf("failed to migrate: %w", err)
|
||||
}
|
||||
|
||||
log.Println("mysql connected and migrated")
|
||||
return &PromptDB{db: db}, nil
|
||||
}
|
||||
|
||||
func migrate(db *sql.DB) error {
|
||||
query := `
|
||||
CREATE TABLE IF NOT EXISTS prompts (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
session_id VARCHAR(128) NOT NULL,
|
||||
project_name VARCHAR(255) NOT NULL DEFAULT '',
|
||||
prompt TEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_session_id (session_id),
|
||||
INDEX idx_project_name (project_name),
|
||||
INDEX idx_created_at (created_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;`
|
||||
|
||||
_, err := db.Exec(query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 兼容旧表:如果已存在但缺少 project_name 列,则补充
|
||||
_, err = db.Exec("ALTER TABLE prompts ADD COLUMN project_name VARCHAR(255) NOT NULL DEFAULT '' AFTER session_id")
|
||||
if err != nil {
|
||||
// 忽略 "Duplicate column" 错误,说明列已存在
|
||||
log.Printf("alter table (expected if column exists): %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SavePrompt 将一条 prompt 写入数据库
|
||||
func (p *PromptDB) SavePrompt(sessionID, projectName, prompt string) error {
|
||||
_, err := p.db.Exec(
|
||||
"INSERT INTO prompts (session_id, project_name, prompt) VALUES (?, ?, ?)",
|
||||
sessionID, projectName, prompt,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
// Close 关闭数据库连接
|
||||
func (p *PromptDB) Close() error {
|
||||
if p.db != nil {
|
||||
return p.db.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user