Files
opencloud/vendor/github.com/open-policy-agent/opa/util/time.go
dependabot[bot] 8a4523b406 Bump github.com/open-policy-agent/opa from 0.69.0 to 0.70.0
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 0.69.0 to 0.70.0.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v0.69.0...v0.70.0)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-05 13:23:44 +01:00

49 lines
1.4 KiB
Go

package util
import "time"
// TimerWithCancel exists because of memory leaks when using
// time.After in select statements. Instead, we now manually create timers,
// wait on them, and manually free them.
//
// See this for more details:
// https://www.arangodb.com/2020/09/a-story-of-a-memory-leak-in-go-how-to-properly-use-time-after/
//
// Note: This issue is fixed in Go 1.23, but this fix helps us until then.
//
// Warning: the cancel cannot be done concurrent to reading, everything should
// work in the same goroutine.
//
// Example:
//
// for retries := 0; true; retries++ {
//
// ...main logic...
//
// timer, cancel := utils.TimerWithCancel(utils.Backoff(retries))
// select {
// case <-ctx.Done():
// cancel()
// return ctx.Err()
// case <-timer.C:
// continue
// }
// }
func TimerWithCancel(delay time.Duration) (*time.Timer, func()) {
timer := time.NewTimer(delay)
return timer, func() {
// Note: The Stop function returns:
// - true: if the timer is active. (no draining required)
// - false: if the timer was already stopped or fired/expired.
// In this case the channel should be drained to prevent memory
// leaks only if it is not empty.
// This operation is safe only if the cancel function is
// used in same goroutine. Concurrent reading or canceling may
// cause deadlock.
if !timer.Stop() && len(timer.C) > 0 {
<-timer.C
}
}
}