OLD | NEW |
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package retry | 5 package retry |
6 | 6 |
7 import ( | 7 import ( |
8 "time" | 8 "time" |
9 | 9 |
10 "github.com/luci/luci-go/common/errors" | 10 "github.com/luci/luci-go/common/errors" |
11 "golang.org/x/net/context" | 11 "golang.org/x/net/context" |
12 ) | 12 ) |
13 | 13 |
14 // transientOnlyIterator is an Iterator implementation that only retries errors | 14 // transientOnlyIterator is an Iterator implementation that only retries errors |
15 // if they are transient. | 15 // if they are tagged with `retry.Tag`. |
16 // | |
17 // (See errors.IsTransient). | |
18 type transientOnlyIterator struct { | 16 type transientOnlyIterator struct { |
19 Iterator // The wrapped Iterator. | 17 Iterator // The wrapped Iterator. |
20 } | 18 } |
21 | 19 |
22 func (i *transientOnlyIterator) Next(ctx context.Context, err error) time.Durati
on { | 20 func (i *transientOnlyIterator) Next(ctx context.Context, err error) time.Durati
on { |
23 » if !errors.IsTransient(err) { | 21 » if !Tag.In(err) { |
24 return Stop | 22 return Stop |
25 } | 23 } |
26 return i.Iterator.Next(ctx, err) | 24 return i.Iterator.Next(ctx, err) |
27 } | 25 } |
28 | 26 |
29 // TransientOnly returns an Iterator that wraps another Iterator. It will fall | 27 // TransientOnly returns an Iterator that wraps another Iterator. It will fall |
30 // through to the wrapped Iterator if a transient error is encountered; | 28 // through to the wrapped Iterator if a transient error is encountered; |
31 // otherwise, it will not retry. | 29 // otherwise, it will not retry. |
32 // Returns nil if f is nil. | 30 // Returns nil if f is nil. |
33 func TransientOnly(f Factory) Factory { | 31 func TransientOnly(f Factory) Factory { |
34 if f == nil { | 32 if f == nil { |
35 return nil | 33 return nil |
36 } | 34 } |
37 return wrap(f, func(it Iterator) Iterator { | 35 return wrap(f, func(it Iterator) Iterator { |
38 return &transientOnlyIterator{it} | 36 return &transientOnlyIterator{it} |
39 }) | 37 }) |
40 } | 38 } |
| 39 |
| 40 // Tag is used to indicate that an error should be retried by this package. Use |
| 41 // like: |
| 42 // err = retry.Tag.Apply(err) |
| 43 // |
| 44 // This allows libraries to preserve the original error, but indicate to the |
| 45 // retry library that the error may be transient. |
| 46 var Tag = errors.NewBoolTag("this error may go away with a retry") |
OLD | NEW |