fix: close stream adaptive gaps and switch notify to stario v0.1.1

- make stream fast path honor adaptive soft payload limits end-to-end
  - split oversized fast-stream payloads into sequential frames before batching
  - use adaptive soft cap when encoding stream batch payloads
  - move timeout-like error detection into production code for adaptive tx
  - tune notify FrameReader read size explicitly to avoid throughput regression
  - drop local stario replace and depend on released b612.me/stario v0.1.1
This commit is contained in:
2026-04-18 16:05:57 +08:00
parent 4f760f2807
commit f038a89771
76 changed files with 12656 additions and 906 deletions
+320 -3
View File
@@ -109,6 +109,9 @@ func TestBulkOpenRoundTripTCP(t *testing.T) {
if !clientSnapshots[0].BindingAlive || !clientSnapshots[0].BindingCurrent || !clientSnapshots[0].TransportAttached || !clientSnapshots[0].TransportCurrent {
t.Fatalf("client bulk binding snapshot mismatch: %+v", clientSnapshots[0])
}
if got, want := clientSnapshots[0].BindingBulkAdaptiveSoftPayloadBytes, bulkAdaptiveSoftPayloadStartBytes; got != want {
t.Fatalf("client bulk BindingBulkAdaptiveSoftPayloadBytes = %d, want %d", got, want)
}
serverSnapshots, err := GetServerBulkSnapshots(server)
if err != nil {
t.Fatalf("GetServerBulkSnapshots failed: %v", err)
@@ -119,6 +122,9 @@ func TestBulkOpenRoundTripTCP(t *testing.T) {
if got, want := serverSnapshots[0].BindingOwner, "server-transport"; got != want {
t.Fatalf("server bulk BindingOwner = %q, want %q", got, want)
}
if got, want := serverSnapshots[0].BindingBulkAdaptiveSoftPayloadBytes, bulkAdaptiveSoftPayloadStartBytes; got != want {
t.Fatalf("server bulk BindingBulkAdaptiveSoftPayloadBytes = %d, want %d", got, want)
}
if !serverSnapshots[0].BindingAlive || !serverSnapshots[0].BindingCurrent || !serverSnapshots[0].TransportAttached || !serverSnapshots[0].TransportCurrent {
t.Fatalf("server bulk binding snapshot mismatch: %+v", serverSnapshots[0])
}
@@ -135,6 +141,314 @@ func TestBulkOpenRoundTripTCP(t *testing.T) {
waitForBulkContextDone(t, bulk.Context(), 2*time.Second)
}
func TestDedicatedBulkOpenUnblocksSynchronousReadHandler(t *testing.T) {
server := NewServer().(*ServerCommon)
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatalf("UseModernPSKServer failed: %v", err)
}
readCh := make(chan string, 1)
server.SetBulkHandler(func(info BulkAcceptInfo) error {
defer func() {
_ = info.Bulk.Close()
}()
buf := make([]byte, 5)
if _, err := io.ReadFull(info.Bulk, buf); err != nil {
return err
}
readCh <- string(buf)
return nil
})
if err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
t.Fatalf("server Listen failed: %v", err)
}
defer func() {
_ = server.Stop()
}()
client := NewClient().(*ClientCommon)
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatalf("UseModernPSKClient failed: %v", err)
}
if err := client.Connect("tcp", server.listener.Addr().String()); err != nil {
t.Fatalf("client Connect failed: %v", err)
}
defer func() {
_ = client.Stop()
}()
type openResult struct {
bulk Bulk
err error
}
openCh := make(chan openResult, 1)
go func() {
bulk, err := client.OpenDedicatedBulk(context.Background(), BulkOpenOptions{
ID: "sync-read-handler",
Range: BulkRange{
Offset: 0,
Length: 5,
},
})
openCh <- openResult{bulk: bulk, err: err}
}()
var bulk Bulk
select {
case result := <-openCh:
if result.err != nil {
t.Fatalf("client OpenDedicatedBulk failed: %v", result.err)
}
bulk = result.bulk
case <-time.After(2 * time.Second):
t.Fatal("client OpenDedicatedBulk timed out while remote handler was synchronously reading")
}
defer func() {
if bulk != nil {
_ = bulk.Close()
}
}()
if _, err := bulk.Write([]byte("hello")); err != nil {
t.Fatalf("client dedicated bulk Write failed: %v", err)
}
select {
case got := <-readCh:
if got != "hello" {
t.Fatalf("server handler read %q, want %q", got, "hello")
}
case <-time.After(2 * time.Second):
t.Fatal("timed out waiting for synchronous handler read")
}
}
func TestDedicatedBulkOpenUnblocksOnBlockingFirstWrite(t *testing.T) {
server := NewServer().(*ServerCommon)
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatalf("UseModernPSKServer failed: %v", err)
}
payload := strings.Repeat("w", 16)
writeDone := make(chan error, 1)
server.SetBulkHandler(func(info BulkAcceptInfo) error {
_, err := io.WriteString(info.Bulk, payload)
if err == nil {
err = info.Bulk.CloseWrite()
}
writeDone <- err
return err
})
if err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
t.Fatalf("server Listen failed: %v", err)
}
defer func() {
_ = server.Stop()
}()
client := NewClient().(*ClientCommon)
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatalf("UseModernPSKClient failed: %v", err)
}
if err := client.Connect("tcp", server.listener.Addr().String()); err != nil {
t.Fatalf("client Connect failed: %v", err)
}
defer func() {
_ = client.Stop()
}()
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
bulk, err := client.OpenDedicatedBulk(ctx, BulkOpenOptions{
ID: "blocking-write-ready",
Range: BulkRange{
Offset: 0,
Length: int64(len(payload)),
},
ChunkSize: 4,
WindowBytes: 4,
MaxInFlight: 1,
})
if err != nil {
t.Fatalf("client OpenDedicatedBulk failed: %v", err)
}
readBulkExactly(t, bulk, payload, 2*time.Second)
waitForBulkReadEOF(t, bulk, 2*time.Second)
select {
case err := <-writeDone:
if err != nil {
t.Fatalf("server handler write failed: %v", err)
}
case <-time.After(2 * time.Second):
t.Fatal("timed out waiting for blocking first write to finish")
}
if err := bulk.Close(); err != nil {
t.Fatalf("client dedicated bulk Close failed: %v", err)
}
waitForBulkContextDone(t, bulk.Context(), 2*time.Second)
}
func TestServerOpenBulkLogicalDedicatedUnblocksOnBlockingFirstRead(t *testing.T) {
server := NewServer().(*ServerCommon)
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatalf("UseModernPSKServer failed: %v", err)
}
if err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
t.Fatalf("server Listen failed: %v", err)
}
defer func() {
_ = server.Stop()
}()
client := NewClient().(*ClientCommon)
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatalf("UseModernPSKClient failed: %v", err)
}
readCh := make(chan string, 1)
client.SetBulkHandler(func(info BulkAcceptInfo) error {
defer func() {
_ = info.Bulk.Close()
}()
buf := make([]byte, 5)
if _, err := io.ReadFull(info.Bulk, buf); err != nil {
return err
}
readCh <- string(buf)
return nil
})
if err := client.Connect("tcp", server.listener.Addr().String()); err != nil {
t.Fatalf("client Connect failed: %v", err)
}
defer func() {
_ = client.Stop()
}()
logical := waitForTransferControlLogicalConn(t, server, 2*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
bulk, err := server.OpenBulkLogical(ctx, logical, BulkOpenOptions{
ID: "server-blocking-read-ready",
Range: BulkRange{
Offset: 0,
Length: 5,
},
Dedicated: true,
})
if err != nil {
t.Fatalf("server OpenBulkLogical dedicated failed: %v", err)
}
if _, err := bulk.Write([]byte("hello")); err != nil {
t.Fatalf("server dedicated bulk Write failed: %v", err)
}
select {
case got := <-readCh:
if got != "hello" {
t.Fatalf("client handler read %q, want %q", got, "hello")
}
case <-time.After(2 * time.Second):
t.Fatal("timed out waiting for blocking first read to finish")
}
if err := bulk.Close(); err != nil {
t.Fatalf("server dedicated bulk Close failed: %v", err)
}
waitForBulkContextDone(t, bulk.Context(), 2*time.Second)
}
func TestDedicatedBulkOpenReturnsHandlerFailureAfterAccepted(t *testing.T) {
server := NewServer().(*ServerCommon)
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatalf("UseModernPSKServer failed: %v", err)
}
server.SetBulkHandler(func(info BulkAcceptInfo) error {
time.Sleep(80 * time.Millisecond)
return errors.New("dedicated handler failed after accept")
})
if err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
t.Fatalf("server Listen failed: %v", err)
}
defer func() {
_ = server.Stop()
}()
client := NewClient().(*ClientCommon)
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatalf("UseModernPSKClient failed: %v", err)
}
if err := client.Connect("tcp", server.listener.Addr().String()); err != nil {
t.Fatalf("client Connect failed: %v", err)
}
defer func() {
_ = client.Stop()
}()
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
_, err := client.OpenDedicatedBulk(ctx, BulkOpenOptions{
ID: "accepted-then-fail",
Range: BulkRange{
Offset: 0,
Length: 1,
},
})
if err == nil || !strings.Contains(err.Error(), "dedicated handler failed after accept") {
t.Fatalf("client OpenDedicatedBulk error = %v, want dedicated handler failure after accept", err)
}
}
func TestServerOpenBulkLogicalDedicatedReturnsHandlerFailureAfterAccepted(t *testing.T) {
server := NewServer().(*ServerCommon)
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatalf("UseModernPSKServer failed: %v", err)
}
if err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
t.Fatalf("server Listen failed: %v", err)
}
defer func() {
_ = server.Stop()
}()
client := NewClient().(*ClientCommon)
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
t.Fatalf("UseModernPSKClient failed: %v", err)
}
client.SetBulkHandler(func(info BulkAcceptInfo) error {
time.Sleep(80 * time.Millisecond)
return errors.New("client dedicated handler failed after accept")
})
if err := client.Connect("tcp", server.listener.Addr().String()); err != nil {
t.Fatalf("client Connect failed: %v", err)
}
defer func() {
_ = client.Stop()
}()
logical := waitForTransferControlLogicalConn(t, server, 2*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
_, err := server.OpenBulkLogical(ctx, logical, BulkOpenOptions{
ID: "server-accepted-then-fail",
Range: BulkRange{
Offset: 0,
Length: 1,
},
Dedicated: true,
})
if err == nil || !strings.Contains(err.Error(), "client dedicated handler failed after accept") {
t.Fatalf("server OpenBulkLogical dedicated error = %v, want client dedicated handler failure after accept", err)
}
}
func TestBulkOpenRoundTripServerLogicalTCP(t *testing.T) {
server := NewServer().(*ServerCommon)
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
@@ -532,15 +846,18 @@ func TestDedicatedBulkWritePrefersClosedPipeOverContextCanceled(t *testing.T) {
MaxInFlight: 4,
}, 0, nil, nil, 0, nil, nil, func(context.Context, *bulkHandle, []byte) error {
return nil
}, func(ctx context.Context, bulk *bulkHandle, payload []byte) (int, error) {
}, func(ctx context.Context, bulk *bulkHandle, startSeq uint64, payload []byte, payloadOwned bool) (int, error) {
bulk.markPeerClosed()
<-ctx.Done()
return 0, ctx.Err()
}, nil)
_, err := bulk.Write([]byte("abcdefgh"))
if !errors.Is(err, io.ErrClosedPipe) {
t.Fatalf("bulk Write error = %v, want %v", err, io.ErrClosedPipe)
if err != nil && !errors.Is(err, io.ErrClosedPipe) {
t.Fatalf("bulk Write error = %v, want nil or %v", err, io.ErrClosedPipe)
}
if err := bulk.waitPendingAsyncWrites(context.Background()); err != nil && !errors.Is(err, io.ErrClosedPipe) {
t.Fatalf("bulk waitPendingAsyncWrites error = %v, want nil or %v", err, io.ErrClosedPipe)
}
}