@@ -294,23 +294,26 @@ func (m *TCPManager) RegisterWithAgent(ctx context.Context, serviceID, serviceVe
294294 m .heartbeatStop = cancel
295295 go m .heartbeatLoop (ctx )
296296
297- // 控制面 manifest 上传(best-effort,不阻断注册结果)
298- m .maybeRegisterCapabilities ()
297+ // 控制面 manifest 上传(审查发现 #2):fire-and-forget——控制面慢/
298+ // 不可达时不得拖慢注册主路径(同步执行最长 10s)。参数全部取
299+ // 快照传值,避免与后续重注册竞态。
300+ m .maybeRegisterCapabilitiesAsync ()
299301
300302 return m .sessionID , nil
301303}
302304
303305// buildManifest 构建供控制面注册的能力清单(provider 元数据 + 函数摘要),
304306// 与 JS/C# 参考实现同构。
305- func (m * TCPManager ) buildManifest () map [string ]interface {} {
307+ func (m * TCPManager ) buildManifest (serviceID , serviceVersion string ,
308+ functions []* sdkv1.ProviderFunctionDescriptor ) map [string ]interface {} {
306309 provider := map [string ]interface {}{
307- "id" : orDefault (m . serviceID , "go-service" ),
308- "version" : orDefault (m . serviceVersion , "1.0.0" ),
310+ "id" : orDefault (serviceID , "go-service" ),
311+ "version" : orDefault (serviceVersion , "1.0.0" ),
309312 "lang" : orDefault (m .config .ProviderLang , "go" ),
310313 "sdk" : orDefault (m .config .ProviderSDK , "croupier-go-sdk" ),
311314 }
312- functions := make ([]map [string ]interface {}, 0 , len (m . functions ))
313- for _ , descriptor := range m . functions {
315+ entries := make ([]map [string ]interface {}, 0 , len (functions ))
316+ for _ , descriptor := range functions {
314317 if descriptor == nil || strings .TrimSpace (descriptor .Id ) == "" {
315318 continue
316319 }
@@ -339,9 +342,9 @@ func (m *TCPManager) buildManifest() map[string]interface{} {
339342 if descriptor .OutputSchema != "" {
340343 entry ["outputSchema" ] = json .RawMessage (descriptor .OutputSchema )
341344 }
342- functions = append (functions , entry )
345+ entries = append (entries , entry )
343346 }
344- return map [string ]interface {}{"provider" : provider , "functions" : functions }
347+ return map [string ]interface {}{"provider" : provider , "functions" : entries }
345348}
346349
347350func orDefault (value , fallback string ) string {
@@ -364,14 +367,31 @@ func gzipBytes(data []byte) ([]byte, error) {
364367 return buf .Bytes (), nil
365368}
366369
370+ // maybeRegisterCapabilitiesAsync 异步 fire-and-forget:先快照上传所需
371+ // 状态(functions 会在重注册时整体替换),再交后台执行——注册主路径
372+ // 不再被控制面连接/调用阻塞(审查发现 #2)。
373+ func (m * TCPManager ) maybeRegisterCapabilitiesAsync () {
374+ if strings .TrimSpace (m .config .ControlAddr ) == "" {
375+ return
376+ }
377+ m .mu .RLock ()
378+ serviceID , serviceVersion := m .serviceID , m .serviceVersion
379+ functions := make ([]* sdkv1.ProviderFunctionDescriptor , len (m .functions ))
380+ copy (functions , m .functions )
381+ m .mu .RUnlock ()
382+
383+ go m .maybeRegisterCapabilities (serviceID , serviceVersion , functions )
384+ }
385+
367386// maybeRegisterCapabilities 向控制面(config.ControlAddr)上传能力清单。
368387// 独立短连接 + 5s 超时;任何失败仅告警,不影响已完成的函数注册。
369- func (m * TCPManager ) maybeRegisterCapabilities () {
388+ func (m * TCPManager ) maybeRegisterCapabilities (serviceID , serviceVersion string ,
389+ functions []* sdkv1.ProviderFunctionDescriptor ) {
370390 if strings .TrimSpace (m .config .ControlAddr ) == "" {
371391 return
372392 }
373393
374- manifestJSON , err := json .Marshal (m .buildManifest ())
394+ manifestJSON , err := json .Marshal (m .buildManifest (serviceID , serviceVersion , functions ))
375395 if err != nil {
376396 logWarnf ("register capabilities: marshal manifest: %v" , err )
377397 return
0 commit comments