gochannelgo-fiber

Channel is not sending data on the first API request


I have a SSE endpoint which sends data to the frontend, and that data is retrieved from another API endpoint. I'm still quite new with channels in go and it seems that i have to trigger the API endpoint twice so that the SSE endpoint will send the data once to the frontend. As for now, i have not written the frontend code to establish the SSE connection since I'm still playing around with channels. Could someone explain why this requires the API to be called twice for the SSE to send data?

The SSE route

func SendSSE(appCtx *fiber.Ctx, dataChannel chan string) error {
    appCtx.Set("Content-Type", "text/event-stream")
    appCtx.Set("Cache-Control", "no-cache")
    appCtx.Set("Connection", "keep-alive")
    appCtx.Set("Transfer-Encoding", "chunked")

    appCtx.Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) {
        log.Println("SSE Opened")
        for {
            log.Println("Retrieving data channel..")
            fmt.Fprintf(w, "data: Message: %s\n\n", <-dataChannel)
            log.Println(<-dataChannel)

            err := w.Flush()
            if err != nil {
                // Refreshing page in web browser will establish a new
                // SSE connection, but only (the last) one is alive, so
                // dead connections must be closed here.
                fmt.Printf("Error while flushing: %v. Closing http connection.\n", err)

                break
            }

        }
    }))

    fmt.Println("SSE Closed")
    return nil

}

API that sends data to sse

func GetApiData(appCtx *fiber.Ctx, dataChannel chan string) error {
    log.Println("Sending DataChannel data")
    dataChannel <- "Data is passed from api to sse"
    return appCtx.Status(http.StatusOK).SendString("Not Implemented")
}

Fiber logs


Solution

  • The reason you see this is that you are consuming 2 messages in this section

    fmt.Fprintf(w, "data: Message: %s\n\n", <-dataChannel)
    log.Println(<-dataChannel)
    

    Every odd message will get sent to SSE, every even message will be logged to the console. It should be changed to

    message := <-dataChannel
    fmt.Fprintf(w, "data: Message: %s\n\n", message)
    log.Println(message)