zerr: sequence: changed into interface for future proofing
This commit is contained in:
parent
dba226c1c1
commit
ab159d9426
|
@ -27,7 +27,7 @@ type Err struct {
|
|||
id string
|
||||
logger Logger
|
||||
notifier Notifier
|
||||
sequence *Sequence
|
||||
sequence Sequence
|
||||
}
|
||||
|
||||
// Join implements Error.
|
||||
|
@ -215,7 +215,7 @@ func (mu *Err) Notify(ctx context.Context, opts ...zoptions.NotifyOption) Error
|
|||
}
|
||||
|
||||
// Sequence returns the state of the error sequence.
|
||||
func (mu *Err) Sequence() *Sequence {
|
||||
func (mu *Err) Sequence() Sequence {
|
||||
return mu.sequence
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,11 @@ func (er *Err) WriteBuilder(w io.Writer) {
|
|||
return
|
||||
}
|
||||
var previous string
|
||||
if err := er.sequence.Outer(); err != nil && !err.IsMulti() {
|
||||
if parent := er.sequence.Parent(); parent != nil {
|
||||
if err := parent.Error(); err != nil && !err.IsMulti() {
|
||||
previous = err.GetMessage()
|
||||
}
|
||||
}
|
||||
current := strings.TrimPrefix(er.message, previous)
|
||||
if current != "" {
|
||||
if previous != "" {
|
||||
|
|
|
@ -85,7 +85,9 @@ type Error interface {
|
|||
Notify(ctx context.Context, opts ...zoptions.NotifyOption) Error
|
||||
|
||||
// Sequence returns the state of the error sequence.
|
||||
Sequence() *Sequence
|
||||
//
|
||||
// Sequence must not be nil.
|
||||
Sequence() Sequence
|
||||
|
||||
// IsMulti returns true if the error is a multiple error.
|
||||
IsMulti() bool
|
||||
|
|
|
@ -9,24 +9,50 @@ import "iter"
|
|||
// When wrapping errors, the wrapping error
|
||||
// will be the parent of the wrapped Error
|
||||
// if the wrapped Error is a zerr.Error.
|
||||
type Sequence struct {
|
||||
parent *Sequence
|
||||
children []*Sequence
|
||||
type Sequence interface {
|
||||
// WrapBy prepends the next Sequence to the current Sequence.
|
||||
WrapBy(parent Sequence)
|
||||
|
||||
// Parent returns the parent Sequence.
|
||||
// Return nil if this Sequence is Root.
|
||||
Parent() Sequence
|
||||
|
||||
// Root returns the outermost Sequence in the sequence.
|
||||
//
|
||||
// Returns self if current Sequence is the outermost.
|
||||
Root() Sequence
|
||||
|
||||
// IsRoot checks if the Sequence is the outermost Sequence in the sequence.
|
||||
IsRoot() bool
|
||||
|
||||
// Error returns the Error in the sequence.
|
||||
Error() Error
|
||||
|
||||
// Iter returns an iterator to traverse Errors in the sequence.
|
||||
Iter() iter.Seq[Error]
|
||||
|
||||
// AppendChild appends a child Sequence to the current Sequence.
|
||||
AppendChild(child Sequence)
|
||||
}
|
||||
|
||||
type sequence struct {
|
||||
parent Sequence
|
||||
children []Sequence
|
||||
err Error
|
||||
}
|
||||
|
||||
// WrapBy prepends the next Sequence to the current Sequence.
|
||||
func (se *Sequence) WrapBy(parent *Sequence) {
|
||||
parent.children = append(parent.children, se)
|
||||
func (se *sequence) WrapBy(parent Sequence) {
|
||||
parent.AppendChild(se)
|
||||
se.parent = parent
|
||||
}
|
||||
|
||||
// Outer returns the error that wraps this Error.
|
||||
// Return nil if this Error is not wrapped
|
||||
// or wrapping outer is not a zerr.Error.
|
||||
func (se *Sequence) Outer() Error {
|
||||
func (se *sequence) AppendChild(child Sequence) {
|
||||
se.children = append(se.children, child)
|
||||
}
|
||||
|
||||
func (se *sequence) Parent() Sequence {
|
||||
if se.parent != nil {
|
||||
return se.parent.err
|
||||
return se.parent
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -34,21 +60,23 @@ func (se *Sequence) Outer() Error {
|
|||
// Root returns the outermost Error in the sequence.
|
||||
//
|
||||
// Returns self if there is no outermost.
|
||||
func (se *Sequence) Root() *Sequence {
|
||||
root := se
|
||||
for root.parent != nil {
|
||||
root = root.parent
|
||||
}
|
||||
func (se *sequence) Root() Sequence {
|
||||
var root Sequence = se
|
||||
for {
|
||||
if root.Parent() == nil {
|
||||
return root
|
||||
}
|
||||
root = root.Parent()
|
||||
}
|
||||
}
|
||||
|
||||
// IsRoot checks if the Error is the outermost Error in the sequence.
|
||||
func (se *Sequence) IsRoot() bool {
|
||||
func (se *sequence) IsRoot() bool {
|
||||
return se.parent == nil
|
||||
}
|
||||
|
||||
// Error returns the Error in the sequence.
|
||||
func (se *Sequence) Error() Error {
|
||||
func (se *sequence) Error() Error {
|
||||
return se.err
|
||||
}
|
||||
|
||||
|
@ -64,7 +92,7 @@ func (se *Sequence) Error() Error {
|
|||
// // e is zerr.Error
|
||||
// // do something with e
|
||||
// }
|
||||
func (se *Sequence) Iter() iter.Seq[Error] {
|
||||
func (se *sequence) Iter() iter.Seq[Error] {
|
||||
return func(yield func(Error) bool) {
|
||||
if se.err != nil && !yield(se.err) {
|
||||
return
|
||||
|
|
|
@ -7,19 +7,20 @@ import (
|
|||
"gitlab.bareksa.com/backend/zen/core/zoptions"
|
||||
)
|
||||
|
||||
type WrapInitialInput struct {
|
||||
Error error
|
||||
type WrapInput struct {
|
||||
Errors []error
|
||||
Message string
|
||||
PC uintptr
|
||||
Time time.Time
|
||||
Logger Logger
|
||||
Notifier Notifier
|
||||
Details []any
|
||||
}
|
||||
|
||||
type Wrapper interface {
|
||||
// Wrap creates a zerr.Error with inputs
|
||||
// generated by global entry points.
|
||||
Wrap(input WrapInitialInput) Error
|
||||
Wrap(input WrapInput) Error
|
||||
}
|
||||
|
||||
type Logger interface {
|
||||
|
@ -30,12 +31,35 @@ type Notifier interface {
|
|||
NotifyError(ctx context.Context, err Error, opts ...zoptions.NotifyOption)
|
||||
}
|
||||
|
||||
type WrapperFunc func(input WrapInitialInput) Error
|
||||
type WrapperFunc func(input WrapInput) Error
|
||||
|
||||
func (wr WrapperFunc) Wrap(input WrapInitialInput) Error {
|
||||
func (wr WrapperFunc) Wrap(input WrapInput) Error {
|
||||
return wr(input)
|
||||
}
|
||||
|
||||
var DefaultWrapper Wrapper = WrapperFunc(func(input WrapInitialInput) Error {
|
||||
panic("not implemented")
|
||||
var DefaultWrapper Wrapper = WrapperFunc(func(input WrapInput) Error {
|
||||
e := &Err{
|
||||
message: input.Message,
|
||||
errs: input.Errors,
|
||||
caller: input.PC,
|
||||
time: input.Time,
|
||||
logger: input.Logger,
|
||||
notifier: input.Notifier,
|
||||
details: input.Details,
|
||||
}
|
||||
e.sequence = &sequence{err: e}
|
||||
for _, err := range input.Errors {
|
||||
if err, ok := err.(Error); ok {
|
||||
err.Sequence().WrapBy(e.sequence)
|
||||
}
|
||||
}
|
||||
return e
|
||||
})
|
||||
|
||||
func Wrap(input WrapInput) Error {
|
||||
return DefaultWrapper.Wrap(input)
|
||||
}
|
||||
|
||||
func SetDefaultWrapper(w Wrapper) {
|
||||
DefaultWrapper = w
|
||||
}
|
||||
|
|
4
go.mod
4
go.mod
|
@ -6,6 +6,8 @@ require (
|
|||
connectrpc.com/connect v1.16.2
|
||||
connectrpc.com/grpcreflect v1.2.0
|
||||
github.com/fatih/color v1.17.0
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/pborman/indent v1.2.1
|
||||
github.com/tidwall/pretty v1.2.1
|
||||
golang.org/x/net v0.23.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
|
@ -13,8 +15,6 @@ require (
|
|||
|
||||
require (
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/pborman/indent v1.2.1 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue