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
+53
View File
@@ -1,12 +1,27 @@
package notify
import (
"b612.me/stario"
"context"
"errors"
"math"
"net"
"sync"
"testing"
"time"
)
type bulkReleaseTrackingConn struct {
net.Conn
started chan struct{}
once sync.Once
}
func (c *bulkReleaseTrackingConn) Write(p []byte) (int, error) {
c.once.Do(func() { close(c.started) })
return c.Conn.Write(p)
}
func TestBulkOwnedChunkReleaseAfterRead(t *testing.T) {
bulk := newBulkHandle(context.Background(), newBulkRuntime("buffer-release-read"), clientFileScope(), BulkOpenRequest{
BulkID: "buffer-release-read",
@@ -117,3 +132,41 @@ func TestBulkReadDoesNotBlockOnAsyncWindowRelease(t *testing.T) {
}
}
}
func TestLegacyBulkReleaseHonorsBulkCancellation(t *testing.T) {
client := NewClient().(*ClientCommon)
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatal(err)
}
stopCtx, stopFn := context.WithCancel(context.Background())
defer stopFn()
pipeLeft, right := net.Pipe()
left := &bulkReleaseTrackingConn{Conn: pipeLeft, started: make(chan struct{})}
defer left.Close()
defer right.Close()
queue := stario.NewQueueCtx(stopCtx, 4, math.MaxUint32)
client.setClientSessionRuntime(newClientSessionRuntime(left, stopCtx, stopFn, queue, 1))
client.markSessionStarted()
bulk := newBulkHandle(context.Background(), nil, "test", BulkOpenRequest{
BulkID: "legacy-release",
DataID: 1,
FastPathVersion: bulkFastPathVersionV1,
ChunkSize: 4,
WindowBytes: 4,
MaxInFlight: 1,
}, 0, nil, nil, 0, nil, nil, nil, nil, clientBulkReleaseSender(client))
bulk.maybeSendWindowRelease(4, true)
select {
case <-left.started:
case <-time.After(time.Second):
t.Fatal("legacy release did not enter physical write")
}
bulk.finalize()
select {
case <-bulk.releaseWorkerDone:
case <-time.After(150 * time.Millisecond):
t.Fatal("legacy bulk release worker ignored bulk cancellation while its send was blocked")
}
}