The delay d(n) for the nth retry was
d(1) = rand(initial_interval)
d(n+1) = d(n) + rand(d(n))
There are two problem with this:
1) The entire sequence is dominated by the random value for d(1). If
this is a small value, lots of retries at short interval ensue. In
extremis, if d(1) is 0, indefinite immediate retries would ensue.
2) The delay is not a true exponential backoff; the upper bound only
increases exponentially *probabilistically*.
The new algorithm calculates
d(n) = random_value in range [i-i/2,i+i/2],
where i = initial_interval * 1.5^(n-1).
Thus d(1) is at least initial_interval/2, and successive values are
independent of previous values, forming a true exponential sequence of
intervals bounds between which the retry delay is chosen randomly.
Due to the change in algorithm we reduce...
- the initial interval from 5s to 2s. Recall that previously d(1) was
in the range [0,initial_interval=5s]. It is now [2-2/2=1s,2+2/2=3s].
- the max interval from 10 minutes to 6. Previously, once that was
reached, it would stay exactly there. It is now randomly chosen in
the range [6-6/2=3m,6+6/2=9min].
Thus previously delays would range from 0 to 10 minutes, now they
range from 1s to 9 minutes.
Fixes#412.
Using the Ring CRDT and Weave gossip, provides an interface
for the weave script to allocate IP addresses in `weave run`,
`weave start` and `weave expose`.
See docs/ipam.md for implementation details, and site/features.md
for user-visible changes.
...by moving the logic into the connection actor goroutine.
The heartbeater goroutine was doing a lot more than just heartbeating;
namely it also had tickers for triggering a ProtocolFetchAll and
initiating a fragmentation test. Furhermore, ensureHeartbeats also
spawned the forwarders.
So this was quite a mix of functionality, and, furthermore, most of it
related quite closely to the connection actor. So moving the
functionality into that simplifies the code.
In the process we also fix#294.