I made a server with client hitting throught http. I set retry mechanism in the client inside its Transport's RoundTripper method. Here's the example of working code for each server and client:
server main.go
package main
import (
"fmt"
"net/http"
"time"
)
func test(w http.ResponseWriter, req *http.Request) {
time.Sleep(2 * time.Second)
fmt.Fprintf(w, "hello\n")
}
func main() {
http.HandleFunc("/test", test)
http.ListenAndServe(":8090", nil)
}
client main.go
package main
import (
"context"
"fmt"
"log"
"net/http"
"time"
)
type Retry struct {
nums int
transport http.RoundTripper
}
// to retry
func (r *Retry) RoundTrip(req *http.Request) (resp *http.Response, err error) {
for i := 0; i < r.nums; i++ {
log.Println("Attempt: ", i+1)
resp, err = r.transport.RoundTrip(req)
if resp != nil && err == nil {
return
}
log.Println("Retrying...")
}
return
}
func main() {
r := &Retry{
nums: 5,
transport: http.DefaultTransport,
}
c := &http.Client{Transport: r}
// each request will be timeout in 1 second
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:8090/test", nil)
if err != nil {
panic(err)
}
resp, err := c.Do(req)
if err != nil {
panic(err)
}
fmt.Println(resp.StatusCode)
}
What's happening is the retry seems only work for first iteration. For subsequent iteration it doesn't wait for one second each, instead the debugging message printed for as much as the retry nums.
I expect the retry attempt to be waiting 1 second each as I put the timeout for 1 second in the context. But it seems only wait for 1 second for whole retries. What do I miss?
Beside, how to stop server from processing timeout request?, I saw CloseNotifier already deprecated.