Files
tyapi-server/internal/domains/api/services/processors/comb/comb_service.go
2025-07-28 01:46:39 +08:00

167 lines
4.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package comb
import (
"context"
"encoding/json"
"fmt"
"sort"
"sync"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/domains/product/entities"
"tyapi-server/internal/domains/product/services"
)
// CombService 组合包服务
type CombService struct {
productManagementService *services.ProductManagementService
processorRegistry map[string]processors.ProcessorFunc
}
// NewCombService 创建组合包服务
func NewCombService(productManagementService *services.ProductManagementService) *CombService {
return &CombService{
productManagementService: productManagementService,
processorRegistry: make(map[string]processors.ProcessorFunc),
}
}
// RegisterProcessor 注册处理器
func (cs *CombService) RegisterProcessor(apiCode string, processor processors.ProcessorFunc) {
cs.processorRegistry[apiCode] = processor
}
// ProcessCombRequest 处理组合包请求 - 实现 CombServiceInterface
func (cs *CombService) ProcessCombRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies, packageCode string) ([]byte, error) {
// 1. 根据组合包code获取产品信息
packageProduct, err := cs.productManagementService.GetProductByCode(ctx, packageCode)
if err != nil {
return nil, fmt.Errorf("获取组合包信息失败: %s", err.Error())
}
if !packageProduct.IsPackage {
return nil, fmt.Errorf("产品 %s 不是组合包", packageCode)
}
// 2. 获取组合包的所有子产品
packageItems, err := cs.productManagementService.GetPackageItems(ctx, packageProduct.ID)
if err != nil {
return nil, fmt.Errorf("获取组合包子产品失败: %s", err.Error())
}
if len(packageItems) == 0 {
return nil, fmt.Errorf("组合包 %s 没有配置子产品", packageCode)
}
// 3. 并发调用所有子产品的处理器
results := cs.processSubProducts(ctx, params, deps, packageItems)
// 4. 组合结果
return cs.combineResults(results)
}
// processSubProducts 并发处理子产品
func (cs *CombService) processSubProducts(
ctx context.Context,
params []byte,
deps *processors.ProcessorDependencies,
packageItems []*entities.ProductPackageItem,
) []*SubProductResult {
results := make([]*SubProductResult, 0, len(packageItems))
var wg sync.WaitGroup
var mu sync.Mutex
// 并发处理每个子产品
for _, item := range packageItems {
wg.Add(1)
go func(item *entities.ProductPackageItem) {
defer wg.Done()
result := cs.processSingleSubProduct(ctx, params, deps, item)
mu.Lock()
results = append(results, result)
mu.Unlock()
}(item)
}
wg.Wait()
// 按SortOrder排序
sort.Slice(results, func(i, j int) bool {
return results[i].SortOrder < results[j].SortOrder
})
return results
}
// processSingleSubProduct 处理单个子产品
func (cs *CombService) processSingleSubProduct(
ctx context.Context,
params []byte,
deps *processors.ProcessorDependencies,
item *entities.ProductPackageItem,
) *SubProductResult {
result := &SubProductResult{
ApiCode: item.Product.Code,
SortOrder: item.SortOrder,
Success: false,
}
// 查找对应的处理器
processor, exists := cs.processorRegistry[item.Product.Code]
if !exists {
result.Error = fmt.Sprintf("未找到处理器: %s", item.Product.Code)
return result
}
// 调用处理器
respBytes, err := processor(ctx, params, deps)
if err != nil {
result.Error = err.Error()
return result
}
// 解析响应
var responseData interface{}
if err := json.Unmarshal(respBytes, &responseData); err != nil {
result.Error = fmt.Sprintf("解析响应失败: %s", err.Error())
return result
}
result.Success = true
result.Data = responseData
return result
}
// combineResults 组合所有子产品的结果
func (cs *CombService) combineResults(results []*SubProductResult) ([]byte, error) {
// 构建组合结果
combinedResult := &CombinedResult{
Responses: results,
}
// 序列化结果
respBytes, err := json.Marshal(combinedResult)
if err != nil {
return nil, fmt.Errorf("序列化组合结果失败: %s", err.Error())
}
return respBytes, nil
}
// SubProductResult 子产品处理结果
type SubProductResult struct {
ApiCode string `json:"api_code"` // 子接口标识
Data interface{} `json:"data"` // 子接口返回数据
Success bool `json:"success"` // 是否成功
Error string `json:"error,omitempty"` // 错误信息(仅在失败时)
SortOrder int `json:"-"` // 排序字段不输出到JSON
}
// CombinedResult 组合结果
type CombinedResult struct {
Responses []*SubProductResult `json:"responses"` // 子接口响应列表
}