feat(chain): PostgreSQL 持久化链(最小改动·写穿+启动水合)

- internal/chain/persistent.go: PersistentChain 装饰 MemoryChain
  - 复用 MemoryChain 全部业务规则(权限/1:1绑定/防换壳),读走内存
  - 写路径在内存变更成功后写穿 PG 镜像表(content_registry/hash_binding/identity_mapping/version_history/chain_tx)
  - 启动从 PG 水合恢复内存状态,重启不丢数据;PG 为非权威镜像,写穿失败仅记日志
- deploy/migrations/0004_binding_revoked.sql: hash_binding 增加 revoked/revoked_reason 列(集级下架镜像)
- cmd/api-svc/main.go: 共享一个 *sql.DB,PG 可用时启用 PersistentChain+PostgresStore,否则回退内存
- 验证: seed_demo 后内容/映射/哈希落库;重启水合3条内容,resolve/mappings 正常恢复
- 面向未来: 接真实 ChainMaker 时整体替换 chain.Client,业务层零改动
This commit is contained in:
selfrelease
2026-06-14 19:24:38 +08:00
parent 34b03a7afa
commit 599ccfe1c8
4 changed files with 753 additions and 10 deletions
+34 -10
View File
@@ -15,25 +15,49 @@ import (
"github.com/tcs-iptv/tcs/internal/service"
)
// newAllocationStore 优先使用 PostgreSQL(持久、防重号),不可用时回退内存。
func newAllocationStore(dsn string) macode.AllocationStore {
// openDB 尝试连接 PostgreSQL,连通则返回 *sql.DB,否则返回 nil回退内存
func openDB(dsn string) *sql.DB {
db, err := sql.Open("postgres", dsn)
if err == nil {
if pingErr := db.Ping(); pingErr == nil {
log.Printf("macode: 使用 PostgreSQL 号段存储")
return macode.NewPostgresStore(db)
}
if err != nil {
return nil
}
if err := db.Ping(); err != nil {
return nil
}
return db
}
// newAllocationStore 优先使用 PostgreSQL(持久、防重号),不可用时回退内存。
func newAllocationStore(db *sql.DB) macode.AllocationStore {
if db != nil {
log.Printf("macode: 使用 PostgreSQL 号段存储")
return macode.NewPostgresStore(db)
}
log.Printf("macode: PostgreSQL 不可用,回退内存号段存储(仅开发用)")
return macode.NewMemoryStore()
}
// newChain 优先使用 PostgreSQL 持久化链(写穿 + 启动水合),不可用时回退纯内存。
func newChain(db *sql.DB) chain.Client {
if db != nil {
if pc, err := chain.NewPersistentChain(db); err == nil {
log.Printf("chain: 使用 PostgreSQL 持久化链(写穿+水合,重启不丢数据)")
return pc
} else {
log.Printf("chain: PG 持久化链初始化失败(%v),回退内存链", err)
}
}
log.Printf("chain: 使用内存链(仅开发用,重启丢数据)")
return chain.NewMemoryChain()
}
func main() {
cfg := config.Load()
// 装配依赖:链(MVP 用内存 mock)+ MA 码生成器(登记号段)+ 业务服务
ch := chain.NewMemoryChain()
gen := macode.NewGenerator(newAllocationStore(cfg.PostgresDSN))
// 装配依赖:共享一个 PG 连接给链持久化与号段存储
db := openDB(cfg.PostgresDSN)
ch := newChain(db)
gen := macode.NewGenerator(newAllocationStore(db))
// 示例号段(生产由与发码机构对接后配置)
// 机构节点 6101 = 陕西(管理方:陕西IPTV运营公司);行业节点 8531 = IPTV视听内容
_ = gen.RegisterSegment(macode.Segment{