Go Heartbeat: Difference between revisions
Jump to navigation
Jump to search
Line 25: | Line 25: | ||
} | } | ||
go func() { | go func() { | ||
defer close(c) | defer close(c) // we own the channel, we must close it when it's not needed anymore | ||
defer ticker.Stop() | defer ticker.Stop() | ||
for { | for { |
Latest revision as of 21:19, 13 February 2024
External
- Concurrency in Go Katherine Cox-Buday, Chapter 5. "Concurrency at Scale" Section "Heartbeats"
Internal
Overview
Heartbeats are a way for concurrent processes to signal life to outside parties.
There are two different types of heartbeats: that occur on a time interval, and that occur at the beginning of a unit of work.
Example
// makeHeartbeatChannel will start a goroutine that sends heartbeats with the given duration on the channel
// returned as result. The heartbeat will be canceled when the context is canceled. When the heartbeat is
// canceled, the returned channel will be closed.
func makeHeartbeatChannel(ctx context.Context, interval time.Duration) <-chan interface{} {
c := make(chan interface{})
ticker := time.NewTicker(interval)
sendHeartbeat := func() {
select {
case c <- struct{}{}:
default:
// if the channel is blocked, give up, we'll send heartbeat next time
}
}
go func() {
defer close(c) // we own the channel, we must close it when it's not needed anymore
defer ticker.Stop()
for {
select {
case <-ctx.Done():
fmt.Println("context canceled")
return
case <-ticker.C:
sendHeartbeat()
}
}
}()
return c
}
...
ctx, cancel := context.WithCancel(context.Background())
heartbeat := makeHeartbeatChannel(ctx, 1*time.Second)
go func() {
<-time.After(10 * time.Second)
cancel()
}()
for {
select {
case _, ok := <-heartbeat:
if ok == false {
return
}
fmt.Println(".")
}
}