Documentation
¶
Index ¶
- type ClosestNodesIter
- type EventPoolAddFindCloserQuery
- type EventPoolAddQuery
- type EventPoolNodeFailure
- type EventPoolNodeResponse
- type EventPoolPoll
- type EventPoolStopQuery
- type EventQueryCancel
- type EventQueryNodeFailure
- type EventQueryNodeResponse
- type EventQueryPoll
- type NodeIter
- type NodeState
- type NodeStatus
- type Pool
- type PoolConfig
- type PoolEvent
- type PoolState
- type Query
- func NewFindCloserQuery[K kad.Key[K], N kad.NodeID[K], M coordt.Message[K, N]](self N, id coordt.QueryID, target K, iter NodeIter[K, N], ...) (*Query[K, N, M], error)
- func NewQuery[K kad.Key[K], N kad.NodeID[K], M coordt.Message[K, N]](self N, id coordt.QueryID, target K, msg M, iter NodeIter[K, N], ...) (*Query[K, N, M], error)
- type QueryConfig
- type QueryEvent
- type QueryState
- type QueryStats
- type SequentialIter
- type StateNodeFailed
- type StateNodeNotContacted
- type StateNodeSucceeded
- type StateNodeUnresponsive
- type StateNodeWaiting
- type StatePoolFindCloser
- type StatePoolIdle
- type StatePoolQueryFinished
- type StatePoolQueryTimeout
- type StatePoolSendMessage
- type StatePoolWaitingAtCapacity
- type StatePoolWaitingWithCapacity
- type StateQueryFindCloser
- type StateQueryFinished
- type StateQuerySendMessage
- type StateQueryWaitingAtCapacity
- type StateQueryWaitingWithCapacity
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ClosestNodesIter ¶
type ClosestNodesIter[K kad.Key[K], N kad.NodeID[K]] struct { // contains filtered or unexported fields }
A ClosestNodesIter iterates nodes in order of ascending distance from a key.
func NewClosestNodesIter ¶
func NewClosestNodesIter[K kad.Key[K], N kad.NodeID[K]](target K) *ClosestNodesIter[K, N]
NewClosestNodesIter creates a new ClosestNodesIter
func (*ClosestNodesIter[K, N]) Add ¶
func (iter *ClosestNodesIter[K, N]) Add(ni *NodeStatus[K, N])
func (*ClosestNodesIter[K, N]) Each ¶
func (iter *ClosestNodesIter[K, N]) Each(ctx context.Context, fn func(context.Context, *NodeStatus[K, N]) bool) bool
func (*ClosestNodesIter[K, N]) Find ¶
func (iter *ClosestNodesIter[K, N]) Find(k K) (*NodeStatus[K, N], bool)
type EventPoolAddFindCloserQuery ¶
type EventPoolAddFindCloserQuery[K kad.Key[K], N kad.NodeID[K]] struct { QueryID coordt.QueryID // the id to use for the new query Target K // the target key for the query Seed []N // an initial set of close nodes the query should use NumResults int // the minimum number of nodes to successfully contact before considering iteration complete }
EventPoolAddQuery is an event that attempts to add a new query that finds closer nodes to a target key.
type EventPoolAddQuery ¶
type EventPoolAddQuery[K kad.Key[K], N kad.NodeID[K], M coordt.Message[K, N]] struct { QueryID coordt.QueryID // the id to use for the new query Target K // the target key for the query Message M // message to be sent to each node Seed []N // an initial set of close nodes the query should use NumResults int // the minimum number of nodes to successfully contact before considering iteration complete }
EventPoolAddQuery is an event that attempts to add a new query that sends a message.
type EventPoolNodeFailure ¶
type EventPoolNodeFailure[K kad.Key[K], N kad.NodeID[K]] struct { QueryID coordt.QueryID // the id of the query that sent the message NodeID N // the node the message was sent to Error error // the error that caused the failure, if any }
EventPoolNodeFailure notifies a Pool that an attempt to contact a node has failed.
type EventPoolNodeResponse ¶
type EventPoolNodeResponse[K kad.Key[K], N kad.NodeID[K]] struct { QueryID coordt.QueryID // the id of the query that sent the message NodeID N // the node the message was sent to CloserNodes []N // the closer nodes sent by the node }
EventPoolNodeResponse notifies a Pool that an attempt to contact a node has received a successful response.
type EventPoolPoll ¶
type EventPoolPoll struct{}
EventPoolPoll is an event that signals the pool that it can perform housekeeping work such as time out queries.
type EventPoolStopQuery ¶
type EventPoolStopQuery struct {
QueryID coordt.QueryID // the id of the query that should be stopped
}
EventPoolStopQuery notifies a Pool to stop a query.
type EventQueryCancel ¶
type EventQueryCancel struct{}
EventQueryMessageResponse notifies a query to stop all work and enter the finished state.
type EventQueryNodeFailure ¶
type EventQueryNodeFailure[K kad.Key[K], N kad.NodeID[K]] struct { NodeID N // the node the message was sent to Error error // the error that caused the failure, if any }
EventQueryNodeFailure notifies a Query that an attempt to to contact a node has failed.
type EventQueryNodeResponse ¶
type EventQueryNodeResponse[K kad.Key[K], N kad.NodeID[K]] struct { NodeID N // the node the message was sent to CloserNodes []N // the closer nodes sent by the node }
EventQueryNodeResponse notifies a Query that an attempt to contact a node has received a successful response.
type EventQueryPoll ¶
type EventQueryPoll struct{}
EventQueryPoll is an event that signals a Query that it can perform housekeeping work.
type NodeIter ¶
type NodeIter[K kad.Key[K], N kad.NodeID[K]] interface { // Add adds node information to the iterator Add(*NodeStatus[K, N]) // Find returns the node information corresponding to the given Kademlia key Find(K) (*NodeStatus[K, N], bool) // Each applies fn to each entry in the iterator in order. Each stops and returns true if fn returns true. // Otherwise, Each returns false when there are no further entries. Each(ctx context.Context, fn func(context.Context, *NodeStatus[K, N]) bool) bool }
A NodeIter iterates nodes according to some strategy.
type NodeStatus ¶
type Pool ¶
type Pool[K kad.Key[K], N kad.NodeID[K], M coordt.Message[K, N]] struct { // contains filtered or unexported fields }
type PoolConfig ¶
type PoolConfig struct {
Concurrency int // the maximum number of queries that may be waiting for message responses at any one time
Timeout time.Duration // the time to wait before terminating a query that is not making progress
Replication int // the 'k' parameter defined by Kademlia
QueryConcurrency int // the maximum number of concurrent requests that each query may have in flight
RequestTimeout time.Duration // the timeout queries should use for contacting a single node
// Tracer is the tracer that should be used to trace execution.
Tracer trace.Tracer
}
PoolConfig specifies optional configuration for a Pool
func DefaultPoolConfig ¶
func DefaultPoolConfig() *PoolConfig
DefaultPoolConfig returns the default configuration options for a Pool. Options may be overridden before passing to NewPool
func (*PoolConfig) Validate ¶
func (cfg *PoolConfig) Validate() error
Validate checks the configuration options and returns an error if any have invalid values.
type PoolEvent ¶
type PoolEvent interface {
// contains filtered or unexported methods
}
PoolEvent is an event intended to advance the state of a pool.
type Query ¶
type Query[K kad.Key[K], N kad.NodeID[K], M coordt.Message[K, N]] struct { // contains filtered or unexported fields }
A Query is one iterative Kademlia lookup.
It contacts nodes in ascending order of distance from a target key. Each response supplies further nodes, so the query walks towards the target until the closest nodes it knows of stop improving. The ordering is decided by the NodeIter the query is given rather than by the query itself.
A query either asks each node for the nodes it holds closest to the target, emitting StateQueryFindCloser, or sends each node a message and takes the closer nodes from the reply, emitting StateQuerySendMessage. NewFindCloserQuery creates the first kind and NewQuery the second.
Every advance walks the whole iterator and returns at the first thing it can do, so one advance produces at most one request. Along the way it marks any node whose request deadline has passed as unresponsive, which frees a concurrency slot. The first node that has not been contacted is then sent a request if a slot is free, and that instruction is what the advance returns. The walk stops early if every slot is already in use.
The query is finished when, walking outward, it reaches a node that responded successfully having already counted QueryConfig.NumResults successes with no request outstanding nearer the target; or when the walk reaches the end with nothing in flight and nothing left to contact; or when it is cancelled by EventQueryCancel. Finishing is sticky, since the finished flag is tested before the event, so every later advance returns the same StateQueryFinished carrying the same nodes.
Two deadlines apply and the query treats them differently. QueryConfig.RequestTimeout bounds a single request and the query enforces it itself by marking the node unresponsive. QueryConfig.Timeout bounds the whole query, is set when the first node is contacted, and is only reported: the query keeps running past it and the caller decides what running out of time means.
The node the query is running on is excluded throughout, both from the seed set and from the closer nodes carried by any response.
func NewFindCloserQuery ¶
func NewFindCloserQuery[K kad.Key[K], N kad.NodeID[K], M coordt.Message[K, N]](self N, id coordt.QueryID, target K, iter NodeIter[K, N], knownClosestNodes []N, cfg *QueryConfig) (*Query[K, N, M], error)
NewFindCloserQuery creates a query that asks each node it contacts for the nodes that node holds closest to target, and takes those as the nodes to contact next. It sends no message of its own, so the message type parameter goes unused, and it reports the node it wants contacted by emitting StateQueryFindCloser.
The query is seeded with knownClosestNodes, from which self is excluded, and orders every node it learns of using iter. It reports its progress under the query id id. A nil cfg uses DefaultQueryConfig, and a non-nil one is validated.
func NewQuery ¶
func NewQuery[K kad.Key[K], N kad.NodeID[K], M coordt.Message[K, N]](self N, id coordt.QueryID, target K, msg M, iter NodeIter[K, N], knownClosestNodes []N, cfg *QueryConfig) (*Query[K, N, M], error)
NewQuery creates a query that sends msg to each node it contacts and takes the nodes closer to target from each reply, so the reply serves both as the answer to the message and as the source of the next nodes to walk to. It reports the node it wants contacted by emitting StateQuerySendMessage.
The query is seeded with knownClosestNodes, from which self is excluded, and orders every node it learns of using iter. It reports its progress under the query id id. A nil cfg uses DefaultQueryConfig, and a non-nil one is validated.
func (*Query[K, N, M]) Advance ¶
func (q *Query[K, N, M]) Advance(ctx context.Context, now time.Time, ev QueryEvent) (out QueryState)
type QueryConfig ¶
type QueryConfig struct {
Concurrency int // the maximum number of concurrent requests that may be in flight
NumResults int // the minimum number of nodes to successfully contact before considering iteration complete
RequestTimeout time.Duration // the timeout for contacting a single node
Timeout time.Duration // the time to wait before the query is considered to have stopped making progress
// Tracer is the tracer that should be used to trace execution.
Tracer trace.Tracer
}
QueryConfig specifies optional configuration for a Query
func DefaultQueryConfig ¶
func DefaultQueryConfig() *QueryConfig
DefaultQueryConfig returns the default configuration options for a Query. Options may be overridden before passing to NewQuery
func (*QueryConfig) Validate ¶
func (cfg *QueryConfig) Validate() error
Validate checks the configuration options and returns an error if any have invalid values.
type QueryEvent ¶
type QueryEvent interface {
// contains filtered or unexported methods
}
type QueryState ¶
type QueryState interface {
// contains filtered or unexported methods
}
type QueryStats ¶
type QueryStats struct {
Start time.Time // the time the first request was dispatched, zero until then
End time.Time // the time the query finished, zero until then
Requests int // the number of requests dispatched
Success int // the number of requests answered within their deadline
Failure int // the number of requests that errored or passed their deadline
}
QueryStats holds the counts and timings a Query accumulates as it runs. A query reports them with every state it emits.
The counters track requests rather than nodes, and each request that has completed counts once, so Success and Failure together never exceed Requests.
type SequentialIter ¶
type SequentialIter[K kad.Key[K], N kad.NodeID[K]] struct { // contains filtered or unexported fields }
A SequentialIter iterates nodes in the order they were added to the iterator.
func NewSequentialIter ¶
func NewSequentialIter[K kad.Key[K], N kad.NodeID[K]]() *SequentialIter[K, N]
NewSequentialIter creates a new SequentialIter
func (*SequentialIter[K, N]) Add ¶
func (iter *SequentialIter[K, N]) Add(ni *NodeStatus[K, N])
func (*SequentialIter[K, N]) Each ¶
func (iter *SequentialIter[K, N]) Each(ctx context.Context, fn func(context.Context, *NodeStatus[K, N]) bool) bool
func (*SequentialIter[K, N]) Find ¶
func (iter *SequentialIter[K, N]) Find(k K) (*NodeStatus[K, N], bool)
Find returns the node information corresponding to the given Kademlia key. It uses a linear search which makes it unsuitable for large numbers of entries.
type StateNodeFailed ¶
type StateNodeFailed struct{}
StateNodeFailed indicates that the attempt to contact the node failed.
type StateNodeNotContacted ¶
type StateNodeNotContacted struct{}
StateNodeNotContacted indicates that the node has not been contacted yet.
type StateNodeSucceeded ¶
type StateNodeSucceeded struct{}
StateNodeSucceeded indicates that the attempt to contact the node succeeded.
type StateNodeUnresponsive ¶
type StateNodeUnresponsive struct{}
StateNodeUnresponsive indicates that the node did not respond within the configured timeout.
type StateNodeWaiting ¶
StateNodeWaiting indicates that a query is waiting for a response from the node.
type StatePoolFindCloser ¶
type StatePoolFindCloser[K kad.Key[K], N kad.NodeID[K]] struct { QueryID coordt.QueryID Target K // the key that the query wants to find closer nodes for NodeID N // the node to send the message to Stats QueryStats }
StatePoolFindCloser indicates that a pool query wants to send a find closer nodes message to a node.
type StatePoolIdle ¶
type StatePoolIdle struct {
NextDue time.Time // the earliest time advancing the pool could make progress, zero if there is none
}
StatePoolIdle indicates that the pool is idle, i.e. there are no queries to process.
type StatePoolQueryFinished ¶
type StatePoolQueryFinished[K kad.Key[K], N kad.NodeID[K]] struct { QueryID coordt.QueryID Stats QueryStats Target K // the key the query was looking for the closest nodes to ClosestNodes []N }
StatePoolQueryFinished indicates that a query has finished.
type StatePoolQueryTimeout ¶
type StatePoolQueryTimeout struct {
QueryID coordt.QueryID
Stats QueryStats
}
StatePoolQueryTimeout indicates that a query has timed out.
type StatePoolSendMessage ¶
type StatePoolSendMessage[K kad.Key[K], N kad.NodeID[K], M coordt.Message[K, N]] struct { QueryID coordt.QueryID NodeID N // the node to send the message to Message M Stats QueryStats }
StatePoolSendMessage indicates that a pool query wants to send a message to a node.
type StatePoolWaitingAtCapacity ¶
type StatePoolWaitingAtCapacity struct {
NextDue time.Time // the earliest time advancing the pool could make progress, zero if there is none
}
StatePoolWaitingAtCapacity indicates that at least one query is waiting for results and the pool has reached its maximum number of concurrent queries.
type StatePoolWaitingWithCapacity ¶
type StatePoolWaitingWithCapacity struct {
NextDue time.Time // the earliest time advancing the pool could make progress, zero if there is none
}
StatePoolWaitingWithCapacity indicates that at least one query is waiting for results but capacity to start more is available.
type StateQueryFindCloser ¶
type StateQueryFindCloser[K kad.Key[K], N kad.NodeID[K]] struct { QueryID coordt.QueryID Target K // the key that the query wants to find closer nodes for NodeID N // the node to send the message to Stats QueryStats }
StateQueryFindCloser indicates that the Query wants to send a find closer nodes message to a node.
type StateQueryFinished ¶
type StateQueryFinished[K kad.Key[K], N kad.NodeID[K]] struct { QueryID coordt.QueryID Stats QueryStats Target K // the key the query was looking for the closest nodes to ClosestNodes []N // contains the closest nodes to the target key that were found }
StateQueryFinished indicates that the Query has finished.
type StateQuerySendMessage ¶
type StateQuerySendMessage[K kad.Key[K], N kad.NodeID[K], M coordt.Message[K, N]] struct { QueryID coordt.QueryID NodeID N // the node to send the message to Message M Stats QueryStats }
StateQuerySendMessage indicates that the Query wants to send a message to a node.
type StateQueryWaitingAtCapacity ¶
type StateQueryWaitingAtCapacity struct {
QueryID coordt.QueryID
Stats QueryStats
Deadline time.Time // the time by which the query must have completed
NextDue time.Time // the earliest time advancing the query could make progress, zero if there is none
}
StateQueryWaitingAtCapacity indicates that the Query is waiting for results and is at capacity.
type StateQueryWaitingWithCapacity ¶
type StateQueryWaitingWithCapacity struct {
QueryID coordt.QueryID
Stats QueryStats
Deadline time.Time // the time by which the query must have completed
NextDue time.Time // the earliest time advancing the query could make progress, zero if there is none
}
StateQueryWaitingWithCapacity indicates that the Query is waiting for results but has no further nodes to contact.