kubo/core/node/libp2p/routingopt.go
Gus Eggert a09c8df24d
fix: remove timeout on default DHT operations (#9783)
* fix: remove timeout on default DHT operations

This removes the timeout by default for DHT operations. In particular
this causes issues with ProvideMany requests which can take an
indeterminate amount of time, but really these should just respect
context timeouts by default. Users can still specify timeouts here if
they want, but by default they will be set to "0" which means "no
timeout".

This is unlikely to break existing users of custom routing, because
there was previously no utility in configuring a router with timeout=0
because that would cause the router to immediately fail, so it is
unlikely (and incorrect) if anybody was using timeout=0.

* fix: remove 5m timeout on ProvideManyRouter

For context see
5fda291b66

---------

Co-authored-by: Marcin Rataj <lidel@lidel.org>
2023-03-30 16:08:43 -04:00

173 lines
5.0 KiB
Go

package libp2p
import (
"context"
"os"
"strings"
"time"
"github.com/ipfs/go-datastore"
"github.com/ipfs/kubo/config"
irouting "github.com/ipfs/kubo/routing"
dht "github.com/libp2p/go-libp2p-kad-dht"
dual "github.com/libp2p/go-libp2p-kad-dht/dual"
record "github.com/libp2p/go-libp2p-record"
routinghelpers "github.com/libp2p/go-libp2p-routing-helpers"
host "github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
routing "github.com/libp2p/go-libp2p/core/routing"
)
type RoutingOption func(
context.Context,
host.Host,
datastore.Batching,
record.Validator,
...peer.AddrInfo,
) (routing.Routing, error)
// Default HTTP routers used in parallel to DHT when Routing.Type = "auto"
var defaultHTTPRouters = []string{
"https://cid.contact", // https://github.com/ipfs/kubo/issues/9422#issuecomment-1338142084
// TODO: add an independent router from Cloudflare
}
func init() {
// Override HTTP routers if custom ones were passed via env
if routers := os.Getenv("IPFS_HTTP_ROUTERS"); routers != "" {
defaultHTTPRouters = strings.Split(routers, " ")
}
}
// ConstructDefaultRouting returns routers used when Routing.Type is unset or set to "auto"
func ConstructDefaultRouting(peerID string, addrs []string, privKey string, routingOpt RoutingOption) func(
ctx context.Context,
host host.Host,
dstore datastore.Batching,
validator record.Validator,
bootstrapPeers ...peer.AddrInfo,
) (routing.Routing, error) {
return func(
ctx context.Context,
host host.Host,
dstore datastore.Batching,
validator record.Validator,
bootstrapPeers ...peer.AddrInfo,
) (routing.Routing, error) {
// Defined routers will be queried in parallel (optimizing for response speed)
// Different trade-offs can be made by setting Routing.Type = "custom" with own Routing.Routers
var routers []*routinghelpers.ParallelRouter
dhtRouting, err := routingOpt(ctx, host, dstore, validator, bootstrapPeers...)
if err != nil {
return nil, err
}
routers = append(routers, &routinghelpers.ParallelRouter{
Router: dhtRouting,
IgnoreError: false,
ExecuteAfter: 0,
})
// Append HTTP routers for additional speed
for _, endpoint := range defaultHTTPRouters {
httpRouter, err := irouting.ConstructHTTPRouter(endpoint, peerID, addrs, privKey)
if err != nil {
return nil, err
}
r := &irouting.Composer{
GetValueRouter: routinghelpers.Null{},
PutValueRouter: routinghelpers.Null{},
ProvideRouter: routinghelpers.Null{}, // modify this when indexers supports provide
FindPeersRouter: routinghelpers.Null{},
FindProvidersRouter: httpRouter,
}
routers = append(routers, &routinghelpers.ParallelRouter{
Router: r,
IgnoreError: true, // https://github.com/ipfs/kubo/pull/9475#discussion_r1042507387
Timeout: 15 * time.Second, // 5x server value from https://github.com/ipfs/kubo/pull/9475#discussion_r1042428529
ExecuteAfter: 0,
})
}
routing := routinghelpers.NewComposableParallel(routers)
return routing, nil
}
}
// constructDHTRouting is used when Routing.Type = "dht"
func constructDHTRouting(mode dht.ModeOpt) func(
ctx context.Context,
host host.Host,
dstore datastore.Batching,
validator record.Validator,
bootstrapPeers ...peer.AddrInfo,
) (routing.Routing, error) {
return func(
ctx context.Context,
host host.Host,
dstore datastore.Batching,
validator record.Validator,
bootstrapPeers ...peer.AddrInfo,
) (routing.Routing, error) {
return dual.New(
ctx, host,
dual.DHTOption(
dht.Concurrency(10),
dht.Mode(mode),
dht.Datastore(dstore),
dht.Validator(validator)),
dual.WanDHTOption(dht.BootstrapPeers(bootstrapPeers...)),
)
}
}
// ConstructDelegatedRouting is used when Routing.Type = "custom"
func ConstructDelegatedRouting(routers config.Routers, methods config.Methods, peerID string, addrs []string, privKey string) func(
ctx context.Context,
host host.Host,
dstore datastore.Batching,
validator record.Validator,
bootstrapPeers ...peer.AddrInfo,
) (routing.Routing, error) {
return func(
ctx context.Context,
host host.Host,
dstore datastore.Batching,
validator record.Validator,
bootstrapPeers ...peer.AddrInfo,
) (routing.Routing, error) {
return irouting.Parse(routers, methods,
&irouting.ExtraDHTParams{
BootstrapPeers: bootstrapPeers,
Host: host,
Validator: validator,
Datastore: dstore,
Context: ctx,
},
&irouting.ExtraHTTPParams{
PeerID: peerID,
Addrs: addrs,
PrivKeyB64: privKey,
})
}
}
func constructNilRouting(
ctx context.Context,
host host.Host,
dstore datastore.Batching,
validator record.Validator,
bootstrapPeers ...peer.AddrInfo,
) (routing.Routing, error) {
return routinghelpers.Null{}, nil
}
var (
DHTOption RoutingOption = constructDHTRouting(dht.ModeAuto)
DHTClientOption = constructDHTRouting(dht.ModeClient)
DHTServerOption = constructDHTRouting(dht.ModeServer)
NilRouterOption = constructNilRouting
)