Go Heartbeat: Difference between revisions

From NovaOrdis Knowledge Base
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(".")
	}
}