feat: 完善 RecordStream 的协议协商、运行观测与文档说明
- 将 RecordStream 出站路径收敛为单 writer loop - 支持在 batch header 中 piggyback AckSeq,保留独立 ack 作为兼容回退 - 增加 record stream 打开阶段能力协商,支持 mixed-version peer 自动降级 - 补充 RecordSnapshot 与 diagnostics summary 的 record-plane 观测项 - 增加 batch/ack/error frame、piggyback ack、barrier 等待拆分与 apply backlog 指标 - 收紧 TransportConn detach 后的 runtime snapshot 语义 - 补充 README 中的 RecordStream 语义、兼容行为与诊断快照说明 - 补充相关单测与 race 回归验证
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package notify
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNegotiateRecordStreamOpenMetadataEnablesBatchAck(t *testing.T) {
|
||||
reqMetadata, respMetadata := negotiateRecordStreamOpenMetadata(StreamRecordChannel, StreamMetadata{
|
||||
recordStreamMetadataCapBatchAckKey: recordStreamMetadataEnabledValue,
|
||||
})
|
||||
if !recordStreamUseBatchAck(reqMetadata) {
|
||||
t.Fatal("request metadata should enable batch ack")
|
||||
}
|
||||
if !recordStreamUseBatchAck(respMetadata) {
|
||||
t.Fatal("response metadata should enable batch ack")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegotiateRecordStreamOpenMetadataKeepsFallbackWithoutCapability(t *testing.T) {
|
||||
reqMetadata, respMetadata := negotiateRecordStreamOpenMetadata(StreamRecordChannel, nil)
|
||||
if recordStreamUseBatchAck(reqMetadata) {
|
||||
t.Fatalf("request metadata should keep fallback mode: %+v", reqMetadata)
|
||||
}
|
||||
if recordStreamUseBatchAck(respMetadata) {
|
||||
t.Fatalf("response metadata should keep fallback mode: %+v", respMetadata)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenRecordStreamNegotiatesBatchAck(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
secret := []byte("0123456789abcdef0123456789abcdef")
|
||||
server = newRunningPeerAttachServerForTest(t, func(server *ServerCommon) {
|
||||
server.SetSecretKey(secret)
|
||||
})
|
||||
|
||||
acceptedCh := make(chan RecordAcceptInfo, 1)
|
||||
server.SetRecordStreamHandler(func(info RecordAcceptInfo) error {
|
||||
acceptedCh <- info
|
||||
return nil
|
||||
})
|
||||
|
||||
client := NewClient().(*ClientCommon)
|
||||
client.SetSecretKey(secret)
|
||||
left, right := net.Pipe()
|
||||
defer right.Close()
|
||||
bootstrapPeerAttachConnForTest(t, server, right)
|
||||
if err := client.ConnectByConn(left); err != nil {
|
||||
t.Fatalf("client ConnectByConn failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
client.setByeFromServer(true)
|
||||
_ = client.Stop()
|
||||
}()
|
||||
|
||||
record, err := client.OpenRecordStream(context.Background(), RecordOpenOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("OpenRecordStream failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = record.Close()
|
||||
}()
|
||||
|
||||
if !recordStreamUseBatchAck(record.Metadata()) {
|
||||
t.Fatalf("client record stream metadata should negotiate batch ack: %+v", record.Metadata())
|
||||
}
|
||||
|
||||
select {
|
||||
case accepted := <-acceptedCh:
|
||||
if !recordStreamUseBatchAck(accepted.Metadata) {
|
||||
t.Fatalf("accepted record metadata should negotiate batch ack: %+v", accepted.Metadata)
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("timed out waiting accepted record stream")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user