package ai_summarizer import ( "context" "errors" "fmt" "net" "net/http" "strings" "github.com/minio/minio-go/v7" ) // isMinioNotFound reports whether err indicates the object or bucket key is missing. // The MinIO Go SDK often returns success from GetObject and surfaces NoSuchKey on Read. func isMinioNotFound(err error) bool { if err == nil { return false } var minioErr minio.ErrorResponse if errors.As(err, &minioErr) { if minioErr.StatusCode == http.StatusNotFound { return true } switch strings.ToLower(minioErr.Code) { case "nosuchkey", "notfound": return true } } msg := strings.ToLower(err.Error()) return strings.Contains(msg, "does not exist") || strings.Contains(msg, "nosuchkey") || strings.Contains(msg, "not found") } // isMinioConnectionError reports whether err indicates MinIO is unreachable. func isMinioConnectionError(err error) bool { if err == nil { return false } if errors.Is(err, ErrMinIOUnavailable) { return true } if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { return true } var netErr net.Error if errors.As(err, &netErr) && netErr.Timeout() { return true } var opErr *net.OpError if errors.As(err, &opErr) { return true } msg := strings.ToLower(err.Error()) connectionHints := []string{ "connection refused", "connection reset", "no such host", "dial tcp", "dial udp", "i/o timeout", "network is unreachable", "broken pipe", "tls handshake", "server gave http response to https client", "eof", } for _, hint := range connectionHints { if strings.Contains(msg, hint) { return true } } return false } // wrapMinIOError attaches ErrMinIOUnavailable when the root cause is connectivity. func wrapMinIOError(err error) error { if err == nil || isMinioNotFound(err) { return err } if isMinioConnectionError(err) { return fmt.Errorf("%w: %v", ErrMinIOUnavailable, err) } return err }