fix(notify): 根治低带宽控制面阻塞与传输写入卡死
- 为控制消息增加优先级、公平调度、队列字节预算和自适应批处理 - 支持可取消的写门等待,收紧 shared/dedicated bulk、stream 和 Reply 写入边界 - 修复 bulk reset/close、连接 handoff 和安全 profile 切换时序 - 保留旧取消与超时错误契约,新增阶段化 TransportSendError - 增加 ReplyCtx、ReplyObjCtx、写超时配置及黑洞连接和竞态回归测试
This commit is contained in:
+111
-2
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -74,7 +76,6 @@ func TestClientSendCtxReturnsContextCanceled(t *testing.T) {
|
||||
server := newRunningPeerAttachServerForTest(t, func(server *ServerCommon) {
|
||||
server.SetSecretKey(secret)
|
||||
})
|
||||
|
||||
left, right := net.Pipe()
|
||||
defer right.Close()
|
||||
bootstrapPeerAttachConnForTest(t, server, right)
|
||||
@@ -101,7 +102,6 @@ func TestServerSendCtxReturnsContextCanceled(t *testing.T) {
|
||||
server := newRunningPeerAttachServerForTest(t, func(server *ServerCommon) {
|
||||
server.SetSecretKey(secret)
|
||||
})
|
||||
|
||||
left, right := net.Pipe()
|
||||
defer right.Close()
|
||||
bootstrapPeerAttachConnForTest(t, server, right)
|
||||
@@ -133,3 +133,112 @@ func TestServerSendCtxReturnsContextCanceled(t *testing.T) {
|
||||
t.Fatalf("server SendCtxLogical error = %v, want %v", err, context.Canceled)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReplyWaitPreservesLegacyDeadlineAndCancelSentinels(t *testing.T) {
|
||||
client := NewClient().(*ClientCommon)
|
||||
secret := []byte("0123456789abcdef0123456789abcdef")
|
||||
client.SetSecretKey(secret)
|
||||
server := newRunningPeerAttachServerForTest(t, func(server *ServerCommon) {
|
||||
server.SetSecretKey(secret)
|
||||
})
|
||||
clientCancelCtx, clientCancel := context.WithCancel(context.Background())
|
||||
serverCancelCtx, serverCancel := context.WithCancel(context.Background())
|
||||
server.SetLink("client-wait-timeout", func(*Message) {})
|
||||
server.SetLink("client-ctx-cancel", func(*Message) { clientCancel() })
|
||||
client.SetLink("server-wait-timeout", func(*Message) {})
|
||||
client.SetLink("server-ctx-cancel", func(*Message) { serverCancel() })
|
||||
|
||||
left, right := net.Pipe()
|
||||
t.Cleanup(func() { _ = right.Close() })
|
||||
bootstrapPeerAttachConnForTest(t, server, right)
|
||||
if err := client.ConnectByConn(left); err != nil {
|
||||
t.Fatalf("client ConnectByConn failed: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
client.setByeFromServer(true)
|
||||
_ = client.Stop()
|
||||
})
|
||||
|
||||
var logical *LogicalConn
|
||||
deadline := time.Now().Add(time.Second)
|
||||
for time.Now().Before(deadline) {
|
||||
logical = server.GetLogicalConn(client.peerIdentity)
|
||||
if logical != nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
if logical == nil {
|
||||
t.Fatal("server logical conn not found")
|
||||
}
|
||||
|
||||
if _, err := client.SendWait("client-wait-timeout", []byte("payload"), 50*time.Millisecond); err != os.ErrDeadlineExceeded {
|
||||
t.Fatalf("client SendWait error=%#v, want exact os.ErrDeadlineExceeded", err)
|
||||
}
|
||||
|
||||
if _, err := client.SendCtx(clientCancelCtx, "client-ctx-cancel", []byte("payload")); err != context.Canceled {
|
||||
t.Fatalf("client SendCtx error=%#v, want exact context.Canceled", err)
|
||||
}
|
||||
|
||||
if _, err := server.SendWaitLogical(logical, "server-wait-timeout", []byte("payload"), 50*time.Millisecond); err != os.ErrDeadlineExceeded {
|
||||
t.Fatalf("server SendWaitLogical error=%#v, want exact os.ErrDeadlineExceeded", err)
|
||||
}
|
||||
|
||||
if _, err := server.SendCtxLogical(serverCancelCtx, logical, "server-ctx-cancel", []byte("payload")); err != context.Canceled {
|
||||
t.Fatalf("server SendCtxLogical error=%#v, want exact context.Canceled", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetLinkIsSafeDuringConcurrentDispatch(t *testing.T) {
|
||||
t.Run("client", func(t *testing.T) {
|
||||
client := NewClient().(*ClientCommon)
|
||||
testConcurrentHandlerUpdateAndDispatch(
|
||||
t,
|
||||
client.SetLink,
|
||||
client.SetDefaultLink,
|
||||
client.dispatchMsg,
|
||||
)
|
||||
})
|
||||
t.Run("server", func(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
testConcurrentHandlerUpdateAndDispatch(
|
||||
t,
|
||||
server.SetLink,
|
||||
server.SetDefaultLink,
|
||||
server.dispatchMsg,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
func testConcurrentHandlerUpdateAndDispatch(
|
||||
t *testing.T,
|
||||
setLink func(string, func(*Message)),
|
||||
setDefault func(func(*Message)),
|
||||
dispatch func(Message),
|
||||
) {
|
||||
t.Helper()
|
||||
const iterations = 1000
|
||||
start := make(chan struct{})
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
<-start
|
||||
for i := 0; i < iterations; i++ {
|
||||
setLink("concurrent-handler", func(*Message) {})
|
||||
setDefault(func(*Message) {})
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
<-start
|
||||
for i := 0; i < iterations; i++ {
|
||||
dispatch(Message{TransferMsg: TransferMsg{
|
||||
Key: "concurrent-handler",
|
||||
Type: MSG_ASYNC,
|
||||
}})
|
||||
}
|
||||
}()
|
||||
close(start)
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user