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:
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -136,6 +137,7 @@ func TestHandleBulkAttachSystemMessageAcceptedWritesDirectReplyBeforeDedicatedHa
|
||||
Dedicated: true,
|
||||
AttachToken: "attach-token",
|
||||
}, 0, target, nil, 0, nil, nil, nil, nil, nil)
|
||||
bulk.markAcceptHandled()
|
||||
if err := server.getBulkRuntime().register(serverFileScope(target), bulk); err != nil {
|
||||
t.Fatalf("register bulk runtime failed: %v", err)
|
||||
}
|
||||
@@ -215,3 +217,251 @@ func TestHandleBulkAttachSystemMessageAcceptedWritesDirectReplyBeforeDedicatedHa
|
||||
t.Fatalf("attach sidecar logical should be removed after handoff, got %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleBulkAttachSystemMessageDoesNotExposeSharedSidecarBeforeReplyCompletes(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
UseLegacySecurityServer(server)
|
||||
|
||||
sidecarLeft, sidecarRight := net.Pipe()
|
||||
defer sidecarRight.Close()
|
||||
|
||||
current := server.bootstrapAcceptedLogical("dedicated-attach-current-blocked", nil, sidecarLeft)
|
||||
if current == nil {
|
||||
t.Fatal("bootstrapAcceptedLogical(current) should return logical")
|
||||
}
|
||||
target := server.bootstrapAcceptedLogical("dedicated-attach-target-blocked", nil, nil)
|
||||
if target == nil {
|
||||
t.Fatal("bootstrapAcceptedLogical(target) should return logical")
|
||||
}
|
||||
|
||||
currentBulk := newBulkHandle(context.Background(), server.getBulkRuntime(), serverFileScope(target), BulkOpenRequest{
|
||||
BulkID: "server-dedicated-current",
|
||||
DataID: 17,
|
||||
Dedicated: true,
|
||||
AttachToken: "attach-token",
|
||||
}, 0, target, nil, 0, nil, nil, nil, nil, nil)
|
||||
currentBulk.markAcceptHandled()
|
||||
if err := server.getBulkRuntime().register(serverFileScope(target), currentBulk); err != nil {
|
||||
t.Fatalf("register current bulk runtime failed: %v", err)
|
||||
}
|
||||
|
||||
pendingBulk := newBulkHandle(context.Background(), server.getBulkRuntime(), serverFileScope(target), BulkOpenRequest{
|
||||
BulkID: "server-dedicated-pending",
|
||||
DataID: 18,
|
||||
Dedicated: true,
|
||||
AttachToken: "attach-token-2",
|
||||
}, 0, target, nil, 0, nil, nil, nil, nil, nil)
|
||||
pendingBulk.markAcceptHandled()
|
||||
if err := server.getBulkRuntime().register(serverFileScope(target), pendingBulk); err != nil {
|
||||
t.Fatalf("register pending bulk runtime failed: %v", err)
|
||||
}
|
||||
|
||||
reqPayload, err := server.sequenceEn(bulkAttachRequest{
|
||||
PeerID: target.ID(),
|
||||
BulkID: currentBulk.ID(),
|
||||
AttachToken: "attach-token",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("encode bulkAttachRequest failed: %v", err)
|
||||
}
|
||||
msg := Message{
|
||||
NetType: NET_SERVER,
|
||||
LogicalConn: current,
|
||||
ClientConn: current.compatClientConn(),
|
||||
TransferMsg: TransferMsg{
|
||||
ID: 77,
|
||||
Key: systemBulkAttachKey,
|
||||
Value: reqPayload,
|
||||
Type: MSG_SYS_WAIT,
|
||||
},
|
||||
inboundConn: sidecarLeft,
|
||||
Time: time.Now(),
|
||||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
_ = server.handleBulkAttachSystemMessage(msg)
|
||||
}()
|
||||
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
if got := pendingBulk.dedicatedConnSnapshot(); got != nil {
|
||||
t.Fatal("pending dedicated bulk should not observe shared sidecar before attach reply is fully sent")
|
||||
}
|
||||
if got := server.serverDedicatedSidecarSnapshot(target); got != nil {
|
||||
t.Fatal("server dedicated sidecar should not be published before attach reply is fully sent")
|
||||
}
|
||||
|
||||
type attachReplyResult struct {
|
||||
transfer TransferMsg
|
||||
resp bulkAttachResponse
|
||||
err error
|
||||
}
|
||||
replyCh := make(chan attachReplyResult, 1)
|
||||
go func() {
|
||||
_ = sidecarRight.SetReadDeadline(time.Now().Add(time.Second))
|
||||
replyPayload, err := readDirectSignalFramePayload(sidecarRight)
|
||||
if err != nil {
|
||||
replyCh <- attachReplyResult{err: err}
|
||||
return
|
||||
}
|
||||
transfer, err := decodeDirectSignalPayload(server.sequenceDe, current.msgDeSnapshot(), current.secretKeySnapshot(), replyPayload)
|
||||
if err != nil {
|
||||
replyCh <- attachReplyResult{err: err}
|
||||
return
|
||||
}
|
||||
resp, err := decodeBulkAttachResponse(server.sequenceDe, transfer.Value)
|
||||
replyCh <- attachReplyResult{transfer: transfer, resp: resp, err: err}
|
||||
}()
|
||||
|
||||
select {
|
||||
case result := <-replyCh:
|
||||
if result.err != nil {
|
||||
t.Fatalf("read direct attach reply failed: %v", result.err)
|
||||
}
|
||||
if !result.resp.Accepted {
|
||||
t.Fatalf("bulk attach response = %+v, want accepted", result.resp)
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("timed out waiting for direct attach reply")
|
||||
}
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("timed out waiting for handleBulkAttachSystemMessage to finish")
|
||||
}
|
||||
|
||||
if got := pendingBulk.dedicatedConnSnapshot(); got != sidecarLeft {
|
||||
t.Fatalf("pending dedicated bulk conn mismatch after reply: got %v want %v", got, sidecarLeft)
|
||||
}
|
||||
if got := server.serverDedicatedSidecarSnapshot(target); got == nil || got.conn != sidecarLeft {
|
||||
t.Fatal("server dedicated sidecar should be published after attach reply completes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBulkAttachResponseErrorCarriesStructuredFields(t *testing.T) {
|
||||
resp := toBulkAttachResponseError(&bulkAttachError{
|
||||
Code: bulkAttachErrorCodeTokenMismatch,
|
||||
Retryable: false,
|
||||
Message: "bulk attach token mismatch",
|
||||
FailedSeq: 7,
|
||||
FailedBulk: "bulk-1",
|
||||
}, "fallback-bulk")
|
||||
|
||||
if resp.Accepted {
|
||||
t.Fatalf("Accepted = %v, want false", resp.Accepted)
|
||||
}
|
||||
if got, want := resp.Code, string(bulkAttachErrorCodeTokenMismatch); got != want {
|
||||
t.Fatalf("Code = %q, want %q", got, want)
|
||||
}
|
||||
if got, want := resp.Retryable, false; got != want {
|
||||
t.Fatalf("Retryable = %v, want %v", got, want)
|
||||
}
|
||||
if got, want := resp.FailedSeq, uint64(7); got != want {
|
||||
t.Fatalf("FailedSeq = %d, want %d", got, want)
|
||||
}
|
||||
if got, want := resp.FailedBulk, "bulk-1"; got != want {
|
||||
t.Fatalf("FailedBulk = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveInboundDedicatedBulkRejectsAlreadyAttachedAfterDataStarted(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
UseLegacySecurityServer(server)
|
||||
|
||||
currentLeft, currentRight := net.Pipe()
|
||||
defer currentRight.Close()
|
||||
current := server.bootstrapAcceptedLogical("dedicated-attach-current", nil, currentLeft)
|
||||
if current == nil {
|
||||
t.Fatal("bootstrapAcceptedLogical(current) should return logical")
|
||||
}
|
||||
target := server.bootstrapAcceptedLogical("dedicated-attach-target", nil, nil)
|
||||
if target == nil {
|
||||
t.Fatal("bootstrapAcceptedLogical(target) should return logical")
|
||||
}
|
||||
|
||||
bulk := newBulkHandle(context.Background(), server.getBulkRuntime(), serverFileScope(target), BulkOpenRequest{
|
||||
BulkID: "server-dedicated-attach-test",
|
||||
DataID: 7,
|
||||
Dedicated: true,
|
||||
AttachToken: "attach-token",
|
||||
}, 0, target, nil, 0, nil, nil, nil, nil, nil)
|
||||
bulk.markAcceptHandled()
|
||||
if err := server.getBulkRuntime().register(serverFileScope(target), bulk); err != nil {
|
||||
t.Fatalf("register bulk runtime failed: %v", err)
|
||||
}
|
||||
attachedLeft, attachedRight := net.Pipe()
|
||||
defer attachedRight.Close()
|
||||
if err := bulk.attachDedicatedConn(attachedLeft); err != nil {
|
||||
t.Fatalf("attachDedicatedConn failed: %v", err)
|
||||
}
|
||||
bulk.markDedicatedDataStarted()
|
||||
|
||||
_, _, err := server.resolveInboundDedicatedBulk(current, bulkAttachRequest{
|
||||
PeerID: target.ID(),
|
||||
BulkID: bulk.ID(),
|
||||
AttachToken: "attach-token",
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("resolveInboundDedicatedBulk should reject duplicate attach after data started")
|
||||
}
|
||||
var attachErr *bulkAttachError
|
||||
if !errors.As(err, &attachErr) || attachErr == nil {
|
||||
t.Fatalf("resolveInboundDedicatedBulk error type = %T, want *bulkAttachError", err)
|
||||
}
|
||||
if got, want := attachErr.Code, bulkAttachErrorCodeAlreadyAttached; got != want {
|
||||
t.Fatalf("attach error code = %q, want %q", got, want)
|
||||
}
|
||||
if attachErr.Retryable {
|
||||
t.Fatalf("attach error retryable = true, want false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveInboundDedicatedBulkAllowsReattachBeforeDataStarts(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
UseLegacySecurityServer(server)
|
||||
|
||||
currentLeft, currentRight := net.Pipe()
|
||||
defer currentRight.Close()
|
||||
current := server.bootstrapAcceptedLogical("dedicated-attach-current", nil, currentLeft)
|
||||
if current == nil {
|
||||
t.Fatal("bootstrapAcceptedLogical(current) should return logical")
|
||||
}
|
||||
target := server.bootstrapAcceptedLogical("dedicated-attach-target", nil, nil)
|
||||
if target == nil {
|
||||
t.Fatal("bootstrapAcceptedLogical(target) should return logical")
|
||||
}
|
||||
|
||||
bulk := newBulkHandle(context.Background(), server.getBulkRuntime(), serverFileScope(target), BulkOpenRequest{
|
||||
BulkID: "server-dedicated-attach-test",
|
||||
DataID: 7,
|
||||
Dedicated: true,
|
||||
AttachToken: "attach-token",
|
||||
}, 0, target, nil, 0, nil, nil, nil, nil, nil)
|
||||
bulk.markAcceptHandled()
|
||||
if err := server.getBulkRuntime().register(serverFileScope(target), bulk); err != nil {
|
||||
t.Fatalf("register bulk runtime failed: %v", err)
|
||||
}
|
||||
attachedLeft, attachedRight := net.Pipe()
|
||||
defer attachedRight.Close()
|
||||
if err := bulk.attachDedicatedConn(attachedLeft); err != nil {
|
||||
t.Fatalf("attachDedicatedConn failed: %v", err)
|
||||
}
|
||||
|
||||
resolvedLogical, resolvedBulk, err := server.resolveInboundDedicatedBulk(current, bulkAttachRequest{
|
||||
PeerID: target.ID(),
|
||||
BulkID: bulk.ID(),
|
||||
AttachToken: "attach-token",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("resolveInboundDedicatedBulk failed: %v", err)
|
||||
}
|
||||
if resolvedLogical != target {
|
||||
t.Fatalf("resolved logical mismatch: got %v want %v", resolvedLogical, target)
|
||||
}
|
||||
if resolvedBulk != bulk {
|
||||
t.Fatalf("resolved bulk mismatch: got %v want %v", resolvedBulk, bulk)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user