Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
2b13bc47
Commit
2b13bc47
authored
Feb 24, 2016
by
Alex Robinson
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #21892 from jayunit100/backoff-flake-fix
fake backoff implementation for speeding up flakey test
parents
9d4c9c9c
4097cfe0
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
61 additions
and
21 deletions
+61
-21
request.go
pkg/client/unversioned/request.go
+4
-4
request_test.go
pkg/client/unversioned/request_test.go
+16
-7
urlbackoff.go
pkg/client/unversioned/urlbackoff.go
+9
-1
backoff.go
pkg/util/backoff.go
+9
-0
backoff_test.go
pkg/util/backoff_test.go
+0
-9
clock.go
pkg/util/clock.go
+13
-0
clock_test.go
pkg/util/clock_test.go
+10
-0
No files found.
pkg/client/unversioned/request.go
View file @
2b13bc47
...
@@ -645,7 +645,7 @@ func (r *Request) Watch() (watch.Interface, error) {
...
@@ -645,7 +645,7 @@ func (r *Request) Watch() (watch.Interface, error) {
if
client
==
nil
{
if
client
==
nil
{
client
=
http
.
DefaultClient
client
=
http
.
DefaultClient
}
}
time
.
Sleep
(
r
.
backoffMgr
.
CalculateBackoff
(
r
.
URL
()))
r
.
backoffMgr
.
Sleep
(
r
.
backoffMgr
.
CalculateBackoff
(
r
.
URL
()))
resp
,
err
:=
client
.
Do
(
req
)
resp
,
err
:=
client
.
Do
(
req
)
updateURLMetrics
(
r
,
resp
,
err
)
updateURLMetrics
(
r
,
resp
,
err
)
if
r
.
baseURL
!=
nil
{
if
r
.
baseURL
!=
nil
{
...
@@ -710,7 +710,7 @@ func (r *Request) Stream() (io.ReadCloser, error) {
...
@@ -710,7 +710,7 @@ func (r *Request) Stream() (io.ReadCloser, error) {
if
client
==
nil
{
if
client
==
nil
{
client
=
http
.
DefaultClient
client
=
http
.
DefaultClient
}
}
time
.
Sleep
(
r
.
backoffMgr
.
CalculateBackoff
(
r
.
URL
()))
r
.
backoffMgr
.
Sleep
(
r
.
backoffMgr
.
CalculateBackoff
(
r
.
URL
()))
resp
,
err
:=
client
.
Do
(
req
)
resp
,
err
:=
client
.
Do
(
req
)
updateURLMetrics
(
r
,
resp
,
err
)
updateURLMetrics
(
r
,
resp
,
err
)
if
r
.
baseURL
!=
nil
{
if
r
.
baseURL
!=
nil
{
...
@@ -792,7 +792,7 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
...
@@ -792,7 +792,7 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
}
}
req
.
Header
=
r
.
headers
req
.
Header
=
r
.
headers
time
.
Sleep
(
r
.
backoffMgr
.
CalculateBackoff
(
r
.
URL
()))
r
.
backoffMgr
.
Sleep
(
r
.
backoffMgr
.
CalculateBackoff
(
r
.
URL
()))
resp
,
err
:=
client
.
Do
(
req
)
resp
,
err
:=
client
.
Do
(
req
)
updateURLMetrics
(
r
,
resp
,
err
)
updateURLMetrics
(
r
,
resp
,
err
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -812,7 +812,7 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
...
@@ -812,7 +812,7 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
retries
++
retries
++
if
seconds
,
wait
:=
checkWait
(
resp
);
wait
&&
retries
<
maxRetries
{
if
seconds
,
wait
:=
checkWait
(
resp
);
wait
&&
retries
<
maxRetries
{
glog
.
V
(
4
)
.
Infof
(
"Got a Retry-After %s response for attempt %d to %v"
,
seconds
,
retries
,
url
)
glog
.
V
(
4
)
.
Infof
(
"Got a Retry-After %s response for attempt %d to %v"
,
seconds
,
retries
,
url
)
time
.
Sleep
(
time
.
Duration
(
seconds
)
*
time
.
Second
)
r
.
backoffMgr
.
Sleep
(
time
.
Duration
(
seconds
)
*
time
.
Second
)
return
false
return
false
}
}
fn
(
req
,
resp
)
fn
(
req
,
resp
)
...
...
pkg/client/unversioned/request_test.go
View file @
2b13bc47
...
@@ -767,17 +767,26 @@ func TestBackoffLifecycle(t *testing.T) {
...
@@ -767,17 +767,26 @@ func TestBackoffLifecycle(t *testing.T) {
// which are used in the server implementation returning StatusOK above.
// which are used in the server implementation returning StatusOK above.
seconds
:=
[]
int
{
0
,
1
,
2
,
4
,
8
,
0
,
1
,
2
,
4
,
0
}
seconds
:=
[]
int
{
0
,
1
,
2
,
4
,
8
,
0
,
1
,
2
,
4
,
0
}
request
:=
c
.
Verb
(
"POST"
)
.
Prefix
(
"backofftest"
)
.
Suffix
(
"abc"
)
request
:=
c
.
Verb
(
"POST"
)
.
Prefix
(
"backofftest"
)
.
Suffix
(
"abc"
)
clock
:=
util
.
FakeClock
{}
request
.
backoffMgr
=
&
URLBackoff
{
request
.
backoffMgr
=
&
URLBackoff
{
Backoff
:
util
.
NewBackOff
(
// Use a fake backoff here to avoid flakes and speed the test up.
Backoff
:
util
.
NewFakeBackOff
(
time
.
Duration
(
1
)
*
time
.
Second
,
time
.
Duration
(
1
)
*
time
.
Second
,
time
.
Duration
(
200
)
*
time
.
Second
)}
time
.
Duration
(
200
)
*
time
.
Second
,
&
clock
,
)}
for
_
,
sec
:=
range
seconds
{
for
_
,
sec
:=
range
seconds
{
start
:=
time
.
Now
()
thisBackoff
:=
request
.
backoffMgr
.
CalculateBackoff
(
request
.
URL
())
t
.
Logf
(
"Current backoff %v"
,
thisBackoff
)
if
thisBackoff
!=
time
.
Duration
(
sec
)
*
time
.
Second
{
t
.
Errorf
(
"Backoff is %v instead of %v"
,
thisBackoff
,
sec
)
}
now
:=
clock
.
Now
()
request
.
DoRaw
()
request
.
DoRaw
()
finish
:=
time
.
Since
(
start
)
elapsed
:=
clock
.
Since
(
now
)
t
.
Logf
(
"%v finished in %v"
,
sec
,
finish
)
if
clock
.
Since
(
now
)
!=
thisBackoff
{
if
finish
<
time
.
Duration
(
sec
)
*
time
.
Second
||
finish
>=
time
.
Duration
(
sec
+
5
)
*
time
.
Second
{
t
.
Errorf
(
"CalculatedBackoff not honored by clock: Expected time of %v, but got %v "
,
thisBackoff
,
elapsed
)
t
.
Fatalf
(
"%v not in range %v"
,
finish
,
sec
)
}
}
}
}
}
}
...
...
pkg/client/unversioned/urlbackoff.go
View file @
2b13bc47
...
@@ -35,6 +35,7 @@ var maxResponseCode = 499
...
@@ -35,6 +35,7 @@ var maxResponseCode = 499
type
BackoffManager
interface
{
type
BackoffManager
interface
{
UpdateBackoff
(
actualUrl
*
url
.
URL
,
err
error
,
responseCode
int
)
UpdateBackoff
(
actualUrl
*
url
.
URL
,
err
error
,
responseCode
int
)
CalculateBackoff
(
actualUrl
*
url
.
URL
)
time
.
Duration
CalculateBackoff
(
actualUrl
*
url
.
URL
)
time
.
Duration
Sleep
(
d
time
.
Duration
)
}
}
// URLBackoff struct implements the semantics on top of Backoff which
// URLBackoff struct implements the semantics on top of Backoff which
...
@@ -54,6 +55,9 @@ func (n *NoBackoff) UpdateBackoff(actualUrl *url.URL, err error, responseCode in
...
@@ -54,6 +55,9 @@ func (n *NoBackoff) UpdateBackoff(actualUrl *url.URL, err error, responseCode in
func
(
n
*
NoBackoff
)
CalculateBackoff
(
actualUrl
*
url
.
URL
)
time
.
Duration
{
func
(
n
*
NoBackoff
)
CalculateBackoff
(
actualUrl
*
url
.
URL
)
time
.
Duration
{
return
0
*
time
.
Second
return
0
*
time
.
Second
}
}
func
(
n
*
NoBackoff
)
Sleep
(
d
time
.
Duration
)
{
return
}
// Disable makes the backoff trivial, i.e., sets it to zero. This might be used
// Disable makes the backoff trivial, i.e., sets it to zero. This might be used
// by tests which want to run 1000s of mock requests without slowing down.
// by tests which want to run 1000s of mock requests without slowing down.
...
@@ -80,7 +84,7 @@ func (b *URLBackoff) baseUrlKey(rawurl *url.URL) string {
...
@@ -80,7 +84,7 @@ func (b *URLBackoff) baseUrlKey(rawurl *url.URL) string {
func
(
b
*
URLBackoff
)
UpdateBackoff
(
actualUrl
*
url
.
URL
,
err
error
,
responseCode
int
)
{
func
(
b
*
URLBackoff
)
UpdateBackoff
(
actualUrl
*
url
.
URL
,
err
error
,
responseCode
int
)
{
// range for retry counts that we store is [0,13]
// range for retry counts that we store is [0,13]
if
responseCode
>
maxResponseCode
||
serverIsOverloadedSet
.
Has
(
responseCode
)
{
if
responseCode
>
maxResponseCode
||
serverIsOverloadedSet
.
Has
(
responseCode
)
{
b
.
Backoff
.
Next
(
b
.
baseUrlKey
(
actualUrl
),
time
.
Now
())
b
.
Backoff
.
Next
(
b
.
baseUrlKey
(
actualUrl
),
b
.
Backoff
.
Clock
.
Now
())
return
return
}
else
if
responseCode
>=
300
||
err
!=
nil
{
}
else
if
responseCode
>=
300
||
err
!=
nil
{
glog
.
V
(
4
)
.
Infof
(
"Client is returning errors: code %v, error %v"
,
responseCode
,
err
)
glog
.
V
(
4
)
.
Infof
(
"Client is returning errors: code %v, error %v"
,
responseCode
,
err
)
...
@@ -95,3 +99,7 @@ func (b *URLBackoff) UpdateBackoff(actualUrl *url.URL, err error, responseCode i
...
@@ -95,3 +99,7 @@ func (b *URLBackoff) UpdateBackoff(actualUrl *url.URL, err error, responseCode i
func
(
b
*
URLBackoff
)
CalculateBackoff
(
actualUrl
*
url
.
URL
)
time
.
Duration
{
func
(
b
*
URLBackoff
)
CalculateBackoff
(
actualUrl
*
url
.
URL
)
time
.
Duration
{
return
b
.
Backoff
.
Get
(
b
.
baseUrlKey
(
actualUrl
))
return
b
.
Backoff
.
Get
(
b
.
baseUrlKey
(
actualUrl
))
}
}
func
(
b
*
URLBackoff
)
Sleep
(
d
time
.
Duration
)
{
b
.
Backoff
.
Clock
.
Sleep
(
d
)
}
pkg/util/backoff.go
View file @
2b13bc47
...
@@ -36,6 +36,15 @@ type Backoff struct {
...
@@ -36,6 +36,15 @@ type Backoff struct {
perItemBackoff
map
[
string
]
*
backoffEntry
perItemBackoff
map
[
string
]
*
backoffEntry
}
}
func
NewFakeBackOff
(
initial
,
max
time
.
Duration
,
tc
*
FakeClock
)
*
Backoff
{
return
&
Backoff
{
perItemBackoff
:
map
[
string
]
*
backoffEntry
{},
Clock
:
tc
,
defaultDuration
:
initial
,
maxDuration
:
max
,
}
}
func
NewBackOff
(
initial
,
max
time
.
Duration
)
*
Backoff
{
func
NewBackOff
(
initial
,
max
time
.
Duration
)
*
Backoff
{
return
&
Backoff
{
return
&
Backoff
{
perItemBackoff
:
map
[
string
]
*
backoffEntry
{},
perItemBackoff
:
map
[
string
]
*
backoffEntry
{},
...
...
pkg/util/backoff_test.go
View file @
2b13bc47
...
@@ -21,15 +21,6 @@ import (
...
@@ -21,15 +21,6 @@ import (
"time"
"time"
)
)
func
NewFakeBackOff
(
initial
,
max
time
.
Duration
,
tc
*
FakeClock
)
*
Backoff
{
return
&
Backoff
{
perItemBackoff
:
map
[
string
]
*
backoffEntry
{},
Clock
:
tc
,
defaultDuration
:
initial
,
maxDuration
:
max
,
}
}
func
TestSlowBackoff
(
t
*
testing
.
T
)
{
func
TestSlowBackoff
(
t
*
testing
.
T
)
{
id
:=
"_idSlow"
id
:=
"_idSlow"
tc
:=
NewFakeClock
(
time
.
Now
())
tc
:=
NewFakeClock
(
time
.
Now
())
...
...
pkg/util/clock.go
View file @
2b13bc47
...
@@ -27,6 +27,7 @@ type Clock interface {
...
@@ -27,6 +27,7 @@ type Clock interface {
Now
()
time
.
Time
Now
()
time
.
Time
Since
(
time
.
Time
)
time
.
Duration
Since
(
time
.
Time
)
time
.
Duration
After
(
d
time
.
Duration
)
<-
chan
time
.
Time
After
(
d
time
.
Duration
)
<-
chan
time
.
Time
Sleep
(
d
time
.
Duration
)
}
}
var
(
var
(
...
@@ -53,6 +54,10 @@ func (RealClock) After(d time.Duration) <-chan time.Time {
...
@@ -53,6 +54,10 @@ func (RealClock) After(d time.Duration) <-chan time.Time {
return
time
.
After
(
d
)
return
time
.
After
(
d
)
}
}
func
(
RealClock
)
Sleep
(
d
time
.
Duration
)
{
time
.
Sleep
(
d
)
}
// FakeClock implements Clock, but returns an arbitrary time.
// FakeClock implements Clock, but returns an arbitrary time.
type
FakeClock
struct
{
type
FakeClock
struct
{
lock
sync
.
RWMutex
lock
sync
.
RWMutex
...
@@ -137,6 +142,10 @@ func (f *FakeClock) HasWaiters() bool {
...
@@ -137,6 +142,10 @@ func (f *FakeClock) HasWaiters() bool {
return
len
(
f
.
waiters
)
>
0
return
len
(
f
.
waiters
)
>
0
}
}
func
(
f
*
FakeClock
)
Sleep
(
d
time
.
Duration
)
{
f
.
Step
(
d
)
}
// IntervalClock implements Clock, but each invocation of Now steps the clock forward the specified duration
// IntervalClock implements Clock, but each invocation of Now steps the clock forward the specified duration
type
IntervalClock
struct
{
type
IntervalClock
struct
{
Time
time
.
Time
Time
time
.
Time
...
@@ -159,3 +168,7 @@ func (i *IntervalClock) Since(ts time.Time) time.Duration {
...
@@ -159,3 +168,7 @@ func (i *IntervalClock) Since(ts time.Time) time.Duration {
func
(
*
IntervalClock
)
After
(
d
time
.
Duration
)
<-
chan
time
.
Time
{
func
(
*
IntervalClock
)
After
(
d
time
.
Duration
)
<-
chan
time
.
Time
{
panic
(
"IntervalClock doesn't implement After"
)
panic
(
"IntervalClock doesn't implement After"
)
}
}
func
(
*
IntervalClock
)
Sleep
(
d
time
.
Duration
)
{
panic
(
"IntervalClock doesn't implement Sleep"
)
}
pkg/util/clock_test.go
View file @
2b13bc47
...
@@ -37,6 +37,16 @@ func TestFakeClock(t *testing.T) {
...
@@ -37,6 +37,16 @@ func TestFakeClock(t *testing.T) {
}
}
}
}
func
TestFakeClockSleep
(
t
*
testing
.
T
)
{
startTime
:=
time
.
Now
()
tc
:=
NewFakeClock
(
startTime
)
tc
.
Sleep
(
time
.
Duration
(
1
)
*
time
.
Hour
)
now
:=
tc
.
Now
()
if
now
.
Sub
(
startTime
)
!=
time
.
Hour
{
t
.
Errorf
(
"Fake sleep failed, expected time to advance by one hour, instead, its %v"
,
now
.
Sub
(
startTime
))
}
}
func
TestFakeAfter
(
t
*
testing
.
T
)
{
func
TestFakeAfter
(
t
*
testing
.
T
)
{
tc
:=
NewFakeClock
(
time
.
Now
())
tc
:=
NewFakeClock
(
time
.
Now
())
if
tc
.
HasWaiters
()
{
if
tc
.
HasWaiters
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment