// receive reads result from the decoder in a loop and sends down the result channel. func (sw *StreamWatcher) receive() { defer close(sw.result) defer sw.Stop() defer util.HandleCrash() for { action, obj, err := sw.source.Decode() if err != nil { // Ignore expected error. if sw.stopping() { return } switch err { case io.EOF: // watch closed normally case io.ErrUnexpectedEOF: glog.V(1).Infof("Unexpected EOF during watch stream event decoding: %v", err) default: msg := "Unable to decode an event from the watch stream: %v" if util.IsProbableEOF(err) { glog.V(5).Infof(msg, err) } else { glog.Errorf(msg, err) } } return } sw.result <- Event{ Type: action, Object: obj, } } }
// Watch attempts to begin watching the requested location. // Returns a watch.Interface, or an error. func (r *Request) Watch() (watch.Interface, error) { if r.err != nil { return nil, r.err } url := r.URL().String() req, err := http.NewRequest(r.verb, url, r.body) if err != nil { return nil, err } client := r.client if client == nil { client = http.DefaultClient } time.Sleep(r.backoffMgr.CalculateBackoff(r.URL())) resp, err := client.Do(req) updateURLMetrics(r, resp, err) if r.baseURL != nil { if err != nil { r.backoffMgr.UpdateBackoff(r.baseURL, err, 0) } else { r.backoffMgr.UpdateBackoff(r.baseURL, err, resp.StatusCode) } } if err != nil { // The watch stream mechanism handles many common partial data errors, so closed // connections can be retried in many cases. if util.IsProbableEOF(err) { return watch.NewEmptyWatch(), nil } return nil, err } if resp.StatusCode != http.StatusOK { if result := r.transformResponse(resp, req); result.err != nil { return nil, result.err } return nil, fmt.Errorf("for request '%+v', got status: %v", url, resp.StatusCode) } return watch.NewStreamWatcher(watchjson.NewDecoder(resp.Body, r.codec)), nil }