errclass.go
1 package memory 2 3 import "errors" 4 5 type ErrorClass int 6 7 const ( 8 ClassOK ErrorClass = iota 9 ClassRetryable 10 ClassPermanent 11 ClassUnavailable 12 ) 13 14 func (c ErrorClass) String() string { 15 return [...]string{"ok", "retryable", "permanent", "unavailable"}[c] 16 } 17 18 // ErrTransport is returned by Client when the call failed before the 19 // sidecar could reply (refused, EOF, timeout, ctx cancel, decode failure). 20 var ErrTransport = errors.New("memory: transport failure") 21 22 func ClassifyTransportError(err error) ErrorClass { 23 if err == nil { 24 return ClassOK 25 } 26 return ClassUnavailable 27 } 28 29 // ClassifyHTTP maps (status, envelope) → ErrorClass per the design's §8 table. 30 // Unknown sub_codes default to ClassRetryable (fail-open). 31 func ClassifyHTTP(status int, env *ResponseEnvelope) ErrorClass { 32 if status >= 200 && status < 300 { 33 return ClassOK 34 } 35 sub := "" 36 code := "" 37 if env != nil && env.Error != nil { 38 sub = env.Error.SubCode() 39 code = env.Error.Code 40 } 41 switch status { 42 case 400: 43 return ClassPermanent 44 case 401, 403: 45 return ClassPermanent 46 case 409: 47 return ClassRetryable 48 case 422: 49 return ClassPermanent 50 case 503: 51 if code == "not_ready" || sub == "not_ready" { 52 return ClassUnavailable 53 } 54 return ClassPermanent 55 case 500: 56 return ClassRetryable 57 } 58 return ClassRetryable 59 }