mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-06 18:06:36 +08:00
fix: make service update idempotent (upsert)
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
+41
-32
@@ -87,36 +87,32 @@ func updateServices(req updateServicesRequest) error {
|
|||||||
return errors.New("services list cannot be empty")
|
return errors.New("services list cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第一阶段:验证所有服务存在
|
// 第一阶段:验证所有服务名称有效性
|
||||||
for _, serviceConfig := range req.Data {
|
for i := range req.Data {
|
||||||
name := strings.TrimSpace(serviceConfig.Name)
|
name := strings.TrimSpace(req.Data[i].Name)
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return errors.New("service name is required")
|
return errors.New("service name is required")
|
||||||
}
|
}
|
||||||
serviceConfig.Name = name
|
req.Data[i].Name = name
|
||||||
|
|
||||||
old := registry.ServiceRegistry().Get(name)
|
|
||||||
if old == nil {
|
|
||||||
return errors.New("service " + name + " not found")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第二阶段:按照原来的updateService逻辑,逐个更新服务
|
// 第二阶段:逐个更新服务(Upsert模式:存在则更新,不存在则创建)
|
||||||
for _, serviceConfig := range req.Data {
|
for i := range req.Data {
|
||||||
name := strings.TrimSpace(serviceConfig.Name)
|
serviceConfig := &req.Data[i]
|
||||||
serviceConfig.Name = name
|
name := serviceConfig.Name
|
||||||
|
|
||||||
// 1. 获取旧服务
|
// 1. 获取旧服务
|
||||||
old := registry.ServiceRegistry().Get(name)
|
old := registry.ServiceRegistry().Get(name)
|
||||||
|
|
||||||
// 2. 关闭旧服务
|
// 2. 关闭旧服务 (如果存在)
|
||||||
old.Close()
|
if old != nil {
|
||||||
|
old.Close()
|
||||||
// 3. 从注册表移除旧服务
|
// 3. 从注册表移除旧服务
|
||||||
registry.ServiceRegistry().Unregister(name)
|
registry.ServiceRegistry().Unregister(name)
|
||||||
|
}
|
||||||
|
|
||||||
// 4. 解析新服务配置
|
// 4. 解析新服务配置
|
||||||
svc, err := parser.ParseService(&serviceConfig)
|
svc, err := parser.ParseService(serviceConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("create service " + name + " failed: " + err.Error())
|
return errors.New("create service " + name + " failed: " + err.Error())
|
||||||
}
|
}
|
||||||
@@ -133,13 +129,20 @@ func updateServices(req updateServicesRequest) error {
|
|||||||
|
|
||||||
// 第三阶段:更新配置
|
// 第三阶段:更新配置
|
||||||
config.OnUpdate(func(c *config.Config) error {
|
config.OnUpdate(func(c *config.Config) error {
|
||||||
for _, serviceConfig := range req.Data {
|
for i := range req.Data {
|
||||||
for i := range c.Services {
|
// 创建副本以确保指针安全
|
||||||
if c.Services[i].Name == serviceConfig.Name {
|
cfgCopy := req.Data[i]
|
||||||
c.Services[i] = &serviceConfig
|
found := false
|
||||||
|
for j := range c.Services {
|
||||||
|
if c.Services[j].Name == cfgCopy.Name {
|
||||||
|
c.Services[j] = &cfgCopy
|
||||||
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !found {
|
||||||
|
c.Services = append(c.Services, &cfgCopy)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@@ -158,22 +161,22 @@ func deleteServices(req deleteServicesRequest) error {
|
|||||||
name string
|
name string
|
||||||
service service.Service
|
service service.Service
|
||||||
}
|
}
|
||||||
|
var namesToRemove []string
|
||||||
|
|
||||||
for _, serviceName := range req.Services {
|
for _, serviceName := range req.Services {
|
||||||
name := strings.TrimSpace(serviceName)
|
name := strings.TrimSpace(serviceName)
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return errors.New("service name is required")
|
return errors.New("service name is required")
|
||||||
}
|
}
|
||||||
|
namesToRemove = append(namesToRemove, name)
|
||||||
|
|
||||||
svc := registry.ServiceRegistry().Get(name)
|
svc := registry.ServiceRegistry().Get(name)
|
||||||
if svc == nil {
|
if svc != nil {
|
||||||
return errors.New("service " + name + " not found")
|
servicesToDelete = append(servicesToDelete, struct {
|
||||||
|
name string
|
||||||
|
service service.Service
|
||||||
|
}{name, svc})
|
||||||
}
|
}
|
||||||
|
|
||||||
servicesToDelete = append(servicesToDelete, struct {
|
|
||||||
name string
|
|
||||||
service service.Service
|
|
||||||
}{name, svc})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第二阶段:删除所有服务
|
// 第二阶段:删除所有服务
|
||||||
@@ -181,6 +184,12 @@ func deleteServices(req deleteServicesRequest) error {
|
|||||||
registry.ServiceRegistry().Unregister(std.name)
|
registry.ServiceRegistry().Unregister(std.name)
|
||||||
std.service.Close()
|
std.service.Close()
|
||||||
}
|
}
|
||||||
|
// 确保所有请求删除的服务都从注册表中移除(即使之前未找到实例)
|
||||||
|
for _, name := range namesToRemove {
|
||||||
|
if registry.ServiceRegistry().IsRegistered(name) {
|
||||||
|
registry.ServiceRegistry().Unregister(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 第三阶段:更新配置
|
// 第三阶段:更新配置
|
||||||
config.OnUpdate(func(c *config.Config) error {
|
config.OnUpdate(func(c *config.Config) error {
|
||||||
@@ -188,8 +197,8 @@ func deleteServices(req deleteServicesRequest) error {
|
|||||||
c.Services = nil
|
c.Services = nil
|
||||||
for _, s := range services {
|
for _, s := range services {
|
||||||
shouldDelete := false
|
shouldDelete := false
|
||||||
for _, std := range servicesToDelete {
|
for _, name := range namesToRemove {
|
||||||
if s.Name == std.name {
|
if s.Name == name {
|
||||||
shouldDelete = true
|
shouldDelete = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user