Check out my solution below. Sorry, I made the previous reply yesterday but then got distracted and forgot to send it. It is working now. Now I’m working on controlling the finnHubRealTime.Realtime to start, stop, restart. Making progress but crashing on the channel.
in main, I launch monitorRealTiimeChannel() as a go routine. It waits until realTimeGoRoutinesControllerChannel gets set.
In the realTimeHandler(), I populate the realTimeGoRoutinesControllerChannel, which triggers launching finnHubRealTime.Realtime() and it sets the variable: realTimeIsRunning to true. This works fine. The web page is updating every few seconds with the latest stock price.
Now, on the web page I want to switch to a different stock. So again it calls realTimeHandler(). The handler triggers the monitor with:
realTimeGoRoutinesControllerChannel ← &p
The monitor checks realTimeIsRunning and if true, it sets the p.DoRealTime to false and puts p into realTimeGoRoutinesControllerChannel. In the RealTime() function there is an anonymous go function stopped waiting on realTimeGoRoutinesControllerChannel. It checks the value of p.DoRealTime. If false it terminates the web socket processing. It then sets the channel to p.
The monitor has been waiting on the channel and receives the input. It then puts p into the channel, but I think it crashes because nobody is waiting on it. I tested this with this function:
func sendToChannel() {
ch := make(chan bool)
ch <- true
}
This crashes.
Here is my monitor. I apologize for all of the logging but it helps me when dealing with concurrency.
func monitorRealTimeChannel() {
for {
log.Println("monitorRealTimeChannel is waiting")
p := <-realTimeGoRoutinesControllerChannel
log.Println("received realTimeGoRoutinesControllerChannel")
if realTimeIsRunning {
log.Println("realTimeIsRunning")
realTimeIsRunning = false
log.Println("tell realtime to stop - p.DoRealTime = false")
p.DoRealTime = false // tell realtime to stop
log.Printf("p.DoRealTime: %v", p.DoRealTime)
log.Println("realTimeGoRoutinesControllerChannel <- p")
realTimeGoRoutinesControllerChannel <- p
//now wait until realtime has finished up
log.Println("now wait until realtime has finished up")
log.Println("p := <-realTimeGoRoutinesControllerChannel")
p := <-realTimeGoRoutinesControllerChannel
p.DoRealTime = true
log.Printf("p.DoRealTime: %v", p.DoRealTime)
// put p back into realTimeGoRoutinesControllerChannel
log.Println("put p back into realTimeGoRoutinesControllerChannel ")
log.Println("this crashes the app")
log.Println("realTimeGoRoutinesControllerChannel <- p")
// ah ha, the realTimeGoRoutinesControllerChannel has nobody waiting on it
realTimeGoRoutinesControllerChannel <- p
} else {
//tell realtime to run with this p
log.Println("realTimeIsRunning = false, so launch realtime")
realTimeIsRunning = true
go finnHubRealTime.Realtime(p.TrackSpecification.Stock.Symbol, realTimeGoRoutinesControllerChannel, &stock)
}
}
}
What I would like to do is have the monitor waiting on the channel again and then trigger it, but so far I haven’t figured out how to do that.
Then, it will be time to clean up the code as I’ve been doing a lot of trial and error to figure out web sockets, go routines, and channels.
more work …
OK, I guess I will need to study channels some more. The way I understand it, this line should cause a wait until the channel is populated:
p := <-realTimeGoRoutinesControllerChannel
But it didn’t wait and p is nil. This was the second time thru the loop after running realtime and then cancelling it.
I had disabled the code that sets p into the channel to see if I could at least stop the realtime. On this line, the channel is not nil but it allows receiving from it and populates p as nil.
OK, I have it working now. I had a defer close(ch) that I had forgotten about. But then I decided to use 2 channels instead of the 1 and then cut out a bunch of unnecessary code. Now it’s working. However, the markets are closed so I’m not getting much data.