package notify import ( "errors" "sync/atomic" ) type SignalReliabilityStats struct { SignalSendTotal uint64 ReliableSendTotal uint64 RetryTotal uint64 AckWaitTotal uint64 AckDeliverTotal uint64 AckTimeoutTotal uint64 AckCanceledTotal uint64 DuplicateRecvTotal uint64 AckSendTotal uint64 AckSendErrorTotal uint64 } type signalReliabilityState struct { signalSendTotal atomic.Uint64 reliableSendTotal atomic.Uint64 retryTotal atomic.Uint64 ackWaitTotal atomic.Uint64 ackDeliverTotal atomic.Uint64 ackTimeoutTotal atomic.Uint64 ackCanceledTotal atomic.Uint64 duplicateRecvTotal atomic.Uint64 ackSendTotal atomic.Uint64 ackSendErrorTotal atomic.Uint64 } func newSignalReliabilityState() *signalReliabilityState { return &signalReliabilityState{} } func (s *signalReliabilityState) incSignalSend() { if s == nil { return } s.signalSendTotal.Add(1) } func (s *signalReliabilityState) incReliableSend() { if s == nil { return } s.reliableSendTotal.Add(1) } func (s *signalReliabilityState) incRetry() { if s == nil { return } s.retryTotal.Add(1) } func (s *signalReliabilityState) incAckWait() { if s == nil { return } s.ackWaitTotal.Add(1) } func (s *signalReliabilityState) incAckDeliver() { if s == nil { return } s.ackDeliverTotal.Add(1) } func (s *signalReliabilityState) incAckTimeout() { if s == nil { return } s.ackTimeoutTotal.Add(1) } func (s *signalReliabilityState) incAckCanceled() { if s == nil { return } s.ackCanceledTotal.Add(1) } func (s *signalReliabilityState) incDuplicateRecv() { if s == nil { return } s.duplicateRecvTotal.Add(1) } func (s *signalReliabilityState) incAckSend() { if s == nil { return } s.ackSendTotal.Add(1) } func (s *signalReliabilityState) incAckSendError() { if s == nil { return } s.ackSendErrorTotal.Add(1) } func (s *signalReliabilityState) snapshot() SignalReliabilityStats { if s == nil { return SignalReliabilityStats{} } return SignalReliabilityStats{ SignalSendTotal: s.signalSendTotal.Load(), ReliableSendTotal: s.reliableSendTotal.Load(), RetryTotal: s.retryTotal.Load(), AckWaitTotal: s.ackWaitTotal.Load(), AckDeliverTotal: s.ackDeliverTotal.Load(), AckTimeoutTotal: s.ackTimeoutTotal.Load(), AckCanceledTotal: s.ackCanceledTotal.Load(), DuplicateRecvTotal: s.duplicateRecvTotal.Load(), AckSendTotal: s.ackSendTotal.Load(), AckSendErrorTotal: s.ackSendErrorTotal.Load(), } } func (c *ClientCommon) getSignalReliabilityState() *signalReliabilityState { return c.getLogicalSessionState().signalReliableState } func (s *ServerCommon) getSignalReliabilityState() *signalReliabilityState { return s.getLogicalSessionState().signalReliableState } func (c *ClientCommon) signalReliabilityStatsSnapshot() SignalReliabilityStats { return c.getSignalReliabilityState().snapshot() } func (s *ServerCommon) signalReliabilityStatsSnapshot() SignalReliabilityStats { return s.getSignalReliabilityState().snapshot() } type signalReliabilityStatsReader interface { signalReliabilityStatsSnapshot() SignalReliabilityStats } var ( errSignalReliabilityStatsClientNil = errors.New("signal reliability stats client is nil") errSignalReliabilityStatsServerNil = errors.New("signal reliability stats server is nil") errSignalReliabilityStatsClientUnsupported = errors.New("signal reliability stats client type is unsupported") errSignalReliabilityStatsServerUnsupported = errors.New("signal reliability stats server type is unsupported") ) func GetSignalReliabilityStatsClient(c Client) (SignalReliabilityStats, error) { if c == nil { return SignalReliabilityStats{}, errSignalReliabilityStatsClientNil } reader, ok := any(c).(signalReliabilityStatsReader) if !ok { return SignalReliabilityStats{}, errSignalReliabilityStatsClientUnsupported } return reader.signalReliabilityStatsSnapshot(), nil } func GetSignalReliabilityStatsServer(s Server) (SignalReliabilityStats, error) { if s == nil { return SignalReliabilityStats{}, errSignalReliabilityStatsServerNil } reader, ok := any(s).(signalReliabilityStatsReader) if !ok { return SignalReliabilityStats{}, errSignalReliabilityStatsServerUnsupported } return reader.signalReliabilityStatsSnapshot(), nil }