sync
This commit is contained in:
155
bridge/kosmi/errors.go
Normal file
155
bridge/kosmi/errors.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package bkosmi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Sentinel errors for common failure scenarios
|
||||
var (
|
||||
// ErrNotConnected indicates the WebSocket connection is not established
|
||||
ErrNotConnected = errors.New("not connected to Kosmi")
|
||||
|
||||
// ErrAuthFailed indicates authentication with Kosmi failed
|
||||
ErrAuthFailed = errors.New("authentication failed")
|
||||
|
||||
// ErrConnectionLost indicates the WebSocket connection was lost
|
||||
ErrConnectionLost = errors.New("connection lost")
|
||||
|
||||
// ErrTokenExpired indicates the authentication token has expired
|
||||
ErrTokenExpired = errors.New("token expired")
|
||||
|
||||
// ErrInvalidRoomID indicates the room ID format is invalid
|
||||
ErrInvalidRoomID = errors.New("invalid room ID")
|
||||
|
||||
// ErrRoomNotFound indicates the specified room does not exist
|
||||
ErrRoomNotFound = errors.New("room not found")
|
||||
|
||||
// ErrMessageSendFailed indicates a message could not be sent
|
||||
ErrMessageSendFailed = errors.New("failed to send message")
|
||||
|
||||
// ErrSubscriptionFailed indicates subscription to room messages failed
|
||||
ErrSubscriptionFailed = errors.New("failed to subscribe to messages")
|
||||
|
||||
// ErrJoinRoomFailed indicates joining the room failed
|
||||
ErrJoinRoomFailed = errors.New("failed to join room")
|
||||
|
||||
// ErrConnectionTimeout indicates a connection timeout occurred
|
||||
ErrConnectionTimeout = errors.New("connection timeout")
|
||||
|
||||
// ErrInvalidResponse indicates an unexpected response from the server
|
||||
ErrInvalidResponse = errors.New("invalid response from server")
|
||||
)
|
||||
|
||||
// ConnectionError represents a connection-related error with context
|
||||
type ConnectionError struct {
|
||||
Op string // Operation that failed (e.g., "dial", "handshake", "subscribe")
|
||||
URL string // WebSocket URL
|
||||
Err error // Underlying error
|
||||
}
|
||||
|
||||
func (e *ConnectionError) Error() string {
|
||||
return fmt.Sprintf("connection error during %s to %s: %v", e.Op, e.URL, e.Err)
|
||||
}
|
||||
|
||||
func (e *ConnectionError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// AuthError represents an authentication-related error with context
|
||||
type AuthError struct {
|
||||
Op string // Operation that failed (e.g., "login", "token_refresh", "anonymous_login")
|
||||
Reason string // Human-readable reason
|
||||
Err error // Underlying error
|
||||
}
|
||||
|
||||
func (e *AuthError) Error() string {
|
||||
if e.Err != nil {
|
||||
return fmt.Sprintf("auth error during %s: %s (%v)", e.Op, e.Reason, e.Err)
|
||||
}
|
||||
return fmt.Sprintf("auth error during %s: %s", e.Op, e.Reason)
|
||||
}
|
||||
|
||||
func (e *AuthError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// MessageError represents a message-related error with context
|
||||
type MessageError struct {
|
||||
Op string // Operation that failed (e.g., "send", "receive", "parse")
|
||||
RoomID string // Room ID
|
||||
Message string // Message content (truncated if long)
|
||||
Err error // Underlying error
|
||||
}
|
||||
|
||||
func (e *MessageError) Error() string {
|
||||
return fmt.Sprintf("message error during %s in room %s: %v", e.Op, e.RoomID, e.Err)
|
||||
}
|
||||
|
||||
func (e *MessageError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// RoomError represents a room-related error with context
|
||||
type RoomError struct {
|
||||
Op string // Operation that failed (e.g., "join", "leave", "subscribe")
|
||||
RoomID string // Room ID
|
||||
Err error // Underlying error
|
||||
}
|
||||
|
||||
func (e *RoomError) Error() string {
|
||||
return fmt.Sprintf("room error during %s for room %s: %v", e.Op, e.RoomID, e.Err)
|
||||
}
|
||||
|
||||
func (e *RoomError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// IsRetryable returns true if the error is transient and the operation should be retried
|
||||
func IsRetryable(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check for known retryable errors
|
||||
if errors.Is(err, ErrConnectionLost) ||
|
||||
errors.Is(err, ErrConnectionTimeout) ||
|
||||
errors.Is(err, ErrTokenExpired) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check for connection errors (usually retryable)
|
||||
var connErr *ConnectionError
|
||||
if errors.As(err, &connErr) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// IsFatal returns true if the error is fatal and reconnection should not be attempted
|
||||
func IsFatal(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check for known fatal errors
|
||||
if errors.Is(err, ErrAuthFailed) ||
|
||||
errors.Is(err, ErrInvalidRoomID) ||
|
||||
errors.Is(err, ErrRoomNotFound) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check for auth errors with specific reasons
|
||||
var authErr *AuthError
|
||||
if errors.As(err, &authErr) {
|
||||
// Invalid credentials are fatal
|
||||
if authErr.Reason == "invalid credentials" ||
|
||||
authErr.Reason == "account not found" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user