mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 18:37:45 +08:00
* Delegated Routing. Implementation of Reframe specs (https://github.com/ipfs/specs/blob/master/REFRAME.md) using go-delegated-routing library. * Requested changes. * Init using op string * Separate possible ContentRouters for TopicDiscovery. If we don't do this, we have a ciclic dependency creating TieredRouter. Now we can create first all possible content routers, and after that, create Routers. * Set dht default routing type * Add tests and remove uneeded code * Add documentation. * docs: Routing.Routers * Requested changes. Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com> * Add some documentation on new fx functions. * Add changelog entry and integration tests * test: sharness for 'dht' in 'routing' commands Since 'routing' is currently the same as 'dht' (minus query command) we need to test both, that way we won't have unnoticed divergence in the default behavior. * test(sharness): delegated routing via reframe URL * Add more tests for delegated routing. * If any put operation fails, the tiered router will fail. * refactor: Routing.Routers: Parameters.Endpoint As agreed in https://github.com/ipfs/kubo/pull/8997#issuecomment-1175684716 * Try to improve CHANGELOG entry. * chore: update reframe spec link * Update go-delegated-routing dependency * Fix config error test * use new changelog format * Remove port conflict * go mod tidy * ProviderManyWrapper to ProviderMany * Update docs/changelogs/v0.14.md Co-authored-by: Adin Schmahmann <adin.schmahmann@gmail.com> Co-authored-by: Marcin Rataj <lidel@lidel.org> Co-authored-by: Adin Schmahmann <adin.schmahmann@gmail.com>
177 lines
5.0 KiB
Go
177 lines
5.0 KiB
Go
package node
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/ipfs/go-fetcher"
|
|
pin "github.com/ipfs/go-ipfs-pinner"
|
|
provider "github.com/ipfs/go-ipfs-provider"
|
|
"github.com/ipfs/go-ipfs-provider/batched"
|
|
q "github.com/ipfs/go-ipfs-provider/queue"
|
|
"github.com/ipfs/go-ipfs-provider/simple"
|
|
"go.uber.org/fx"
|
|
|
|
"github.com/ipfs/kubo/core/node/helpers"
|
|
"github.com/ipfs/kubo/repo"
|
|
irouting "github.com/ipfs/kubo/routing"
|
|
)
|
|
|
|
const kReprovideFrequency = time.Hour * 12
|
|
|
|
// SIMPLE
|
|
|
|
// ProviderQueue creates new datastore backed provider queue
|
|
func ProviderQueue(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo) (*q.Queue, error) {
|
|
return q.NewQueue(helpers.LifecycleCtx(mctx, lc), "provider-v1", repo.Datastore())
|
|
}
|
|
|
|
// SimpleProvider creates new record provider
|
|
func SimpleProvider(mctx helpers.MetricsCtx, lc fx.Lifecycle, queue *q.Queue, rt irouting.TieredRouter) provider.Provider {
|
|
return simple.NewProvider(helpers.LifecycleCtx(mctx, lc), queue, rt)
|
|
}
|
|
|
|
// SimpleReprovider creates new reprovider
|
|
func SimpleReprovider(reproviderInterval time.Duration) interface{} {
|
|
return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, rt irouting.TieredRouter, keyProvider simple.KeyChanFunc) (provider.Reprovider, error) {
|
|
return simple.NewReprovider(helpers.LifecycleCtx(mctx, lc), reproviderInterval, rt, keyProvider), nil
|
|
}
|
|
}
|
|
|
|
// SimpleProviderSys creates new provider system
|
|
func SimpleProviderSys(isOnline bool) interface{} {
|
|
return func(lc fx.Lifecycle, p provider.Provider, r provider.Reprovider) provider.System {
|
|
sys := provider.NewSystem(p, r)
|
|
|
|
if isOnline {
|
|
lc.Append(fx.Hook{
|
|
OnStart: func(ctx context.Context) error {
|
|
sys.Run()
|
|
return nil
|
|
},
|
|
OnStop: func(ctx context.Context) error {
|
|
return sys.Close()
|
|
},
|
|
})
|
|
}
|
|
|
|
return sys
|
|
}
|
|
}
|
|
|
|
// BatchedProviderSys creates new provider system
|
|
func BatchedProviderSys(isOnline bool, reprovideInterval string) interface{} {
|
|
return func(lc fx.Lifecycle, cr irouting.TieredRouter, q *q.Queue, keyProvider simple.KeyChanFunc, repo repo.Repo) (provider.System, error) {
|
|
r := cr.ProvideMany()
|
|
if r == nil {
|
|
return nil, fmt.Errorf("BatchedProviderSys requires a content router that supports provideMany")
|
|
}
|
|
|
|
reprovideIntervalDuration := kReprovideFrequency
|
|
if reprovideInterval != "" {
|
|
dur, err := time.ParseDuration(reprovideInterval)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
reprovideIntervalDuration = dur
|
|
}
|
|
|
|
sys, err := batched.New(r, q,
|
|
batched.ReproviderInterval(reprovideIntervalDuration),
|
|
batched.Datastore(repo.Datastore()),
|
|
batched.KeyProvider(keyProvider))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if isOnline {
|
|
lc.Append(fx.Hook{
|
|
OnStart: func(ctx context.Context) error {
|
|
sys.Run()
|
|
return nil
|
|
},
|
|
OnStop: func(ctx context.Context) error {
|
|
return sys.Close()
|
|
},
|
|
})
|
|
}
|
|
|
|
return sys, nil
|
|
}
|
|
}
|
|
|
|
// ONLINE/OFFLINE
|
|
|
|
// OnlineProviders groups units managing provider routing records online
|
|
func OnlineProviders(useStrategicProviding bool, useBatchedProviding bool, reprovideStrategy string, reprovideInterval string) fx.Option {
|
|
if useStrategicProviding {
|
|
return fx.Provide(provider.NewOfflineProvider)
|
|
}
|
|
|
|
return fx.Options(
|
|
SimpleProviders(reprovideStrategy, reprovideInterval),
|
|
maybeProvide(SimpleProviderSys(true), !useBatchedProviding),
|
|
maybeProvide(BatchedProviderSys(true, reprovideInterval), useBatchedProviding),
|
|
)
|
|
}
|
|
|
|
// OfflineProviders groups units managing provider routing records offline
|
|
func OfflineProviders(useStrategicProviding bool, useBatchedProviding bool, reprovideStrategy string, reprovideInterval string) fx.Option {
|
|
if useStrategicProviding {
|
|
return fx.Provide(provider.NewOfflineProvider)
|
|
}
|
|
|
|
return fx.Options(
|
|
SimpleProviders(reprovideStrategy, reprovideInterval),
|
|
maybeProvide(SimpleProviderSys(false), true),
|
|
//maybeProvide(BatchedProviderSys(false, reprovideInterval), useBatchedProviding),
|
|
)
|
|
}
|
|
|
|
// SimpleProviders creates the simple provider/reprovider dependencies
|
|
func SimpleProviders(reprovideStrategy string, reprovideInterval string) fx.Option {
|
|
reproviderInterval := kReprovideFrequency
|
|
if reprovideInterval != "" {
|
|
dur, err := time.ParseDuration(reprovideInterval)
|
|
if err != nil {
|
|
return fx.Error(err)
|
|
}
|
|
|
|
reproviderInterval = dur
|
|
}
|
|
|
|
var keyProvider fx.Option
|
|
switch reprovideStrategy {
|
|
case "all":
|
|
fallthrough
|
|
case "":
|
|
keyProvider = fx.Provide(simple.NewBlockstoreProvider)
|
|
case "roots":
|
|
keyProvider = fx.Provide(pinnedProviderStrategy(true))
|
|
case "pinned":
|
|
keyProvider = fx.Provide(pinnedProviderStrategy(false))
|
|
default:
|
|
return fx.Error(fmt.Errorf("unknown reprovider strategy '%s'", reprovideStrategy))
|
|
}
|
|
|
|
return fx.Options(
|
|
fx.Provide(ProviderQueue),
|
|
fx.Provide(SimpleProvider),
|
|
keyProvider,
|
|
fx.Provide(SimpleReprovider(reproviderInterval)),
|
|
)
|
|
}
|
|
|
|
func pinnedProviderStrategy(onlyRoots bool) interface{} {
|
|
type input struct {
|
|
fx.In
|
|
Pinner pin.Pinner
|
|
IPLDFetcher fetcher.Factory `name:"ipldFetcher"`
|
|
}
|
|
return func(in input) simple.KeyChanFunc {
|
|
return simple.NewPinnedProvider(onlyRoots, in.Pinner, in.IPLDFetcher)
|
|
}
|
|
}
|