package mesh import ( "context" "fmt" "strings" "sync" ) type FabricSessionPeerManager struct { mu sync.Mutex sessions map[string]*FabricSessionPump stats FabricSessionPeerManagerStats } type FabricSessionPeerTarget struct { PeerID string BaseURL string Options FabricSessionDialOptions Pump FabricSessionPumpOptions } type FabricSessionPeerManagerStats struct { Opens uint64 `json:"opens"` Reuses uint64 `json:"reuses"` ClosedEvicted uint64 `json:"closed_evicted"` ClosePeerCalls uint64 `json:"close_peer_calls"` CloseAllCalls uint64 `json:"close_all_calls"` } type FabricSessionPeerManagerSnapshot struct { SchemaVersion string `json:"schema_version"` ActiveCount int `json:"active_count"` ClosedCount int `json:"closed_count"` Stats FabricSessionPeerManagerStats `json:"stats"` } func NewFabricSessionPeerManager() *FabricSessionPeerManager { return &FabricSessionPeerManager{ sessions: map[string]*FabricSessionPump{}, } } func (m *FabricSessionPeerManager) Get(ctx context.Context, target FabricSessionPeerTarget) (*FabricSessionPump, error) { if m == nil { return nil, fmt.Errorf("fabric session peer manager is nil") } key, err := fabricSessionPeerKey(target) if err != nil { return nil, err } m.mu.Lock() if pump := m.sessions[key]; pump != nil { if pump.Closed() { delete(m.sessions, key) m.stats.ClosedEvicted++ } else { m.stats.Reuses++ m.mu.Unlock() return pump, nil } } m.mu.Unlock() session, _, err := NewClient(target.BaseURL).OpenFabricSession(ctx, target.Options) if err != nil { return nil, err } pump := session.StartPump(context.Background(), target.Pump) m.mu.Lock() if existing := m.sessions[key]; existing != nil { if existing.Closed() { delete(m.sessions, key) m.stats.ClosedEvicted++ } else { m.stats.Reuses++ m.mu.Unlock() _ = pump.Close() return existing, nil } } if m.sessions == nil { m.sessions = map[string]*FabricSessionPump{} } m.sessions[key] = pump m.stats.Opens++ m.mu.Unlock() return pump, nil } func (m *FabricSessionPeerManager) ClosePeer(target FabricSessionPeerTarget) error { if m == nil { return nil } key, err := fabricSessionPeerKey(target) if err != nil { return err } m.mu.Lock() m.stats.ClosePeerCalls++ pump := m.sessions[key] delete(m.sessions, key) m.mu.Unlock() if pump == nil { return nil } return pump.Close() } func (m *FabricSessionPeerManager) Close() error { if m == nil { return nil } m.mu.Lock() m.stats.CloseAllCalls++ sessions := m.sessions m.sessions = map[string]*FabricSessionPump{} m.mu.Unlock() var firstErr error for _, pump := range sessions { if err := pump.Close(); err != nil && firstErr == nil { firstErr = err } } return firstErr } func (m *FabricSessionPeerManager) Snapshot() FabricSessionPeerManagerSnapshot { if m == nil { return FabricSessionPeerManagerSnapshot{SchemaVersion: "rap.fabric_session_peer_manager.v1"} } m.mu.Lock() defer m.mu.Unlock() snapshot := FabricSessionPeerManagerSnapshot{ SchemaVersion: "rap.fabric_session_peer_manager.v1", Stats: m.stats, } for _, pump := range m.sessions { if pump == nil || pump.Closed() { snapshot.ClosedCount++ continue } snapshot.ActiveCount++ } return snapshot } func fabricSessionPeerKey(target FabricSessionPeerTarget) (string, error) { peerID := strings.TrimSpace(target.PeerID) baseURL := strings.TrimRight(strings.TrimSpace(target.BaseURL), "/") if peerID == "" || baseURL == "" { return "", fmt.Errorf("fabric session peer id and base url are required") } return peerID + "\x00" + baseURL, nil }