-
Notifications
You must be signed in to change notification settings - Fork 1
/
err-slice.go
87 lines (74 loc) · 2.95 KB
/
err-slice.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
© 2024–present Harald Rudell <[email protected]> (https://haraldrudell.github.io/haraldrudell/)
ISC License
*/
package parl
import "github.com/haraldrudell/parl/perrors"
// ErrSlice is a thread-safe unbound awaitable error container
// - [ErrSlice.AddError] is a function to submit errors
// - [ErrSlice.WaitCh] returns a closing channel to await the next error
// - [ErrSlice.Error] returns the next error value if any
// - [ErrSlice.Errors] returns a slice of all errors if any
// - [ErrSlice.EmptyCh] returns a closing channel to await container empty
// providing deferred-close functionality
// - ErrSlice features:
// - — real-time error stream or
// - — collect errors at end and
// - — close then read-to-end function
// - implements [parl.Errs] [parl.ErrorSink]
//
// Usage:
//
// var errs ErrSlice
// go fn(&errs)
// for err := errs.Init(); errs.Condition(&err); {
// // process real-time error stream
// …
// func fn(errs parl.ErrorSink) {
// defer errs.EndErrors()
// …
// errs.AddError(err)
//
// var errs ErrSlice
// fn2(&errs)
// for _, err := range errs.Errors() {
// // process post-invocation errors
// …
// func fn2(errs parl.ErrorSink1) {
// errs.AddError(err)
type ErrSlice struct {
// errs is a thread-safe, unbound awaitable slice of errors
errs AwaitableSlice[error]
}
// ErrSlice provides error one-at-a-time or all-at-once
var _ Errs = &ErrSlice{}
// ErrSlice has AddError error sink method
var _ ErrorSink = &ErrSlice{}
// Error returns the next error value
// - hasValue true: err is valid
// - hasValue false: the error source is empty
func (e *ErrSlice) Error() (error, bool) { return e.errs.Get() }
// Errors returns a slice of errors or nil
func (e *ErrSlice) Errors() (errs []error) { return e.errs.GetAll() }
// WaitCh waits for the next error, possibly indefinitely
// - a received channel closes on errors available
// - the next invocation may return a different channel object
func (e *ErrSlice) WaitCh() (ch AwaitableCh) { return e.errs.DataWaitCh() }
// EndCh awaits the error source closing:
// - the error source must be read to empty
// - the error source must be closed by the error-source providing entity
func (e *ErrSlice) EndCh() (ch AwaitableCh) { return e.errs.EmptyCh(CloseAwaiter) }
// AddError is a function to submit non-fatal errors
func (e *ErrSlice) AddError(err error) { e.errs.Send(err) }
// EndCh awaits the error source closing:
// - the error source must be read to empty
// - the error source must be closed by the error-source providing entity
func (e *ErrSlice) EndErrors() { e.errs.EmptyCh() }
// AppendErrors collects any errors contained and appends them to errp
func (e *ErrSlice) AppendErrors(errp *error) {
for _, err := range e.errs.GetAll() {
*errp = perrors.AppendError(*errp, err)
}
}
func (e *ErrSlice) Init() (err error) { return }
func (e *ErrSlice) Condition(errp *error) (hasValue bool) { return e.errs.Condition(errp) }