this repo has no description

:sparkles: (Go) select for channels

Changed files
+94
Go
+42
Go/racer/racer.go
··· 1 + package racer 2 + 3 + import ( 4 + "fmt" 5 + "net/http" 6 + "time" 7 + ) 8 + 9 + var tenSecondTimeout = 10 * time.Second 10 + 11 + func Racer(a, b string) (winner string, error error) { 12 + return ConfigurableRacer(a, b, tenSecondTimeout) 13 + } 14 + 15 + func ConfigurableRacer(a, b string, timeout time.Duration) (winner string, error error) { 16 + // allows to wait on multiple channels, the first to respond will be executed 17 + select { 18 + case <-ping(a): 19 + return a, nil 20 + case <-ping(b): 21 + return b, nil 22 + case <-time.After(timeout): 23 + return "", fmt.Errorf("timed out waiting for %s and %s", a, b) 24 + } 25 + } 26 + 27 + func measureResponseTime(url string) time.Duration { 28 + start := time.Now() 29 + http.Get(url) 30 + return time.Since(start) 31 + } 32 + 33 + func ping(url string) chan struct{} { 34 + ch := make(chan struct{}) 35 + 36 + go func() { 37 + http.Get(url) 38 + close(ch) 39 + }() 40 + 41 + return ch 42 + }
+52
Go/racer/racer_test.go
··· 1 + package racer 2 + 3 + import ( 4 + "net/http" 5 + "net/http/httptest" 6 + "testing" 7 + "time" 8 + ) 9 + 10 + func TestRacer(t *testing.T) { 11 + t.Run("compares speed of servers, returning the url of the fastest one", func(t *testing.T) { 12 + slowServer := makeDelayedServer(20 * time.Millisecond) 13 + fastServer := makeDelayedServer(0 * time.Millisecond) 14 + 15 + // Defer makes so that this instructions are executed at the end of the function 16 + defer slowServer.Close() 17 + defer fastServer.Close() 18 + 19 + slowUrl := slowServer.URL 20 + fastUrl := fastServer.URL 21 + 22 + want := fastUrl 23 + got, err := Racer(slowUrl, fastUrl) 24 + 25 + if err != nil { 26 + t.Fatalf("did not expect an error but got one %v", err) 27 + } 28 + 29 + if got != want { 30 + t.Errorf("got %q, want %q", got, want) 31 + } 32 + }) 33 + 34 + t.Run("returns an error if a server doesn't respond within 10s", func(t *testing.T) { 35 + server := makeDelayedServer(25 * time.Millisecond) 36 + 37 + defer server.Close() 38 + 39 + _, err := ConfigurableRacer(server.URL, server.URL, 20 * time.Millisecond) 40 + 41 + if err == nil { 42 + t.Errorf("expected an error but didn't get one") 43 + } 44 + }) 45 + } 46 + 47 + func makeDelayedServer(delay time.Duration) *httptest.Server { 48 + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 49 + time.Sleep(delay) 50 + w.WriteHeader(http.StatusOK) 51 + })) 52 + }