Skip to content

Instantly share code, notes, and snippets.

@vcabbage
Last active October 11, 2016 21:20
Show Gist options
  • Save vcabbage/a41b96c4b9ef0af128ac1227c44b3536 to your computer and use it in GitHub Desktop.
Save vcabbage/a41b96c4b9ef0af128ac1227c44b3536 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"time"
"golang.org/x/sync/singleflight"
)
func main() {
var requestGroup singleflight.Group
http.HandleFunc("/github", func(w http.ResponseWriter, r *http.Request) {
// With DoChan we get a channel of singleflight.Result
ch := requestGroup.DoChan("github", func() (interface{}, error) {
return githubStatus()
})
// Create our timeout
timeout := time.After(500 * time.Millisecond)
var result singleflight.Result
select {
case <-timeout: // Timeout elapsed, send a timeout message (504)
log.Println("/github handler timed out")
http.Error(w, "github request timed out", http.StatusGatewayTimeout)
return
case result = <-ch: // Received result from channel
}
// singleflight.Result is the same three values as returned from Do(), but wrapped
// in a struct. We can use the same logic as before, buy referencing the struct fields.
if result.Err != nil {
http.Error(w, result.Err.Error(), http.StatusInternalServerError)
return
}
status := result.Val.(string)
log.Printf("/github handler requst: status %q, shared result %t", status, result.Shared)
fmt.Fprintf(w, "GitHub Status: %q", status)
})
http.ListenAndServe("127.0.0.1:8080", nil)
}
// githubStatus retrieves GitHub's API status
func githubStatus() (string, error) {
log.Println("Making request to GitHub API")
defer log.Println("Request to GitHub API Complete")
time.Sleep(1 * time.Second)
resp, err := http.Get("https://status.github.com/api/status.json")
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return "", fmt.Errorf("github response: %s", resp.Status)
}
r := struct{ Status string }{}
err = json.NewDecoder(resp.Body).Decode(&r)
return r.Status, err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment