// Package mesh ... // // Description : mesh ... // // Author : go_developer@163.com<白茶清欢> // // Date : 2025-03-28 14:11 package mesh import ( "context" "git.zhangdeman.cn/zhangdeman/network/httpclient" "sync" ) func Request(req *RequestConfig, receiver any) *Response { if nil == req.Ctx { req.Ctx = context.Background() } c := &client{ resp: &Response{ IsSuccess: false, ErrorCode: "", ErrorMessage: "", Raw: nil, DataMap: nil, AliasResultTable: make(map[string]*Response), Lock: &sync.RWMutex{}, }, reqCfg: req, receiver: receiver, } return c.Request() } type client struct { ctx context.Context resp *Response reqCfg *RequestConfig receiver any } func (c *client) Request() *Response { for _, itemGroup := range c.reqCfg.Group { if !c.doRequest(itemGroup) { break } } return c.resp } // doRequest 返回是否继续 // // Author : go_developer@163.com<白茶清欢> // // Date : 15:30 2025/3/28 func (c *client) doRequest(apiList []*RequestConfigGroupItem) bool { if len(apiList) == 0 { return true } // 初始化请求配置, 并获取 http client 实例 httpClientList := make([]*httpclient.HttpClient, 0) for _, apiCfg := range apiList { var ( err error httpClient *httpclient.HttpClient ) // 初始化一下请求 c.initApiCfg(apiCfg) if httpClient, err = httpclient.NewHttpClient(apiCfg.RequestCfg, apiCfg.CacheInstance); nil != err { // 此处获取客户端实例即发生异常, 忽略一切配置, 直接作为全局失败, 后续也不请求了 c.resp.ErrorCode = "-500" c.resp.ErrorMessage = err.Error() return false } httpClientList = append(httpClientList, httpClient) } isContinue := true wg := &sync.WaitGroup{} for idx, apiCfg := range apiList { wg.Add(1) go func(clientIdx int, apiCfg *RequestConfigGroupItem) { defer func() { if err := recover(); nil != err { } wg.Done() }() // TODO : 判断是否已经是最终失败 resp := httpClientList[clientIdx].Request() c.resp.Lock.Lock() defer c.resp.Lock.Unlock() if !resp.IsSuccess { } }(idx, apiCfg) } wg.Wait() return isContinue } func (c *client) initApiCfg(apiCfg *RequestConfigGroupItem) { if apiCfg.FailBehavior == nil { apiCfg.FailBehavior = &RequestConfigGroupItemFailBehavior{ Action: FailBehaviorError, // 默认失败终止请求 FinalFailure: true, // 默认一旦失败,则争个整个失败 } } if apiCfg.FailBehavior.Action == FailBehaviorError { // 配置了请求失败则报错, 一定是导致结果最终失败 apiCfg.FailBehavior.FinalFailure = true } // 每一个请求有独立的context apiCfg.RequestCfg.Ctx = context.WithValue(c.reqCfg.Ctx, "alias", apiCfg.Alias) }