feat(scheduler): lifecycle 真实接线适配器(2/2) + 装配 BuildRealConfig
把 scheduler 的 stub lifecycle 换成 SQL 后端真实实现,并接入 server:
- SQLLifecycle:MySQL 后端,同时满足 detect.LifecycleService 与
orchestrate.LifecycleService(两个 thin adapter 包装共享核心)。
- TransitionStatus:乐观锁 UPDATE nodes SET status WHERE id AND status=from
→ rows affected(1=成功/0=冲突 no-op)+ 写 node_events(按状态映射 enum,
eventForStatus 纯函数已单测)+ bump directory_version,全在一个事务内。
- ListNodes/GetNode/SetWeight/BumpVersion/GetLoad(读 LoadCache)/WriteAuditLog。
- 已知限制:无历史 load 表 → GetLoadHistory 返回当前点(掉量规则安全降级);
destroy 的 cert 撤销留 TODO(provision 已拆 VM,撤销为纵深防御,待机群再接)。
- BuildRealConfig:用真实 lifecycle + provisionAdapter 装配三循环。
- main.go:SCHED_ENABLED 且有 DB 时走 BuildRealConfig(provision 无厂商凭证则
CreateNode 优雅失败、替换保持 pending),否则回退 stub。
- 全量 server 23 包测试通过;e2e(判封→drain→换机→置备)待机群+厂商凭证验证。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -11,14 +11,63 @@ package scheduler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
|
||||
"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/scheduler/probe"
|
||||
)
|
||||
|
||||
// BuildRealConfig wires the scheduler against the real lifecycle (SQL-backed)
|
||||
// and provision (#14) services, replacing the no-op stubs of BuildStubConfig.
|
||||
//
|
||||
// - detect/orchestrate lifecycle → SQLLifecycle over the nodes table + LoadCache.
|
||||
// - provision → provisionAdapter over the real provision.Service.
|
||||
//
|
||||
// Without vendor credentials the provision service's CreateNode fails (a pending
|
||||
// replacement simply stays pending), but all lifecycle reads/transitions operate
|
||||
// on real node rows. Capacity monitoring is left disabled (nil) as in the stub.
|
||||
//
|
||||
// e2e behaviour (auto-detect → drain → replace → provision) is verifiable only
|
||||
// against a real node fleet with vendor provisioning configured.
|
||||
func BuildRealConfig(
|
||||
rdb *redis.Client,
|
||||
probeStore *probe.Store,
|
||||
db *sql.DB,
|
||||
loads *nodes.LoadCache,
|
||||
provSvc provisionSvc,
|
||||
provStore provisionResolver,
|
||||
) Config {
|
||||
sqlLC := NewSQLLifecycle(db, loads)
|
||||
detectLC := NewDetectLifecycle(sqlLC)
|
||||
orchLC := NewOrchestrateLifecycle(sqlLC)
|
||||
prov := NewProvisionAdapter(provSvc, provStore)
|
||||
|
||||
streaks := detect.NewStreakStore(rdb)
|
||||
engine := detect.NewEngine(probeStore, detectLC, streaks, rdb, nil, nil)
|
||||
|
||||
replacer := orchestrate.NewReplacer(orchestrate.Config{
|
||||
RDB: rdb,
|
||||
Prov: prov,
|
||||
LC: orchLC,
|
||||
Snaps: probeStore,
|
||||
Breaker: nil, // StubBreaker default until 15F policy tuned
|
||||
Notifier: nil, // LogNotifier default
|
||||
Clock: nil,
|
||||
})
|
||||
grayscale := orchestrate.NewGrayscale(rdb, orchLC, nil)
|
||||
|
||||
return Config{
|
||||
RDB: rdb,
|
||||
Engine: engine,
|
||||
Replacer: replacer,
|
||||
Grayscale: grayscale,
|
||||
}
|
||||
}
|
||||
|
||||
// BuildStubConfig constructs a scheduler Config wired entirely with in-process
|
||||
// stubs. Useful for:
|
||||
// - Starting the scheduler before tasks #5 / #14 are delivered (no-op ticks).
|
||||
@@ -41,8 +90,8 @@ func BuildStubConfig(rdb *redis.Client, probeStore *probe.Store) Config {
|
||||
|
||||
streaks := detect.NewStreakStore(rdb)
|
||||
engine := detect.NewEngine(
|
||||
probeStore, // 15A probe snapshot reader
|
||||
stubDetectLC, // 15D lifecycle (stub until #5)
|
||||
probeStore, // 15A probe snapshot reader
|
||||
stubDetectLC, // 15D lifecycle (stub until #5)
|
||||
streaks,
|
||||
rdb,
|
||||
nil, // notifier — LogNotifier used by default
|
||||
@@ -91,8 +140,8 @@ func (stubOrchLC) TransitionStatus(_ context.Context, _, _, _ string, _ map[stri
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
func (stubOrchLC) SetWeight(_ context.Context, _ string, _ int) error { return nil }
|
||||
func (stubOrchLC) BumpVersion(_ context.Context) error { return nil }
|
||||
func (stubOrchLC) SetWeight(_ context.Context, _ string, _ int) error { return nil }
|
||||
func (stubOrchLC) BumpVersion(_ context.Context) error { return nil }
|
||||
func (stubOrchLC) WriteAuditLog(_ context.Context, _, _, _, _ string) error { return nil }
|
||||
|
||||
// stubProvision implements orchestrate.ProvisionService as a no-op.
|
||||
|
||||
Reference in New Issue
Block a user