Reopen closed fabric peer sessions

This commit is contained in:
2026-05-16 09:54:02 +03:00
parent 03efff6770
commit 057e3b65a7
4 changed files with 75 additions and 5 deletions
@@ -293,6 +293,18 @@ func (p *FabricSessionPump) Errors() <-chan error {
return p.errors
}
func (p *FabricSessionPump) Closed() bool {
if p == nil {
return true
}
select {
case <-p.done:
return true
default:
return false
}
}
func (p *FabricSessionPump) Close() error {
if p == nil {
return nil
@@ -35,8 +35,12 @@ func (m *FabricSessionPeerManager) Get(ctx context.Context, target FabricSession
}
m.mu.Lock()
if pump := m.sessions[key]; pump != nil {
m.mu.Unlock()
return pump, nil
if pump.Closed() {
delete(m.sessions, key)
} else {
m.mu.Unlock()
return pump, nil
}
}
m.mu.Unlock()
@@ -48,9 +52,13 @@ func (m *FabricSessionPeerManager) Get(ctx context.Context, target FabricSession
m.mu.Lock()
if existing := m.sessions[key]; existing != nil {
m.mu.Unlock()
_ = pump.Close()
return existing, nil
if existing.Closed() {
delete(m.sessions, key)
} else {
m.mu.Unlock()
_ = pump.Close()
return existing, nil
}
}
if m.sessions == nil {
m.sessions = map[string]*FabricSessionPump{}
@@ -117,6 +117,54 @@ func TestFabricSessionPeerManagerClosePeerReopens(t *testing.T) {
}
}
func TestFabricSessionPeerManagerReopensClosedPump(t *testing.T) {
var opened int
server := httptest.NewServer(Server{
Local: PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"},
FabricSessionEnabled: true,
FabricSessionLogger: func(entry FabricSessionEventLogEntry) {
if entry.Event == "fabric_session_websocket_opened" {
opened++
}
},
}.Handler())
defer server.Close()
manager := NewFabricSessionPeerManager()
defer manager.Close()
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
target := FabricSessionPeerTarget{
PeerID: "node-a",
BaseURL: server.URL,
Options: FabricSessionDialOptions{
Token: "rap_fsn_manager_closed",
Timeout: time.Second,
},
}
first, err := manager.Get(ctx, target)
if err != nil {
t.Fatalf("first get: %v", err)
}
if err := first.Close(); err != nil {
t.Fatalf("close first pump: %v", err)
}
if !first.Closed() {
t.Fatal("first pump should report closed")
}
second, err := manager.Get(ctx, target)
if err != nil {
t.Fatalf("second get: %v", err)
}
if first == second {
t.Fatal("manager reused closed pump")
}
if opened != 2 {
t.Fatalf("opened sessions = %d, want 2", opened)
}
}
func TestFabricSessionPeerManagerRejectsIncompleteTarget(t *testing.T) {
manager := NewFabricSessionPeerManager()
_, err := manager.Get(context.Background(), FabricSessionPeerTarget{PeerID: "node-a"})