fix(notify): 根治低带宽控制面阻塞与传输写入卡死

- 为控制消息增加优先级、公平调度、队列字节预算和自适应批处理
- 支持可取消的写门等待,收紧 shared/dedicated bulk、stream 和 Reply 写入边界
- 修复 bulk reset/close、连接 handoff 和安全 profile 切换时序
- 保留旧取消与超时错误契约,新增阶段化 TransportSendError
- 增加 ReplyCtx、ReplyObjCtx、写超时配置及黑洞连接和竞态回归测试
This commit is contained in:
2026-08-14 10:16:37 +08:00
parent 98ef9e7fcc
commit 0826e17063
45 changed files with 4231 additions and 293 deletions
+30 -11
View File
@@ -9,9 +9,20 @@ import (
)
func (c *ClientCommon) send(msg TransferMsg) (WaitMsg, error) {
return c.sendWithContext(context.Background(), msg)
}
func (c *ClientCommon) sendWithContext(ctx context.Context, msg TransferMsg) (WaitMsg, error) {
return c.sendWithContextTimeout(ctx, msg, 0)
}
func (c *ClientCommon) sendWithContextTimeout(ctx context.Context, msg TransferMsg, writeTimeout time.Duration) (WaitMsg, error) {
if err := c.ensureClientSendReady(); err != nil {
return WaitMsg{}, err
}
if ctx == nil {
ctx = context.Background()
}
var wait WaitMsg
if msg.Type != MSG_SYNC_REPLY && msg.Type != MSG_KEY_CHANGE && msg.Type != MSG_SYS_REPLY || msg.ID == 0 {
msg.ID = atomic.AddUint64(&c.msgID, 1)
@@ -20,6 +31,8 @@ func (c *ClientCommon) send(msg TransferMsg) (WaitMsg, error) {
if err != nil {
return WaitMsg{}, err
}
env.controlCtx = ctx
env.controlTimeout = writeTimeout
if requiresSignalReplyWait(msg) {
wait = c.getPendingWaitPool().createAndStore(msg)
}
@@ -42,9 +55,9 @@ func (c *ClientCommon) sendEnvelope(env Envelope) error {
return err
}
if batchedControlEnvelope(env) {
return c.writeControlPayloadToTransport(payload)
return c.writeControlPayloadToTransportTimeout(env.controlContext(), payload, env.controlPriority, env.controlTimeout)
}
return c.writePayloadToTransport(payload)
return c.writePayloadToTransportContextTimeout(env.controlContext(), payload, env.controlTimeout)
}
func (c *ClientCommon) dispatchEnvelope(env Envelope, now time.Time) {
@@ -90,12 +103,18 @@ func (c *ClientCommon) Send(key string, value MsgVal) error {
}
func (c *ClientCommon) sendWait(msg TransferMsg, timeout time.Duration) (Message, error) {
data, err := c.send(msg)
ctx := context.Background()
cancel := func() {}
if timeout != 0 {
ctx, cancel = context.WithTimeout(ctx, timeout)
}
defer cancel()
data, err := c.sendWithContext(ctx, msg)
if err != nil {
return Message{}, err
return Message{}, publicContextSendError(ctx, err)
}
stopCh := sessionStopChan(c.clientStopContextSnapshot())
if timeout.Seconds() == 0 {
if timeout == 0 {
msg, ok := <-data.Reply
if !ok {
return msg, pendingWaitClosedErrorWith(stopCh, clientTransportDetachedError(c))
@@ -103,7 +122,7 @@ func (c *ClientCommon) sendWait(msg TransferMsg, timeout time.Duration) (Message
return msg, nil
}
select {
case <-time.After(timeout):
case <-ctx.Done():
c.getPendingWaitPool().removeAndClose(data.TransferMsg.ID)
return Message{}, os.ErrDeadlineExceeded
case <-stopCh:
@@ -117,14 +136,14 @@ func (c *ClientCommon) sendWait(msg TransferMsg, timeout time.Duration) (Message
}
func (c *ClientCommon) sendCtx(msg TransferMsg, ctx context.Context) (Message, error) {
data, err := c.send(msg)
if err != nil {
return Message{}, err
}
stopCh := sessionStopChan(c.clientStopContextSnapshot())
if ctx == nil {
ctx = context.Background()
}
data, err := c.sendWithContext(ctx, msg)
if err != nil {
return Message{}, publicContextSendError(ctx, err)
}
stopCh := sessionStopChan(c.clientStopContextSnapshot())
select {
case <-ctx.Done():
c.getPendingWaitPool().removeAndClose(data.TransferMsg.ID)