certimate/pkg/utils/wait/until.go

104 lines
2.9 KiB
Go

package wait
import (
"context"
"time"
)
// 等待直到条件满足。
//
// 入参:
// - condition: 条件函数,接收尝试次数作为参数,返回是否满足条件和错误。
// - interval: 执行条件函数的间隔时间。
//
// 出参:
// - ret: 是否满足条件。
// - err: 错误。
func Until(condition func(index int) (bool, error), interval time.Duration) (bool, error) {
conditionWithContext := func(_ context.Context, index int) (bool, error) {
return condition(index)
}
return UntilWithContext(context.Background(), conditionWithContext, interval)
}
// 等待直到条件满足,或上下文被取消。
//
// 入参:
// - ctx: 上下文。
// - condition: 条件函数,接收上下文和尝试次数作为参数,返回是否满足条件和错误。
// - interval: 执行条件函数的间隔时间。
//
// 出参:
// - ret: 是否满足条件。
// - err: 错误。
func UntilWithContext(ctx context.Context, condition func(ctx context.Context, index int) (bool, error), interval time.Duration) (bool, error) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
attempt := 0
for {
select {
case <-ctx.Done():
return false, ctx.Err()
case <-ticker.C:
attempt++
ret, err := condition(ctx, attempt)
if ret || err != nil {
return ret, err
}
}
}
}
// 等待直到条件满足或超时。
//
// 入参:
// - condition: 条件函数,接收尝试次数作为参数,返回是否满足条件和错误。
// - timeout: 超时时间。
// - interval: 执行条件函数的间隔时间。
//
// 出参:
// - ret: 是否满足条件。
// - err: 错误。
func UntilTimeout(condition func(index int) (bool, error), timeout time.Duration, interval time.Duration) (bool, error) {
conditionWithContext := func(_ context.Context, index int) (bool, error) {
return condition(index)
}
return UntilTimeoutWithContext(context.Background(), conditionWithContext, timeout, interval)
}
// 等待直到条件满足或超时,或上下文被取消。
//
// 入参:
// - ctx: 上下文。
// - condition: 条件函数,接收上下文和尝试次数作为参数,返回是否满足条件和错误。
// - timeout: 超时时间。
// - interval: 执行条件函数的间隔时间。
//
// 出参:
// - ret: 是否满足条件。
// - err: 错误。
func UntilTimeoutWithContext(ctx context.Context, condition func(ctx context.Context, index int) (bool, error), timeout time.Duration, interval time.Duration) (bool, error) {
ctxWithTimeout, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
ticker := time.NewTicker(interval)
defer ticker.Stop()
attempt := 0
for {
select {
case <-ctxWithTimeout.Done():
return false, ctx.Err()
case <-ticker.C:
attempt++
ret, err := condition(ctxWithTimeout, attempt)
if ret || err != nil {
return ret, err
}
}
}
}