Search code examples
linuxgowebsocketgorillaheartbeat

How to run a heartbeat function


I seen tons of questions with responses on how to periodically run a function. The problem? They all lock the program from moving on.

What I need? I have a websocket and I have a for {} that keeps reading for msg's and now and every 10 secs I need to run a call to the heartbeat function, with out interrupting the program or stop reading the chat. I am thinking in using some approaches but none of them seem clean/nice using channels, but I think someone more experienced may have a good and simpler approach to this.

I was using something like this but it never gets to the end of the function to return what I need for the program to continue.

timerCh := time.Tick(time.Duration(10) * time.Second)
  for range timerCh {
    go Heartbeat(ws)
}

return ws

I am looking for a way to be able to call Heartbeat every 10 secs with out:

  1. calling it repetitively every time I read for incoming websocket connections
  2. with out locking the program.

Some context, This is for a bridge chat, so I open a websocket, keep reading from this, and only sent to the other chat when is a chat msg, in the mean time I need to sent a heartbeat with out locking this. What do I have now? now it all works, but after 30 secs or so my websocket closes:

2020/07/01 20:59:09 Error read: websocket: close 1000 (normal)

Solution

  • EDIT: Go with @JimB's answer! This was just meant to show that the timer should be managed outside of the main goroutine.

    Your heartbeat function should manage its own timer. Something like this should work:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func main() {
        go heartbeat()
        for i := 0; i < 10; i++ {
            fmt.Println("main is still going")
            time.Sleep(time.Second * 3)
        }
    }
    
    func heartbeat() {
        for {
            timer := time.After(time.Second * 10)
            <-timer
            fmt.Println("heartbeat happened!")
        }
    }
    

    This example will print from main every 3 seconds and from heartbeat every 10 and will terminate after 30 seconds.