Detect when a fargo error indicates not found
The fargo library already provides the HTTPResponseStatusCode function
to extract an HTTP status code from a returned error, but here we want
to be able to inject similar errors for tests, so look for both a real
fargo error indicating that a heartbeat attempt failed to find its
target instance and a synthetic error returned by a fake connection
during a test.
Steven E. Harris
6 years ago
27 | 27 | type fargoUnsuccessfulHTTPResponse struct { |
28 | 28 | statusCode int |
29 | 29 | messagePrefix string |
30 | } | |
31 | ||
32 | func (u *fargoUnsuccessfulHTTPResponse) Error() string { | |
33 | return fmt.Sprintf("err=%s code=%d", u.messagePrefix, u.statusCode) | |
30 | 34 | } |
31 | 35 | |
32 | 36 | // Registrar maintains service instance liveness information in Eureka. |
109 | 113 | } |
110 | 114 | } |
111 | 115 | |
116 | func httpResponseStatusCode(err error) (code int, present bool) { | |
117 | if code, ok := fargo.HTTPResponseStatusCode(err); ok { | |
118 | return code, true | |
119 | } | |
120 | // Allow injection of errors for testing. | |
121 | if u, ok := err.(*fargoUnsuccessfulHTTPResponse); ok { | |
122 | return u.statusCode, true | |
123 | } | |
124 | return 0, false | |
125 | } | |
126 | ||
127 | func isNotFound(err error) bool { | |
128 | code, ok := httpResponseStatusCode(err) | |
129 | return ok && code == http.StatusNotFound | |
130 | } | |
131 | ||
112 | 132 | func (r *Registrar) heartbeat() error { |
113 | 133 | err := r.conn.HeartBeatInstance(r.instance) |
114 | if err != nil { | |
115 | if u, ok := err.(*fargoUnsuccessfulHTTPResponse); ok && u.statusCode == http.StatusNotFound { | |
116 | // Instance expired (e.g. network partition). Re-register. | |
117 | r.logger.Log("during", "heartbeat", err.Error()) | |
118 | return r.conn.ReregisterInstance(r.instance) | |
119 | } | |
134 | if err == nil { | |
135 | return nil | |
136 | } | |
137 | if isNotFound(err) { | |
138 | // Instance expired (e.g. network partition). Re-register. | |
139 | return r.conn.ReregisterInstance(r.instance) | |
120 | 140 | } |
121 | 141 | return err |
122 | 142 | } |
123 | ||
124 | func (u *fargoUnsuccessfulHTTPResponse) Error() string { | |
125 | return fmt.Sprintf("err=%s code=%d", u.messagePrefix, u.statusCode) | |
126 | } |