blob: e4b7f2f3e55345a0308316b4e8bf79a0a08919a2 [file] [log] [blame]
// Copyright 2019 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cli
import (
"context"
"time"
"go.chromium.org/luci/common/clock"
"go.chromium.org/luci/common/errors"
"go.chromium.org/luci/common/retry"
)
var notReady = errors.BoolTag{Key: errors.NewTagKey("not ready")}
// pollingIter implements the polling policy matching the one used by
// `swarming collect`:
// https://source.chromium.org/chromium/_/chromium/infra/luci/client-py.git/+/885b3febcc170a60f25795304e60927b77d1e92d:swarming.py;l=546;drc=7a76117d3fc4543d7e76c6fb3d39cc2977da0ab9
// which is
// Start with 1 sec delay and for each 30 sec of waiting add another second
// of delay, until hitting 15 sec ceiling.
//
// The error must be tagged with notReady for polling to continue.
type pollingIter struct {
start time.Time
}
func newPollingIter() retry.Iterator {
return &pollingIter{}
}
// Next implements Iterator.
func (c *pollingIter) Next(ctx context.Context, err error) time.Duration {
if !notReady.In(err) {
return retry.Stop
}
now := clock.Now(ctx)
if c.start.IsZero() {
c.start = now
}
delay := now.Sub(c.start) / 30 / time.Second
switch {
case delay < time.Second:
delay = time.Second
case delay > 15*time.Second:
delay = 15 * time.Second
}
return delay
}