All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 2m18s
Test / Hakurei (push) Successful in 3m22s
Test / Hpkg (push) Successful in 3m43s
Test / Sandbox (race detector) (push) Successful in 4m20s
Test / Hakurei (race detector) (push) Successful in 5m21s
Test / Flake checks (push) Successful in 1m38s
This makes handling of fatal errors a lot less squirmy. Signed-off-by: Ophestra <cat@gensokyo.uk>
53 lines
1.1 KiB
Go
53 lines
1.1 KiB
Go
package container
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
"sync/atomic"
|
|
)
|
|
|
|
// MessageError is an error with a user-facing message.
|
|
type MessageError interface {
|
|
// Message returns a user-facing error message.
|
|
Message() string
|
|
|
|
error
|
|
}
|
|
|
|
// GetErrorMessage returns whether an error implements [MessageError], and the message if it does.
|
|
func GetErrorMessage(err error) (string, bool) {
|
|
var e MessageError
|
|
if !errors.As(err, &e) || e == nil {
|
|
return zeroString, false
|
|
}
|
|
return e.Message(), true
|
|
}
|
|
|
|
type Msg interface {
|
|
IsVerbose() bool
|
|
Verbose(v ...any)
|
|
Verbosef(format string, v ...any)
|
|
|
|
Suspend()
|
|
Resume() bool
|
|
BeforeExit()
|
|
}
|
|
|
|
type DefaultMsg struct{ inactive atomic.Bool }
|
|
|
|
func (msg *DefaultMsg) IsVerbose() bool { return true }
|
|
func (msg *DefaultMsg) Verbose(v ...any) {
|
|
if !msg.inactive.Load() {
|
|
log.Println(v...)
|
|
}
|
|
}
|
|
func (msg *DefaultMsg) Verbosef(format string, v ...any) {
|
|
if !msg.inactive.Load() {
|
|
log.Printf(format, v...)
|
|
}
|
|
}
|
|
|
|
func (msg *DefaultMsg) Suspend() { msg.inactive.Store(true) }
|
|
func (msg *DefaultMsg) Resume() bool { return msg.inactive.CompareAndSwap(true, false) }
|
|
func (msg *DefaultMsg) BeforeExit() {}
|