This repository has been archived by the owner on Sep 6, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
56 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,80 +1,79 @@ | ||
// Package backoff provides facilities for creating interdependent backoff timers. | ||
// Package backoff provides facilities for working with interdependent backoff timers. | ||
// | ||
// The design of "backoff trees" proposed in this package is motivated by | ||
// https://github.com/libp2p/go-libp2p-swarm/issues/37. | ||
// This package is motivated by https://github.com/libp2p/go-libp2p-swarm/issues/37. | ||
// | ||
// The design proposed here can be dubbed "backoff trees", and is motivated by the following use case in libp2p: | ||
// | ||
// (1) Each peer has an associated backoff timer, whose significance is that no interaction | ||
// with this peer can commence unless the timer is clear. | ||
// (2) Each peer has a subordinate "find peer" timer, such that find peer operations should not | ||
// be attempted unless the "find peer" timer is clear and the "peer" timer is clear, as well. | ||
// (3) Each peer has any number of subordinate "transport" timers, such that dial attempts on any | ||
// given transport should not happen unless the "transport" timer is clear and the "peer" timer is clear, as well. | ||
// (4) Each TCP transport may have subordinate "IP" timers, such that TCP dial attempts to the given IP | ||
// should not commence unless the "IP", "transport" and "peer" timers are all clear. | ||
// We would like to associate backoff logic to each component of a multiaddr. | ||
// For instance, consider a typical multiaddr of the form IP/transport/protocol. | ||
// The backoff associated with IP dictates whether any multiaddr | ||
// using that IP can be dialed (regardless of transport and protocol). | ||
// The backoff associated with IP and transport dictates whether | ||
// any multiaddr using that IP and transport can be dialed (regardless of protocol). | ||
// And so on. | ||
// | ||
// This example highlights a hierarchical relationship that one might express, for instance as, as: | ||
// peer operations | ||
// find operations | ||
// transport-related operations | ||
// TCP-related operations | ||
// IP-related operations | ||
// Port-related operations | ||
// QUIC-related operations | ||
// | ||
// All nodes in this hierarchy may wish to use a different backoff policy. | ||
// However, in all cases, a timer node is considered "clear" if its own backoff timer is clear, | ||
// as well as the timers of all of its ancestors (all the way to the root). | ||
// | ||
// REMARKS | ||
// Furthermore, we stipulate that software components that utilize backoffs on multiaddrs | ||
// should share the backoff timers in order to benefit from each other's learnings. | ||
// | ||
// Note that this design can be extended to "backoff DAGS", wherein a timer can have multiple parents. | ||
// This can be useful, for instance, in the case when an IP address is viewed as a subordinate timer to multiple protocols, | ||
// like TCP and QUIC. | ||
// | ||
// While supporting timers with multiple parents is straightforward, it is not clear that it can be used conveniently | ||
// by independent code paths. In particular, a runtime instance of the QUIC transport may not (and probably should not) | ||
// be aware that a TCP transport instance is running in parallel. | ||
// To this end, this package provides the definition of a backoff timer (as the interface BackoffTimer), | ||
// as well as an interface for a shared set of backoff timers, called SharedBackoffs. | ||
package backoff | ||
|
||
import ( | ||
"time" | ||
|
||
ma "github.com/multiformats/go-multiaddr" | ||
) | ||
|
||
// NewBackoffTimer creates a new backoff timer. | ||
// The timer name is for display purposes only. | ||
func NewBackoffTimer(name string, policy BackoffPolicy, parent BackoffTimer) BackoffTimer { | ||
panic("not implemented") | ||
} | ||
// SharedBackoffs maintains backoff timers that are shared by multiple IPFS components. | ||
// Some of the timers are correlated. If this is the case, the relationships are documented in the access methods below. | ||
type SharedBackoffs interface { | ||
|
||
// BackoffPolicy represents a specific backoff logic. | ||
// | ||
// Implementations of BackoffPolicy are purely concerned with the "arithmetic" | ||
// of computing when the respective timer should be cleared (e.g. for making new connection retries). | ||
// | ||
// This interface allows for the implementation of flexible backoff policies. | ||
// For instance, a policy could treat a burst of backoffs as a single one. | ||
type BackoffPolicy interface { | ||
// Timers for dialing multiaddresses. | ||
|
||
// Clear informs the policy of the current time and sets its state to cleared. | ||
Clear(now time.Time) | ||
// IP returns the timer associated with a given IP address. | ||
// If the argument multiaddr does not start with an IP component, a panic is thrown. | ||
// The IP timer should be backed off, if it is determined that the IP itself is unreachable | ||
// (e.g. in response to a "no route to IP" error). | ||
// The IP timer should be cleared whenever any successful connection to this IP is established. | ||
IP(ma.Multiaddr) BackoffTimer | ||
|
||
// Backoff informs the policy of the current time and sets its state to backing off. | ||
Backoff(now time.Time) | ||
// IPTransport returns the timer associated with a given IP address and a transport (TCP, UDP, etc.). | ||
// If the argument multiaddr does not start with an IP and transport components, a panic is thrown. | ||
// The IP/Transport timer should be backed off, if it is determined that the IP is reachable but the transport is not. | ||
// The IP/Transport timer should be cleared whenever any successful connection to this IP/transport pair is established. | ||
// The IP/Transport timer will report a clear state whenever the IP and IP/Transport timers are both clear. | ||
IPTransport(ma.Multiaddr) BackoffTimer | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
petar
Author
|
||
|
||
// TimeToClear informs the policy of the current time and returns the duration | ||
// remaining until the back off state is cleared. Zero or negative durations indicate | ||
// that the state is already cleared. | ||
TimeToClear(now time.Time) time.Duration | ||
// IPTransportSwarm returns the timer associated with a given IP address, a transport (TCP, UDP, etc.) and the swarm service. | ||
// If the argument multiaddr does not start with an IP and transport components, a panic is thrown. | ||
// The IP/Transport/Swarm timer should be backed off, if it is determined that the IP is reachable | ||
// using the given transport, but the swarm service is not supported. | ||
// The IP/Transport/Swarm timer should be cleared whenever any successful connection to the IP/transport pair is established | ||
// and the swarm service is available. | ||
// The IP/Transport/Swarm timer will report a clear state whenever the respective IP, IP/Transport and IP/Transport/Swarm | ||
// timers are all clear. | ||
IPTransportSwarm(ma.Multiaddr) BackoffTimer | ||
|
||
// IPTransportSwarmProtocol returns the timer associated with a given IP address, transport (TCP, UDP, etc.) and | ||
// protocol, supported through the swarm service. | ||
// If the argument multiaddr does not start with an IP, transport and protocol components, a panic is thrown. | ||
// The IP/Transport/Swarm/Protocol timer should be backed off, if it is determined that the IP is reachable | ||
// using the given transport, the swarm service is supported, but the protocol is not. | ||
// The IP/Transport/Swarm/Protocol timer should be cleared whenever any successful connection to the protocol | ||
// is established through the swarm service on the given IP/transport. | ||
// The IP/Transport/Swarm/Protocol timer will report a clear state whenever the respective | ||
// IP, IP/Transport and IP/Transport/Swarm, and IP/Transport/Swarm/Protocol timers are all clear. | ||
IPTransportSwarmProtocol(ma.Multiaddr) BackoffTimer | ||
|
||
// Other shared backoff timers should be added here. | ||
} | ||
|
||
// BackoffTimer is a synchronous user-facing interface to a backoff timer. | ||
// Timers are created using NewBackoffTimer. | ||
// BackoffTimer is a user-facing interface to a backoff timer. | ||
type BackoffTimer interface { | ||
// Wait blocks until the timer and all of its ancestors (parent, grandparent, etc.), if any, have been cleared. | ||
Wait() | ||
// TimeToClear returns the duration remaining until the back off state is cleared. | ||
// Zero or negative durations indicate that the state is already cleared. | ||
TimeToClear(now time.Time) time.Duration | ||
// Clear clears this timer and returns instantaneously. | ||
// For example, a user might call this function after a successul connection attempt. | ||
Clear() | ||
|
Some of this distinction (IP vs ip+transport) can be encoded within a
Multiaddr
. ("ip4/1.2.3.4" vs "ip4/1.2.3.4/tcp/443")Can you figure out how specific of a timer in the tree to return based on how specific of a Multiaddr is passed in?