mirror of
https://github.com/rclone/rclone
synced 2024-12-25 17:03:45 +01:00
Add Attack constant to pacer
This commit is contained in:
parent
874a64e5f6
commit
0166544319
@ -15,6 +15,7 @@ type Pacer struct {
|
||||
minSleep time.Duration // minimum sleep time
|
||||
maxSleep time.Duration // maximum sleep time
|
||||
decayConstant uint // decay constant
|
||||
attackConstant uint // attack constant
|
||||
pacer chan struct{} // To pace the operations
|
||||
sleepTime time.Duration // Time to sleep for each transaction
|
||||
retries int // Max number of retries
|
||||
@ -58,11 +59,12 @@ type Paced func() (bool, error)
|
||||
// New returns a Pacer with sensible defaults
|
||||
func New() *Pacer {
|
||||
p := &Pacer{
|
||||
minSleep: 10 * time.Millisecond,
|
||||
maxSleep: 2 * time.Second,
|
||||
decayConstant: 2,
|
||||
retries: fs.Config.LowLevelRetries,
|
||||
pacer: make(chan struct{}, 1),
|
||||
minSleep: 10 * time.Millisecond,
|
||||
maxSleep: 2 * time.Second,
|
||||
decayConstant: 2,
|
||||
attackConstant: 1,
|
||||
retries: fs.Config.LowLevelRetries,
|
||||
pacer: make(chan struct{}, 1),
|
||||
}
|
||||
p.sleepTime = p.minSleep
|
||||
p.SetPacer(DefaultPacer)
|
||||
@ -116,7 +118,7 @@ func (p *Pacer) SetMaxConnections(n int) *Pacer {
|
||||
// This is the speed the time falls back to the minimum after errors
|
||||
// have occurred.
|
||||
//
|
||||
// bigger for slower decay, exponential
|
||||
// bigger for slower decay, exponential. 1 is halve, 0 is go straight to minimum
|
||||
func (p *Pacer) SetDecayConstant(decay uint) *Pacer {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
@ -124,6 +126,19 @@ func (p *Pacer) SetDecayConstant(decay uint) *Pacer {
|
||||
return p
|
||||
}
|
||||
|
||||
// SetAttackConstant sets the attack constant for the pacer
|
||||
//
|
||||
// This is the speed the time grows from the minimum after errors have
|
||||
// occurred.
|
||||
//
|
||||
// bigger for slower attack, 1 is double, 0 is go straight to maximum
|
||||
func (p *Pacer) SetAttackConstant(attack uint) *Pacer {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
p.attackConstant = attack
|
||||
return p
|
||||
}
|
||||
|
||||
// SetRetries sets the max number of tries for Call
|
||||
func (p *Pacer) SetRetries(retries int) *Pacer {
|
||||
p.mu.Lock()
|
||||
@ -185,7 +200,11 @@ func (p *Pacer) beginCall() {
|
||||
func (p *Pacer) defaultPacer(retry bool) {
|
||||
oldSleepTime := p.sleepTime
|
||||
if retry {
|
||||
p.sleepTime *= 2
|
||||
if p.attackConstant == 0 {
|
||||
p.sleepTime = p.maxSleep
|
||||
} else {
|
||||
p.sleepTime = (p.sleepTime << p.attackConstant) / ((1 << p.attackConstant) - 1)
|
||||
}
|
||||
if p.sleepTime > p.maxSleep {
|
||||
p.sleepTime = p.maxSleep
|
||||
}
|
||||
|
@ -27,6 +27,9 @@ func TestNew(t *testing.T) {
|
||||
if p.decayConstant != 2 {
|
||||
t.Errorf("decayConstant")
|
||||
}
|
||||
if p.attackConstant != 1 {
|
||||
t.Errorf("attackConstant")
|
||||
}
|
||||
if cap(p.pacer) != 1 {
|
||||
t.Errorf("pacer 1")
|
||||
}
|
||||
@ -85,6 +88,58 @@ func TestSetDecayConstant(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecay(t *testing.T) {
|
||||
p := New().SetMinSleep(time.Microsecond).SetPacer(DefaultPacer).SetMaxSleep(time.Second)
|
||||
for _, test := range []struct {
|
||||
in time.Duration
|
||||
attackConstant uint
|
||||
want time.Duration
|
||||
}{
|
||||
{8 * time.Millisecond, 1, 4 * time.Millisecond},
|
||||
{1 * time.Millisecond, 0, time.Microsecond},
|
||||
{1 * time.Millisecond, 2, (3 * time.Millisecond) / 4},
|
||||
{1 * time.Millisecond, 3, (7 * time.Millisecond) / 8},
|
||||
} {
|
||||
p.sleepTime = test.in
|
||||
p.SetDecayConstant(test.attackConstant)
|
||||
p.defaultPacer(false)
|
||||
got := p.sleepTime
|
||||
if got != test.want {
|
||||
t.Errorf("bad sleep want %v got %v", test.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetAttackConstant(t *testing.T) {
|
||||
p := New().SetAttackConstant(19)
|
||||
if p.attackConstant != 19 {
|
||||
t.Errorf("didn't set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAttack(t *testing.T) {
|
||||
p := New().SetMinSleep(time.Microsecond).SetPacer(DefaultPacer).SetMaxSleep(time.Second)
|
||||
for _, test := range []struct {
|
||||
in time.Duration
|
||||
attackConstant uint
|
||||
want time.Duration
|
||||
}{
|
||||
{1 * time.Millisecond, 1, 2 * time.Millisecond},
|
||||
{1 * time.Millisecond, 0, time.Second},
|
||||
{1 * time.Millisecond, 2, (4 * time.Millisecond) / 3},
|
||||
{1 * time.Millisecond, 3, (8 * time.Millisecond) / 7},
|
||||
} {
|
||||
p.sleepTime = test.in
|
||||
p.SetAttackConstant(test.attackConstant)
|
||||
p.defaultPacer(true)
|
||||
got := p.sleepTime
|
||||
if got != test.want {
|
||||
t.Errorf("bad sleep want %v got %v", test.want, got)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSetRetries(t *testing.T) {
|
||||
p := New().SetRetries(18)
|
||||
if p.retries != 18 {
|
||||
|
Loading…
Reference in New Issue
Block a user