-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherrors.go
More file actions
134 lines (119 loc) · 4.43 KB
/
Copy patherrors.go
File metadata and controls
134 lines (119 loc) · 4.43 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package parallel
import (
"context"
"errors"
"fmt"
)
// TaskFailedError means that a task in the group has returned an error that
// wasn't caused by the shutdown of the group itself.
//
// TaskFailedError does not become the group result directly, GroupFailedError
// does. Also, TaskFailedError does not become the group context cancelation
// cause directly, ClosingError does.
//
// As a special case, TaskFailedError with Err == nil means that a task with
// exit handling mode Fail has returned nil.
//
// TaskFailedError unwraps as its Err value.
type TaskFailedError struct {
Task string
Err error
}
// Error implements error
func (err TaskFailedError) Error() string {
if err.Err == nil {
return fmt.Sprintf("task %s terminated unexpectedly", err.Task)
}
return fmt.Sprintf("task %s failed: %s", err.Task, err.Err.Error())
}
// Unwrap returns the underlying error
func (err TaskFailedError) Unwrap() error {
return err.Err
}
// TaskSucceededError means that a task in the group with exit handling mode
// Exit has finished successfully. This situation does not cause the group to
// fail unless some other task fails while shutting down.
//
// TaskSucceededError does not become the group result directly,
// GroupFailedError does. Also, TaskSucceededError does not become the group
// context cancelation cause directly, ClosingError does.
type TaskSucceededError struct {
Task string
}
// Error implements error
func (err TaskSucceededError) Error() string {
return fmt.Sprintf("task %s succeeded", err.Task)
}
// GroupFailedError is a group result meaning that at least one of the tasks has
// returned an error that wasn't caused by the shutdown of the group itself, or
// the group was interrupted by cancelation of the parent context, or by
// Group.Exit with an error, or the start function passed to Run has failed.
//
// GroupFailedError unwraps as its Cause.
type GroupFailedError struct {
// Cause is the reason why the group was shut down. It's either
// TaskFailedError, TaskSucceededError, the cancelation cause of the parent
// context, the error returned by the start function passed to Run, or
// whatever was passed to Group.Exit, whichever happened first.
Cause error
errs *[]TaskFailedError // pointer to keep the struct comparable
}
// Error implements error
func (err GroupFailedError) Error() string {
var res string
if err.Cause != nil {
res = err.Cause.Error()
} else {
res = "group closed"
}
for i, e := range *err.errs {
if i != 0 || !errors.Is(e, err.Cause) {
res += "\nWhile closing, " + e.Error()
}
}
return res
}
// Unwrap returns the reason why the group was shut down, same as the Cause
func (err GroupFailedError) Unwrap() error {
return err.Cause
}
// Errors returns the list of all failures of the group's tasks that weren't
// caused by the shutdown of the group itself, in chronological order. If a task
// failure caused the group to shut down, the list contains Cause as its first
// item. Otherwise, the list may or may not be empty.
//
// This would have been a field rather than a method, but a slice would make the
// error type non-comparable, which is a problem:
// https://github.com/golang/go/issues/74488
func (err GroupFailedError) Errors() []TaskFailedError {
return *err.errs
}
// ClosingError appears as the group context cancelation cause (returned by
// context.Cause) when the group is being shut down because of TaskFailedError,
// TaskSucceededError, Group.Exit, or failure of the start function passed to
// Run.
//
// ClosingError does not become the group result, GroupFailedError does.
//
// ClosingError unwraps as context.Canceled rather than its Cause. Rationale: if
// task A fails to read a file, and the ensuing group shutdown interrupts its
// sibling task B, it does not mean that B failed to read a file, only that B
// was interrupted.
type ClosingError struct {
// Cause is the error that caused the cancelation. It is either
// TaskFailedError, TaskSucceededError, the error returned by the start
// function passed to Run, or whatever was passed to Group.Exit.
Cause error
// Group points to the group that is closing. It is here mainly to make
// ClosingError originating from different groups (especially parent and
// child) guaranteed distinct.
Group *Group
}
// Error implements error
func (err ClosingError) Error() string {
return "context canceled, cause: " + err.Cause.Error()
}
// Unwrap returns context.Canceled
func (err ClosingError) Unwrap() error {
return context.Canceled
}