feat(server/db): 多库(3/4)— Dialect 抽象(upsert/锁)+ 合并 directory_version
- db.Dialect:LockForUpdate(mysql "FOR UPDATE" / sqlite "")、Upsert(中性 EXCLUDED.col → mysql VALUES()/ sqlite excluded.);DialectForDB 从连接驱动推导 - 9 处 ON DUPLICATE KEY、11 处 FOR UPDATE 全走 dialect;sqlite 靠 _txlock= immediate 取得 BEGIN IMMEDIATE 悲观锁等价语义 - directory_version 三处重复合并为 store.BumpDirectoryVersion(dialect 感知) - 这些文件同时含(2/4)的 UTC→Go 改动(与 upsert/锁同语句交错,无法拆分) - 顺带:usage 的 FIELD()、codes 的 DATE_ADD/GREATEST 续期、nodes 的 UNIX_TIMESTAMP、NULLIF 等 MySQL 专属构造一并退回 Go/可移植写法 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -8,9 +8,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
dbx "github.com/wangjia/pangolin/server/internal/db"
|
||||
"github.com/wangjia/pangolin/server/internal/nodes"
|
||||
"github.com/wangjia/pangolin/server/internal/scheduler/detect"
|
||||
"github.com/wangjia/pangolin/server/internal/scheduler/orchestrate"
|
||||
"github.com/wangjia/pangolin/server/internal/store"
|
||||
)
|
||||
|
||||
// SQLLifecycle is a MySQL-backed lifecycle store. The detect and orchestrate
|
||||
@@ -30,13 +32,14 @@ import (
|
||||
// — provision.DestroyNode tears down the VM, and the agent's mTLS cert can be
|
||||
// revoked separately. Wire CRL revocation when the real fleet exists (TODO).
|
||||
type SQLLifecycle struct {
|
||||
db *sql.DB
|
||||
loads *nodes.LoadCache
|
||||
db *sql.DB
|
||||
dialect dbx.Dialect
|
||||
loads *nodes.LoadCache
|
||||
}
|
||||
|
||||
// NewSQLLifecycle wires the store. loads may be nil (load reads then return zero).
|
||||
func NewSQLLifecycle(db *sql.DB, loads *nodes.LoadCache) *SQLLifecycle {
|
||||
return &SQLLifecycle{db: db, loads: loads}
|
||||
return &SQLLifecycle{db: db, dialect: dbx.DialectForDB(db), loads: loads}
|
||||
}
|
||||
|
||||
const nodeSelectCols = `id, uuid, status, region, tier, role, reality_sni, reality_pbk, hy2_port, provider_id, weight, name_zh, name_en`
|
||||
@@ -134,9 +137,7 @@ func (l *SQLLifecycle) transition(ctx context.Context, nodeID, from, to string,
|
||||
_, _ = tx.ExecContext(ctx,
|
||||
`INSERT INTO node_events (node_id, event, detail) VALUES (?, ?, ?)`, nodeID, ev, dj)
|
||||
}
|
||||
if _, err := tx.ExecContext(ctx,
|
||||
`INSERT INTO directory_version (id, version) VALUES (1, 1)
|
||||
ON DUPLICATE KEY UPDATE version = version + 1`); err != nil {
|
||||
if err := store.BumpDirectoryVersion(ctx, tx, l.dialect); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := tx.Commit(); err != nil {
|
||||
@@ -151,10 +152,7 @@ func (l *SQLLifecycle) setWeight(ctx context.Context, nodeID string, weight int)
|
||||
}
|
||||
|
||||
func (l *SQLLifecycle) bumpVersion(ctx context.Context) error {
|
||||
_, err := l.db.ExecContext(ctx,
|
||||
`INSERT INTO directory_version (id, version) VALUES (1, 1)
|
||||
ON DUPLICATE KEY UPDATE version = version + 1`)
|
||||
return err
|
||||
return store.BumpDirectoryVersion(ctx, l.db, l.dialect)
|
||||
}
|
||||
|
||||
func (l *SQLLifecycle) version(ctx context.Context) int64 {
|
||||
|
||||
Reference in New Issue
Block a user