Skip to content

Commit

Permalink
Option for double-hashed lookups to return only metadata
Browse files Browse the repository at this point in the history
Supports use cases where provider address information is not needed.

Fixes #122
  • Loading branch information
gammazero committed Sep 22, 2023
1 parent 3bc33f6 commit 1bf84e6
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 21 deletions.
48 changes: 37 additions & 11 deletions find/client/dhash_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/ipni/go-libipni/dhash"
"github.com/ipni/go-libipni/find/model"
"github.com/ipni/go-libipni/pcache"
"github.com/libp2p/go-libp2p/core/peer"
b58 "github.com/mr-tron/base58/base58"
"github.com/multiformats/go-multihash"
)
Expand Down Expand Up @@ -52,17 +53,20 @@ func NewDHashClient(options ...Option) (*DHashClient, error) {
return nil, err
}

if len(opts.providersURLs) == 0 {
if opts.dhstoreURL == "" {
return nil, errors.New("no source of provider information")
var pc *pcache.ProviderCache
if !opts.metadataOnly {
if len(opts.providersURLs) == 0 {
if opts.dhstoreURL == "" {
return nil, errors.New("no source of provider information")
}
opts.providersURLs = []string{opts.dhstoreURL}
}
opts.providersURLs = []string{opts.dhstoreURL}
}

pc, err := pcache.New(pcache.WithTTL(opts.pcacheTTL), pcache.WithPreload(opts.preload),
pcache.WithSourceURL(opts.providersURLs...))
if err != nil {
return nil, err
pc, err = pcache.New(pcache.WithTTL(opts.pcacheTTL), pcache.WithPreload(opts.preload),
pcache.WithSourceURL(opts.providersURLs...))
if err != nil {
return nil, err
}
}

var dhsAPI DHStoreAPI
Expand All @@ -71,6 +75,9 @@ func NewDHashClient(options ...Option) (*DHashClient, error) {
} else {
var dhsURL *url.URL
if opts.dhstoreURL == "" {
if len(opts.providersURLs) == 0 {
return nil, errors.New("no destination for metadata lookup")
}
opts.dhstoreURL = opts.providersURLs[0]
}
dhsURL, err = url.Parse(opts.dhstoreURL)
Expand Down Expand Up @@ -148,7 +155,7 @@ func (c *DHashClient) FindAsync(ctx context.Context, mh multihash.Multihash, res
continue
}

pid, ctxId, err := dhash.SplitValueKey(vk)
pid, ctxID, err := dhash.SplitValueKey(vk)
if err != nil {
log.Warnw("Error splitting value key", "multihash", mh.B58String(), "evk", b58.Encode(evk), "err", err)
continue
Expand All @@ -167,7 +174,26 @@ func (c *DHashClient) FindAsync(ctx context.Context, mh multihash.Multihash, res
continue
}

prs, err := c.pcache.GetResults(ctx, pid, ctxId, metadata)
// If only fetching metadata. The provider ID is still needed in
// order to identify which provider the metadata is associated
// with.
if c.pcache == nil {
pr := model.ProviderResult{
ContextID: ctxID,
Metadata: metadata,
Provider: &peer.AddrInfo{
ID: pid,
},
}
select {
case resChan <- pr:
case <-ctx.Done():
return ctx.Err()
}
continue
}

prs, err := c.pcache.GetResults(ctx, pid, ctxID, metadata)
if err != nil {
log.Warnw("Error fetching provider infos", "multihash", mh.B58String(), "evk", b58.Encode(evk), "err", err)
continue
Expand Down
21 changes: 19 additions & 2 deletions find/client/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type config struct {
providersURLs []string
dhstoreURL string
dhstoreAPI DHStoreAPI
metadataOnly bool
pcacheTTL time.Duration
preload bool
}
Expand Down Expand Up @@ -48,9 +49,22 @@ func WithClient(c *http.Client) Option {
}
}

// WithMetadataOnly configures lookups to only return metadata and not provider
// information. This means that is it is not necessary to specify providers
// URLs, using WithProvidersURL, when provider information is available from a
// separate location.
func WithMetadataOnly(metadataOnly bool) Option {
return func(cfg *config) error {
cfg.metadataOnly = metadataOnly
return nil
}
}

// WithProvidersURL specifies one or more URLs for retrieving provider
// information (/providers and /providers/<pid> endpoints). Multiple URLs may
// be given to specify multiple sources of provider information,
// be given to specify multiple sources of provider information.
//
// This option is ignored if WithMetadataOnly(true) is specified.
func WithProvidersURL(urls ...string) Option {
return func(cfg *config) error {
cfg.providersURLs = append(cfg.providersURLs, urls...)
Expand Down Expand Up @@ -80,6 +94,8 @@ func WithDHStoreAPI(dhsAPI DHStoreAPI) Option {

// WithPcacheTTL sets the time that provider information remains in the cache
// after it is not longer available from any of the original sources.
//
// This option is ignored if WithMetadataOnly(true) is specified.
func WithPcacheTTL(ttl time.Duration) Option {
return func(cfg *config) error {
cfg.pcacheTTL = ttl
Expand All @@ -91,7 +107,8 @@ func WithPcacheTTL(ttl time.Duration) Option {
// should be enabled, even for short-lived clients needing to look up few
// providers.
//
// Default is true (enabled).
// Default is true (enabled). This option is ignored if WithMetadataOnly(true)
// is specified.
func WithPcachePreload(preload bool) Option {
return func(cfg *config) error {
cfg.preload = preload
Expand Down
17 changes: 9 additions & 8 deletions pcache/provider_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var log = logging.Logger("pcache")
var ErrClosed = errors.New("cache closed")

// ProviderSource in an interface that the cache uses to fetch provider
// information for one or all providers from a specific supplier of that
// information. Each ProviderSource is a specific supplier of provider
// information. The cache can be configured with any number of sources that
// supply provider information.
type ProviderSource interface {
Expand Down Expand Up @@ -153,10 +153,11 @@ func (pc *ProviderCache) List() []*model.ProviderInfo {
return pinfos
}

// GetResults retrieves information about the provicer specified by pid and
// composes a slice ProviderResults got the provider. If provider information
// is not available, then a nil slice is returned. An error results from the
// context being canceled or the cache closing.
// GetResults retrieves information about the provider specified by peer ID and
// composes a slice of ProviderResults for the provider and any extended
// providers. If provider information is not available, then a nil slice is
// returned. An error results from the context being canceled or the cache
// closing.
func (pc *ProviderCache) GetResults(ctx context.Context, pid peer.ID, ctxID, metadata []byte) ([]model.ProviderResult, error) {
rpi, err := pc.getReadOnly(ctx, pid)
if err != nil {
Expand Down Expand Up @@ -190,7 +191,7 @@ func (pc *ProviderCache) GetResults(ctx context.Context, pid peer.ID, ctxID, met
override = ctxExtended.override
for i, xpinfo := range ctxExtended.providers {
xmd := ctxExtended.metadatas[i]
// Skippng the main provider's record if its metadata is nil or is
// Skipping the main provider's record if its metadata is nil or is
// the same as the one retrieved from the indexer, because such EP
// record does not advertise any new protocol.
if xpinfo.ID == pid && (len(xmd) == 0 || bytes.Equal(xmd, metadata)) {
Expand Down Expand Up @@ -219,7 +220,7 @@ func (pc *ProviderCache) GetResults(ctx context.Context, pid peer.ID, ctxID, met
extended := rpi.provider.ExtendedProviders
for i, xpinfo := range extended.Providers {
xmd := extended.Metadatas[i]
// Skippng the main provider's record if its metadata is nil or is the
// Skipping the main provider's record if its metadata is nil or is the
// same as the one retrieved from the indexer, because such EP record
// does not advertise any new protocol.
if xpinfo.ID == pid && (len(xmd) == 0 || bytes.Equal(xmd, metadata)) {
Expand Down Expand Up @@ -362,7 +363,7 @@ func (pc *ProviderCache) Refresh(ctx context.Context) error {
return nil
}

// get returns the provider information for the provider specified by pid. If
// get returns the provider information for the provider specified by id. If
// provider information is not available, then a nil slice is returned. An
// error results from the context being canceled or the cache closing.
//
Expand Down

0 comments on commit 1bf84e6

Please sign in to comment.