// 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 utilruntime.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 net.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) { // We specifically don't want to rate limit watches, so we // don't use r.throttle here. if r.err != nil { return nil, r.err } if r.serializers.Framer == nil { return nil, fmt.Errorf("watching resources is not possible with this client (content-type: %s)", r.content.ContentType) } url := r.URL().String() req, err := http.NewRequest(r.verb, url, r.body) if err != nil { return nil, err } req.Header = r.headers client := r.client if client == nil { client = http.DefaultClient } r.backoffMgr.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 net.IsProbableEOF(err) { return watch.NewEmptyWatch(), nil } return nil, err } if resp.StatusCode != http.StatusOK { defer resp.Body.Close() 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) } framer := r.serializers.Framer.NewFrameReader(resp.Body) decoder := streaming.NewDecoder(framer, r.serializers.StreamingSerializer) return watch.NewStreamWatcher(versioned.NewDecoder(decoder, r.serializers.Decoder)), nil }