Files
ai_site/platform/internal/dbsync/pool.go
whm b04b180d30 feat: harden loose-offline sync for user JWT, schema, and console ops
Enable Binding-scoped agent push/pull, empty-table schema ensure, SyncPage inspect/drop-table, default module import, and agent-bound publish docs from the 宇恒联调意见.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 09:47:35 +08:00

86 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package dbsync
import (
"database/sql"
"fmt"
"strings"
"sync"
"time"
)
// remotePool 复用线上 A 连接,避免每次 push 冷开 SQLiteWindows 上常 >3s → 旧默认超时 503
type remotePool struct {
mu sync.Mutex
dbs map[string]*pooledDB
}
type pooledDB struct {
db *sql.DB
driver Driver
lastUsed time.Time
}
var sharedRemotePool = &remotePool{dbs: map[string]*pooledDB{}}
func poolKey(driver Driver, dsn string) string {
if driver == DriverSQLite {
dsn = normalizeSQLiteDSN(dsn)
}
return string(driver) + "|" + dsn
}
// AcquireRemote 获取或新建remote 连接;调用方不要 Close。
func AcquireRemote(driver Driver, dsn string) (*sql.DB, error) {
return sharedRemotePool.acquire(driver, dsn)
}
func (p *remotePool) acquire(driver Driver, dsn string) (*sql.DB, error) {
key := poolKey(driver, dsn)
p.mu.Lock()
defer p.mu.Unlock()
if e, ok := p.dbs[key]; ok && e.db != nil {
if err := e.db.Ping(); err == nil {
e.lastUsed = time.Now()
return e.db, nil
}
_ = e.db.Close()
delete(p.dbs, key)
}
db, err := Open(driver, dsn)
if err != nil {
return nil, err
}
p.dbs[key] = &pooledDB{db: db, driver: driver, lastUsed: time.Now()}
return db, nil
}
// WarmRemote 通道启动时预热,把冷开成本挪出请求路径。
func WarmRemote(driver Driver, dsn string) error {
if strings.TrimSpace(dsn) == "" {
return fmt.Errorf("dsn required")
}
_, err := AcquireRemote(driver, dsn)
return err
}
// InvalidateRemote 通道 DSN 变更或停用时丢掉缓存连接。
func InvalidateRemote(driver Driver, dsn string) {
key := poolKey(driver, dsn)
sharedRemotePool.mu.Lock()
defer sharedRemotePool.mu.Unlock()
if e, ok := sharedRemotePool.dbs[key]; ok {
_ = e.db.Close()
delete(sharedRemotePool.dbs, key)
}
}
// CloseAllRemotes 测试或进程退出时关闭池内连接。
func CloseAllRemotes() {
sharedRemotePool.mu.Lock()
defer sharedRemotePool.mu.Unlock()
for k, e := range sharedRemotePool.dbs {
_ = e.db.Close()
delete(sharedRemotePool.dbs, k)
}
}