Repository navigation
Expand file tree
/
Copy patherrors.go
More file actions
129 lines (118 loc) · 4.35 KB
/
Copy patherrors.go
File metadata and controls
129 lines (118 loc) · 4.35 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
package weir
import (
"errors"
"fmt"
)
// ErrNotFound reports a record that does not exist. Read reports one as
// ReadResult.Missing; the mongodb and search packages return ErrNotFound.
var ErrNotFound = errors.New("weir: record not found")
// ErrInterrupted marks a request an outage cut short, so that sending it again
// later may succeed: the connection to Weir broke, a mutation ended UNKNOWN
// with UNAVAILABLE, or a Native request that began ended with UNAVAILABLE or
// without its end. Whether the backend ran it is unknown, so send it again
// only when repeating it is safe, as it is for a read. A request a server
// refused before it began is not interrupted: it took no effect, and the
// Client already sent it again. Neither is a request that failed for a reason
// of its own, or whose context ended.
//
// ErrInterrupted does not tell whether a write applied. A write certainly took
// no effect only when its *Error has the Outcome MutationNotStarted or
// MutationNotApplied, or the Completion NativeNotStarted. After any other
// error, a context error included, it may have applied.
var ErrInterrupted = errors.New("weir: interrupted")
// Error is a Failure Weir reported for one record or Native request.
type Error struct {
// Outcome is the outcome of a mutation, and zero for a read or Native
// request.
Outcome MutationOutcome
// Completion is how far a Native request got, and zero for a record or a
// Native response that stopped without its end.
Completion NativeCompletion
// Failure is nil when the request has no result or its Native response
// stopped early without one.
Failure *Failure
reason string
interrupted bool
}
func (e *Error) Error() string {
text := "weir"
if e.Outcome != 0 {
text += ": mutation " + e.Outcome.String()
}
if e.Completion != 0 {
text += ": native " + e.Completion.String()
}
if e.Failure != nil {
text += fmt.Sprintf(": %s: %s", e.Failure.GetCode(), e.Failure.GetMessage())
}
if e.reason != "" {
text += ": " + e.reason
}
return text
}
// Unwrap returns ErrInterrupted for an interrupted request.
func (e *Error) Unwrap() error {
if e.interrupted {
return ErrInterrupted
}
return nil
}
// CodeOf returns the FailureCode of the first *Error in err's chain, or zero
// when there is none or it has no Failure.
func CodeOf(err error) FailureCode {
var failed *Error
if !errors.As(err, &failed) {
return 0
}
return failed.Failure.GetCode()
}
// MutationErr returns nil for an APPLIED result without a Failure, and an
// *Error otherwise. APPLIED with a Failure has applied, so never send it again.
// A nil result, a position a broken call left unconfirmed, may have applied.
func MutationErr(result *MutationResult) error {
if result == nil {
failed := &Error{Outcome: MutationUnknown, reason: "without a result", interrupted: true}
return failed
}
outcome := result.GetOutcome()
if outcome == MutationApplied && result.GetFailure() == nil {
return nil
}
interrupted := outcome == MutationUnknown && result.GetFailure().GetCode() == FailureUnavailable
failed := &Error{Outcome: outcome, Failure: result.GetFailure(), interrupted: interrupted}
return failed
}
// Err returns nil for a read that returned a document or confirmed it
// missing, and an *Error for a read that failed or has no result.
func (r *ReadResult) Err() error {
if r == nil {
failed := &Error{reason: "read without a result", interrupted: true}
return failed
}
if r.Failure != nil {
failed := &Error{Failure: r.Failure}
return failed
}
return nil
}
// Err returns nil for a Native request whose response arrived complete, and an
// *Error otherwise. The response's own status, such as an HTTP 404 or a
// MongoDB reply with ok: 0, is data for the caller and never an Err.
func (r *NativeResult) Err() error {
if r == nil {
failed := &Error{reason: "native request without a result", interrupted: true}
return failed
}
if r.Failure != nil {
interrupted := r.Completion != NativeNotStarted && r.Failure.GetCode() == FailureUnavailable
failed := &Error{Completion: r.Completion, Failure: r.Failure, interrupted: interrupted}
return failed
}
// A terminal that is not complete carries a Failure, so this response
// stopped without one.
if r.Completion != NativeResponseComplete {
failed := &Error{Completion: r.Completion, reason: "native response without its end", interrupted: true}
return failed
}
return nil
}