diff --git a/internal/cluster/connection.go b/internal/cluster/connection.go index 6d989b862..a3102cadb 100644 --- a/internal/cluster/connection.go +++ b/internal/cluster/connection.go @@ -337,7 +337,7 @@ func positiveDurationOrMax(duration time.Duration) time.Duration { } func wrapError(err *ihzerrors.ServerError) error { - targetErr := convertErrorCodeToError(errorCode(err.ErrorCode)) + targetErr := convertErrorCodeToError(errorCode(err.ErrorCode())) return ihzerrors.NewClientError(err.String(), err, targetErr) } diff --git a/internal/proto/error_holder.go b/internal/hzerrors/error_holder.go similarity index 77% rename from internal/proto/error_holder.go rename to internal/hzerrors/error_holder.go index 6f5733731..07dd87349 100644 --- a/internal/proto/error_holder.go +++ b/internal/hzerrors/error_holder.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved. + * Copyright (c) 2008-2023, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License") * you may not use this file except in compliance with the License. @@ -14,18 +14,16 @@ * limitations under the License. */ -package proto - -import "github.com/hazelcast/hazelcast-go-client/internal/hzerrors" +package hzerrors type ErrorHolder struct { ClassName string Message string - StackTraceElements []hzerrors.StackTraceElement + StackTraceElements []StackTraceElement ErrorCode int32 } -func NewErrorHolder(errorCode int32, className, message string, stackTraceElements []hzerrors.StackTraceElement) ErrorHolder { +func NewErrorHolder(errorCode int32, className, message string, stackTraceElements []StackTraceElement) ErrorHolder { return ErrorHolder{ ErrorCode: errorCode, ClassName: className, diff --git a/internal/hzerrors/errors.go b/internal/hzerrors/errors.go index c84ac4318..971a48631 100644 --- a/internal/hzerrors/errors.go +++ b/internal/hzerrors/errors.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2022, Hazelcast, Inc. All Rights Reserved. + * Copyright (c) 2008-2023, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License") * you may not use this file except in compliance with the License. @@ -39,33 +39,36 @@ type StackTraceElement struct { } type ServerError struct { - ClassName string - Message string - CauseClassName string - StackTrace []StackTraceElement - ErrorCode int32 - CauseErrorCode int32 + errorHolders []ErrorHolder } -func NewServerError(errorCode int32, className string, message string, stackTrace []StackTraceElement) *ServerError { +func NewServerError(errorHolders []ErrorHolder) *ServerError { return &ServerError{ - ErrorCode: errorCode, - ClassName: className, - Message: message, - StackTrace: stackTrace, + errorHolders: errorHolders, } } -func (e *ServerError) Error() string { - return e.Message +func (e ServerError) ErrorCode() int32 { + return e.errorHolders[0].ErrorCode +} + +func (e ServerError) Error() string { + return fmt.Sprintf("server error: %s: %s", e.lastErrorHolder().ClassName, e.lastErrorHolder().Message) } -func (e *ServerError) String() string { - sb := strings.Builder{} - for _, trace := range e.StackTrace { - sb.WriteString(fmt.Sprintf("\n %s.%s(%s:%d)", trace.ClassName, trace.MethodName, trace.FileName, trace.LineNumber)) +func (e ServerError) String() string { + var sb strings.Builder + for _, h := range e.errorHolders { + sb.WriteString(fmt.Sprintf("%s: %s\n", h.ClassName, h.Message)) + for _, trace := range h.StackTraceElements { + sb.WriteString(fmt.Sprintf("\t%s.%s(%s:%d)\n", trace.ClassName, trace.MethodName, trace.FileName, trace.LineNumber)) + } } - return fmt.Sprintf("got exception from server:\n %s: %s\n %s", e.ClassName, e.Message, sb.String()) + return fmt.Sprintf("server error:\n%s", sb.String()) +} + +func (e ServerError) lastErrorHolder() ErrorHolder { + return e.errorHolders[len(e.errorHolders)-1] } type ClientError struct { diff --git a/internal/proto/codec/builtin.go b/internal/proto/codec/builtin.go index 329565ee8..c4546f021 100644 --- a/internal/proto/codec/builtin.go +++ b/internal/proto/codec/builtin.go @@ -785,15 +785,14 @@ func DecodeString(frameIterator *proto.ForwardFrameIterator) string { func DecodeError(msg *proto.ClientMessage) *ihzerrors.ServerError { frameIterator := msg.FrameIterator() frameIterator.Next() - var errorHolders []proto.ErrorHolder + var errorHolders []ihzerrors.ErrorHolder DecodeListMultiFrame(frameIterator, func(it *proto.ForwardFrameIterator) { errorHolders = append(errorHolders, DecodeErrorHolder(frameIterator)) }) if len(errorHolders) == 0 { return nil } - holder := errorHolders[0] - return ihzerrors.NewServerError(holder.ErrorCode, holder.ClassName, holder.Message, holder.StackTraceElements) + return ihzerrors.NewServerError(errorHolders) } func NewEndpointQualifier(qualifierType int32, identifier string) pubcluster.EndpointQualifier { diff --git a/internal/proto/codec/error_holder_codec.go b/internal/proto/codec/error_holder_codec.go index 38236b628..a5985c890 100644 --- a/internal/proto/codec/error_holder_codec.go +++ b/internal/proto/codec/error_holder_codec.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved. + * Copyright (c) 2008-2023, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License") * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package codec import ( + ihzerrors "github.com/hazelcast/hazelcast-go-client/internal/hzerrors" "github.com/hazelcast/hazelcast-go-client/internal/proto" ) @@ -24,7 +25,7 @@ const ( ErrorHolderCodecErrorCodeInitialFrameSize = ErrorHolderCodecErrorCodeFieldOffset + proto.IntSizeInBytes ) -func EncodeErrorHolder(clientMessage *proto.ClientMessage, errorHolder proto.ErrorHolder) { +func EncodeErrorHolder(clientMessage *proto.ClientMessage, errorHolder ihzerrors.ErrorHolder) { clientMessage.AddFrame(proto.BeginFrame.Copy()) initialFrame := proto.NewFrame(make([]byte, ErrorHolderCodecErrorCodeInitialFrameSize)) FixSizedTypesCodec.EncodeInt(initialFrame.Content, ErrorHolderCodecErrorCodeFieldOffset, int32(errorHolder.ErrorCode)) @@ -37,7 +38,7 @@ func EncodeErrorHolder(clientMessage *proto.ClientMessage, errorHolder proto.Err clientMessage.AddFrame(proto.EndFrame.Copy()) } -func DecodeErrorHolder(frameIterator *proto.ForwardFrameIterator) proto.ErrorHolder { +func DecodeErrorHolder(frameIterator *proto.ForwardFrameIterator) ihzerrors.ErrorHolder { // begin frame frameIterator.Next() initialFrame := frameIterator.Next() @@ -47,5 +48,5 @@ func DecodeErrorHolder(frameIterator *proto.ForwardFrameIterator) proto.ErrorHol message := CodecUtil.DecodeNullableForString(frameIterator) stackTraceElements := DecodeListMultiFrameForStackTraceElement(frameIterator) CodecUtil.FastForwardToEndFrame(frameIterator) - return proto.NewErrorHolder(errorCode, className, message, stackTraceElements) + return ihzerrors.NewErrorHolder(errorCode, className, message, stackTraceElements) }