I'm trying to develop a simple API for Slack and I want to return something to the user right away to avoid the 3000 ms timeout.
Here are my questions:
Why the This should be printed to Slack first
doesn't get printed right away, instead I only got the last message which is The long and blocking process completed
? But it appears in ngrok log though.
Why is my function still reaching the 3000 ms limit even though I'm already using a go routine? Is it because of the done
channel?
func testFunc(w http.ResponseWriter, r *http.Request) {
// Return to the user ASAP to avoid 3000ms timeout.
// But this doesn't work. Nothing is returned but
// the message appeared in ngrok log.
fmt.Fprintln(w, "This should be printed to Slack first!")
// Get the response URL.
r.ParseForm()
responseURL := r.FormValue("response_url")
done := make(chan bool)
go func() {
fmt.Println("Warning! This is a long and blocking process.")
time.Sleep(5 * time.Second)
done <- true
}()
// This works! I received this message. But I still reached the 3000ms timeout.
func(d bool) {
if d == true {
payload := map[string]string{"text": "The long and blocking process completed!"}
j, err := json.Marshal(payload)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
http.Post(responseURL, "application/json", bytes.NewBuffer(j))
}
}(<-done)
}
http.ResponseWriter
streams are buffered by default. If you want data to be sent to a client in realtime (e.g. HTTP SSE), you need to flush the stream after each 'event':
wf, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
return
}
fmt.Fprintln(w, "This should be printed to Slack first!")
wf.Flush()
Flushing is expensive - so take advantage of go's buffering. There will always be an implicit flush once your handler finally exits (hence why you saw your output 'late').