func()

in pkg/client/client_v2.go [765:804]


func (c *clientV2) startActions() {
	c.wg.Add(1)

	// results are held outside of the retry loop, because on re-connect
	// we still want to send the responses that either failed or haven't been
	// sent back to the agent.
	actionResults := make(chan *proto.ActionResponse, 100)
	go func() {
		defer c.wg.Done()
		// If the initial RPC connection fails, actionRoundTrip
		// returns immediately, so we set a timer to avoid spinlocking
		// on the error.
		retryInterval := 1 * time.Second
		retryTimer := time.NewTimer(retryInterval)
		for c.ctx.Err() == nil {
			actionDuration := durationOf(func() {
				c.actionRoundTrip(actionResults)
			})

			if actionDuration < time.Second {
				// If the action round trip lasted less than a second, we're
				// probably in an error loop -- apply exponential backoff up to 30s.
				retryInterval = nextExpBackoff(retryInterval, 30*time.Second)
			} else {
				retryInterval = 1 * time.Second
			}

			// After the RPC client closes, wait until either the timer interval
			// expires or the context is cancelled. Note that the timer waits
			// one second since the checkinRoundTrip was last _called_, not
			// since it returns; immediate retries are ok after an active
			// connection shuts down.
			select {
			case <-retryTimer.C:
				retryTimer.Reset(retryInterval)
			case <-c.ctx.Done():
			}
		}
	}()
}