retrieval

package
v0.35.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2025 License: Apache-2.0, MIT Imports: 9 Imported by: 0

Documentation

Overview

Package retrieval provides state tracking for IPFS content retrieval operations. It enables detailed diagnostics about the retrieval process, including which stage failed (path resolution, provider discovery, connection, or block retrieval) and statistics about provider interactions. This information is particularly useful for debugging timeout errors and understanding retrieval performance.

Index

Constants

View Source
const ContextKey contextKey = "boxo-retrieval-state"

ContextKey is the key used to store State in a context.Context. This can be used directly with context.WithValue if needed, though the ContextWithState and StateFromContext functions are preferred.

View Source
const MaxProvidersSampleSize = 3

MaxProvidersSampleSize limits the number of provider peer IDs (both found and failed) that are kept as a sample for diagnostic purposes. This prevents unbounded memory growth while still providing useful debugging information.

Variables

This section is empty.

Functions

func WrapWithState

func WrapWithState(ctx context.Context, err error) error

WrapWithState wraps an error with retrieval state from the context. It returns an *ErrorWithState that preserves the state for custom handling.

The error is ALWAYS wrapped if retrieval state exists in the context, because even "no providers found" is meaningful diagnostic information. If the error is already an *ErrorWithState, it returns it unchanged to avoid double-wrapping.

Example usage in a gateway or IPFS implementation:

func fetchBlock(ctx context.Context, cid cid.Cid) (blocks.Block, error) {
    block, err := blockService.GetBlock(ctx, cid)
    if err != nil {
        // Wrap error with retrieval diagnostics if available
        return nil, retrieval.WrapWithState(ctx, err)
    }
    return block, nil
}

Callers can then extract the state for custom handling:

var errWithState *retrieval.ErrorWithState
if errors.As(err, &errWithState) {
    state := errWithState.State()
    if state.ProvidersFound.Load() == 0 {
        // Handle "content not in network" case specially
    }
}

Types

type ErrorWithState

type ErrorWithState struct {
	// contains filtered or unexported fields
}

ErrorWithState wraps an error with retrieval state information. It preserves the retrieval diagnostics for programmatic access while providing human-readable error messages.

The zero value is not useful; use WrapWithState to create instances.

func (*ErrorWithState) Error

func (e *ErrorWithState) Error() string

Error returns the error message with retrieval diagnostics appended. Format: "original error: retrieval: diagnostic summary"

If err is nil, returns a generic message. If state is nil, returns just the underlying error message.

func (*ErrorWithState) State

func (e *ErrorWithState) State() *State

State returns the retrieval state associated with this error. This allows callers to access detailed diagnostics for custom handling.

func (*ErrorWithState) Unwrap

func (e *ErrorWithState) Unwrap() error

Unwrap returns the wrapped error, allowing errors.Is and errors.As to work with the underlying error.

type RetrievalPhase

type RetrievalPhase int

RetrievalPhase represents the current phase of content retrieval. Phases progress monotonically - they can only move forward, never backward. This helps identify where in the retrieval process a timeout or failure occurred.

const (
	// PhaseInitializing indicates the retrieval process has not yet started.
	PhaseInitializing RetrievalPhase = iota
	// PhasePathResolution indicates the system is resolving an IPFS path to determine
	// what content needs to be fetched (e.g., /ipfs/Qm.../path/to/file).
	PhasePathResolution
	// PhaseProviderDiscovery indicates the system is finding peers that have the content.
	PhaseProviderDiscovery
	// PhaseConnecting indicates the system is establishing connections to providers.
	PhaseConnecting
	// PhaseDataRetrieval indicates the system is transferring data to the client.
	PhaseDataRetrieval
)

func (RetrievalPhase) String

func (p RetrievalPhase) String() string

String returns a human-readable name for the retrieval phase.

type State

type State struct {
	// ProvidersFound tracks the number of providers discovered for the content.
	ProvidersFound atomic.Int32
	// ProvidersAttempted tracks the number of providers we tried to connect to.
	ProvidersAttempted atomic.Int32
	// ProvidersConnected tracks the number of providers successfully connected.
	ProvidersConnected atomic.Int32
	// contains filtered or unexported fields
}

State tracks diagnostic information about IPFS content retrieval operations. It is safe for concurrent use and maintains monotonic stage progression. Use ContextWithState to add tracking to a context, and StateFromContext to retrieve the state for updates or inspection

func ContextWithState

func ContextWithState(ctx context.Context) (context.Context, *State)

ContextWithState ensures a State exists in the context. If the context already contains a State, it returns the existing one. Otherwise, it creates a new State and adds it to the context. This function is idempotent and safe to call multiple times.

Example:

ctx, retrievalState := retrieval.ContextWithState(ctx)
// Use retrievalState to track progress
retrievalState.SetStage(retrieval.StageProviderDiscovery)

func NewState

func NewState() *State

NewState creates a new State initialized to PhaseInitializing. The returned state is safe for concurrent use.

func StateFromContext

func StateFromContext(ctx context.Context) *State

StateFromContext retrieves the State from the context. Returns nil if no State is present in the context. This function is typically used by subsystems to check if retrieval tracking is enabled and to update the state if it is.

Example:

if retrievalState := retrieval.StateFromContext(ctx); retrievalState != nil {
    retrievalState.SetStage(retrieval.StageBlockRetrieval)
    retrievalState.ProvidersFound.Add(1)
}

func (*State) AddFailedProvider

func (rs *State) AddFailedProvider(peerID peer.ID)

AddFailedProvider records a provider peer ID that failed to deliver the requested content. This method is safe for concurrent use.

func (*State) AddFoundProvider

func (rs *State) AddFoundProvider(peerID peer.ID)

AddFoundProvider records a provider peer ID that was discovered during provider search. This method is safe for concurrent use.

func (*State) GetFailedProviders

func (rs *State) GetFailedProviders() []peer.ID

GetFailedProviders returns a sample of failed providers (up to MaxProvidersSampleSize). This is not all providers, just the first few for diagnostic purposes.

func (*State) GetFoundProviders

func (rs *State) GetFoundProviders() []peer.ID

GetFoundProviders returns a sample of found providers (up to MaxProvidersSampleSize). This is not all providers, just the first few for diagnostic purposes.

func (*State) GetPhase

func (rs *State) GetPhase() RetrievalPhase

GetPhase returns the current retrieval phase. This method is safe for concurrent use.

func (*State) GetRootCID

func (rs *State) GetRootCID() cid.Cid

GetRootCID returns the root CID (first CID in the path). This method is safe for concurrent use.

func (*State) GetTerminalCID

func (rs *State) GetTerminalCID() cid.Cid

GetTerminalCID returns the terminal CID (CID of terminating DAG entity). This method is safe for concurrent use.

func (*State) SetPhase

func (rs *State) SetPhase(phase RetrievalPhase)

SetPhase updates the current retrieval phase to the given phase. The phase progression is monotonic - phases can only move forward, never backward. If the provided phase is less than or equal to the current phase, this is a no-op. This method is safe for concurrent use.

func (*State) SetRootCID

func (rs *State) SetRootCID(c cid.Cid)

SetRootCID sets the root CID (first CID in the path). This method is safe for concurrent use.

func (*State) SetTerminalCID

func (rs *State) SetTerminalCID(c cid.Cid)

SetTerminalCID sets the terminal CID (CID of terminating DAG entity). This method is safe for concurrent use.

func (*State) Summary

func (rs *State) Summary() string

Summary generates a human-readable summary of the retrieval state, useful for timeout error messages and diagnostics.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL