decred.org/dcrdex@v1.0.5/dex/errors.go (about)

     1  // This code is available on the terms of the project LICENSE.md file,
     2  // also available online at https://blueoakcouncil.org/license/1.0.0.
     3  
     4  package dex
     5  
     6  // ErrorKind identifies a kind of error that can be used to define new errors
     7  // via const SomeError = dex.ErrorKind("something").
     8  type ErrorKind string
     9  
    10  // Error satisfies the error interface and prints human-readable errors.
    11  func (e ErrorKind) Error() string {
    12  	return string(e)
    13  }
    14  
    15  // Error pairs an error with details.
    16  type Error struct {
    17  	wrapped error
    18  	detail  string
    19  }
    20  
    21  // Error satisfies the error interface, combining the wrapped error message with
    22  // the details.
    23  func (e Error) Error() string {
    24  	return e.wrapped.Error() + ": " + e.detail
    25  }
    26  
    27  // Unwrap returns the wrapped error, allowing errors.Is and errors.As to work.
    28  func (e Error) Unwrap() error {
    29  	return e.wrapped
    30  }
    31  
    32  // NewError wraps the provided Error with details in a Error, facilitating the
    33  // use of errors.Is and errors.As via errors.Unwrap.
    34  func NewError(err error, detail string) Error {
    35  	return Error{
    36  		wrapped: err,
    37  		detail:  detail,
    38  	}
    39  }
    40  
    41  // ErrorCloser is used to synchronize shutdown when an error is encountered in a
    42  // multi-step process. After each successful step, a shutdown routine can be
    43  // scheduled with Add. If Success is not signaled before Done, the shutdown
    44  // routines will be run in the reverse order that they are added.
    45  type ErrorCloser struct {
    46  	closers []func() error
    47  }
    48  
    49  // NewErrorCloser creates a new ErrorCloser.
    50  func NewErrorCloser() *ErrorCloser {
    51  	return &ErrorCloser{
    52  		closers: make([]func() error, 0, 3),
    53  	}
    54  }
    55  
    56  // Add adds a new function to the queue. If Success is not called before Done,
    57  // the Add'ed functions will be run in the reverse order that they were added.
    58  func (e *ErrorCloser) Add(closer func() error) {
    59  	e.closers = append(e.closers, closer)
    60  }
    61  
    62  // Success cancels the running of any Add'ed functions.
    63  func (e *ErrorCloser) Success() {
    64  	e.closers = nil
    65  }
    66  
    67  // Done signals that the ErrorClose can run its registered functions if success
    68  // has not yet been flagged.
    69  func (e *ErrorCloser) Done(log Logger) {
    70  	for i := len(e.closers) - 1; i >= 0; i-- {
    71  		if err := e.closers[i](); err != nil {
    72  			log.Errorf("error running shutdown function %d: %v", i, err)
    73  		}
    74  	}
    75  }
    76  
    77  // Copy creates a shallow copy of the ErrorCloser.
    78  func (e *ErrorCloser) Copy() *ErrorCloser {
    79  	return &ErrorCloser{
    80  		closers: e.closers,
    81  	}
    82  }