func (h serverHandler) serveKeys(w http.ResponseWriter, r *http.Request) { if !allowMethod(w, r.Method, "GET", "PUT", "POST", "DELETE") { return } ctx, cancel := context.WithTimeout(context.Background(), h.timeout) defer cancel() rr, err := parseRequest(r, etcdserver.GenID()) if err != nil { writeError(w, err) return } resp, err := h.server.Do(ctx, rr) if err != nil { writeError(w, err) return } switch { case resp.Event != nil: if err := writeEvent(w, resp.Event, h.timer); err != nil { // Should never be reached log.Printf("error writing event: %v", err) } case resp.Watcher != nil: ctx, cancel := context.WithTimeout(context.Background(), defaultWatchTimeout) defer cancel() handleWatch(ctx, w, resp.Watcher, rr.Stream, h.timer) default: writeError(w, errors.New("received response with no Event/Watcher!")) } }
// publish registers server information into the cluster. The information // is the JSON representation of this server's member struct, updated with the // static clientURLs of the server. // The function keeps attempting to register until it succeeds, // or its server is stopped. // TODO: take care of info fetched from cluster store after having reconfig. func (s *EtcdServer) publish(retryInterval time.Duration) { m := *s.ClusterStore.Get().FindName(s.name) m.ClientURLs = s.clientURLs.StringSlice() b, err := json.Marshal(m) if err != nil { log.Printf("etcdserver: json marshal error: %v", err) return } req := pb.Request{ ID: GenID(), Method: "PUT", Path: m.storeKey(), Val: string(b), } for { ctx, cancel := context.WithTimeout(context.Background(), retryInterval) _, err := s.Do(ctx, req) cancel() switch err { case nil: log.Printf("etcdserver: published %+v to the cluster", m) return case ErrStopped: log.Printf("etcdserver: aborting publish because server is stopped") return default: log.Printf("etcdserver: publish error: %v", err) } } }
func ExampleWithTimeout() { // Pass a context with a timeout to tell a blocking function that it // should abandon its work after the timeout elapses. ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond) select { case <-time.After(200 * time.Millisecond): fmt.Println("overslept") case <-ctx.Done(): fmt.Println(ctx.Err()) // prints "context deadline exceeded" } // Output: // context deadline exceeded }
func (c *httpClient) Get(key string) (*Response, error) { get := &getAction{ Key: key, Recursive: false, } ctx, cancel := context.WithTimeout(context.Background(), c.timeout) httpresp, body, err := c.do(ctx, get) cancel() if err != nil { return nil, err } return unmarshalHTTPResponse(httpresp.StatusCode, body) }
func (c *httpClient) Create(key, val string, ttl time.Duration) (*Response, error) { uintTTL := uint64(ttl.Seconds()) create := &createAction{ Key: key, Value: val, TTL: &uintTTL, } ctx, cancel := context.WithTimeout(context.Background(), c.timeout) httpresp, body, err := c.do(ctx, create) cancel() if err != nil { return nil, err } return unmarshalHTTPResponse(httpresp.StatusCode, body) }
// sync proposes a SYNC request and is non-blocking. // This makes no guarantee that the request will be proposed or performed. // The request will be cancelled after the given timeout. func (s *EtcdServer) sync(timeout time.Duration) { ctx, cancel := context.WithTimeout(context.Background(), timeout) req := pb.Request{ Method: "SYNC", Id: GenID(), Time: time.Now().UnixNano(), } data, err := req.Marshal() if err != nil { log.Printf("marshal request %#v error: %v", req, err) return } // There is no promise that node has leader when do SYNC request, // so it uses goroutine to propose. go func() { s.Node.Propose(ctx, data) cancel() }() }
func (h serverHandler) serveKeys(w http.ResponseWriter, r *http.Request) { if !allowMethod(w, r.Method, "GET", "PUT", "POST", "DELETE") { return } ctx, cancel := context.WithTimeout(context.Background(), h.timeout) defer cancel() rr, err := parseRequest(r, etcdserver.GenID()) if err != nil { writeError(w, err) return } resp, err := h.server.Do(ctx, rr) if err != nil { writeError(w, err) return } var ev *store.Event switch { case resp.Event != nil: ev = resp.Event case resp.Watcher != nil: if ev, err = waitForEvent(ctx, w, resp.Watcher); err != nil { http.Error(w, err.Error(), http.StatusGatewayTimeout) return } default: writeError(w, errors.New("received response with no Event/Watcher!")) return } if err = writeEvent(w, ev); err != nil { // Should never be reached log.Println("error writing event: %v", err) } }
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // TODO: set read/write timeout? timeout := h.Timeout if timeout == 0 { timeout = DefaultTimeout } ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() switch { case strings.HasPrefix(r.URL.Path, "/raft"): h.serveRaft(ctx, w, r) case strings.HasPrefix(r.URL.Path, keysPrefix): h.serveKeys(ctx, w, r) case strings.HasPrefix(r.URL.Path, machinesPrefix): h.serveMachines(w, r) default: http.NotFound(w, r) } }