51 lines
1.0 KiB
Go
51 lines
1.0 KiB
Go
package crud
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"sync"
|
|
|
|
"aijianzhan/platform/internal/meta"
|
|
"aijianzhan/platform/internal/schema"
|
|
)
|
|
|
|
// DBPool 按 database_per_app 缓存连接。
|
|
type DBPool struct {
|
|
mu sync.Mutex
|
|
baseDSN string
|
|
primary *sql.DB
|
|
dbs map[string]*sql.DB
|
|
}
|
|
|
|
func NewDBPool(defaultDB *sql.DB, baseDSN string) *DBPool {
|
|
return &DBPool{primary: defaultDB, baseDSN: baseDSN, dbs: map[string]*sql.DB{}}
|
|
}
|
|
|
|
func (p *DBPool) ForApp(app *meta.AppRecord) (*sql.DB, error) {
|
|
if p == nil {
|
|
return nil, fmt.Errorf("db pool nil")
|
|
}
|
|
if app == nil || app.DatabaseName == "" {
|
|
return p.primary, nil
|
|
}
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
if db, ok := p.dbs[app.DatabaseName]; ok {
|
|
return db, nil
|
|
}
|
|
dsn, err := schema.DSNForDatabase(p.baseDSN, app.DatabaseName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
db, err := sql.Open("postgres", dsn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := db.Ping(); err != nil {
|
|
_ = db.Close()
|
|
return nil, fmt.Errorf("ping app db %s: %w", app.DatabaseName, err)
|
|
}
|
|
p.dbs[app.DatabaseName] = db
|
|
return db, nil
|
|
}
|