@startuml "GraphSync" package "go-ipld-prime" { interface Node { } interface NodeBuilder { } interface Path { } interface Link package traversal { package selector { interface Selector { } object "PackagePublicFunctions" as goSelectorPF { ReifySelector(cidRootedSelector Node) (Selector, error) } } interface AdvVisitFn { } class TraversalConfig { } class TraversalProgress { TraverseInformatively(Node, Selector, AdvVisitFn) } TraversalProgress *-- TraversalConfig } interface Storer { } interface Loader { } } package "go-graphsync" { interface Cid2BlockFn { } class GraphSync { Request(ctx context.Context, p peer.ID, rootedSelector Node) (chan ResponseProgress, chan error) GetBlocks(ctx context.Context, p peer.ID, rootedSelector Node) (chan blocks.Block, chan error) ReceiveMessage(ctx context.Context, sender peer.ID, incoming GraphSyncMessage) ReceiveError(error) } GraphSync *-- Loader package network { interface Receiver { ReceiveMessage(ctx context.Context, sender peer.ID, incoming GraphSyncMessage) ReceiveError(error) } interface GraphSyncNetwork { SendMessage(ctx context.Context, receiver peer.Id, m GraphSyncMessage) SetDelegate(receiver Receiver) ConnectTo(ctx context.Context, peer.ID) error NewMessageSender(context.Context, peer.ID) (MessageSender, error) } interface MessageSender { SendMsg(context.Context, GraphSyncMessage) error Close() error Reset() error } Receiver <|-- GraphSync : receiver for class libP2PGraphSyncNetwork { } GraphSyncNetwork <|-- libP2PGraphSyncNetwork object "Package Public Functions" as goGraphSyncNetworkPF { NewLibP2PNetwork(host libp2pHost.Host) GraphSyncNetwork } goGraphSyncNetworkPF .. libP2PGraphSyncNetwork } package messagequeue { class MessageQueue { AddRequest(GraphSyncRequest) AddResponses([]GraphSyncResponse, []Block) <-chan struct{} Startup() Shutdown() } object "PackagePublicFunctions" as goMessageQueuePF { New(context.Context, peer.ID, GraphSyncNetwork) *MessageQueue } GraphSync .. goMessageQueuePF MessageQueue *-- GraphSyncNetwork } package peermanager { class PeerManager { Connected(p peer.ID) Disconnected(p peer.ID) ConnectedPeers() []peer.ID GetProcess(peer.ID) PeerProcess } class PeerMessageManager { SendRequest(peer.ID, GraphSyncRequest) SendResponses(peer.ID, []GraphSyncResponse, []Block) } object "Package Public Functions" as goPeerManagerPF { New(ctx context.Context, createPeerProcess func(context, peer.ID) PeerProcess) NewMessageManager(ctx context.Context, createPeerQueue func(context, peer.ID) MessageQueue) } GraphSync .. goPeerManagerPF PeerManager <|-- PeerMessageManager PeerMessageManager *-- MessageQueue } package linktracker { class LinkTracker { ShouldSendBlockFor(Link) bool RecordLinkTraversal(GraphSyncRequestID, Link, bool) FinishRequest(GraphSyncRequestID) bool } object "Package Public Functions" as goLinkTrackerPF { New() *LinkTracker } } package requestmanager { package types { interface ResponseProgress { } interface AsyncLoadResult { } } package "loader" as reqLoader { interface AsyncLoadFn { } object "Package Public Functions" as goRequestLoaderPF { WrapAsyncLoader(context.Context, AsyncLoadFn, GraphSyncRequestID, chan error) } } package asyncloader { package loadattempqueue { interface LoadRequest { } interface LoadAttempter { func(GraphSyncRequestID, ipld.Link) ([]byte, error) } class LoadAttemptQueue { AttemptLoad(LoadRequest, bool) ClearRequest(GraphSyncRequestID) RetryLoads() } object "Package Public Functions" as goLoadAttemptQueuePF { NewLoadRequest(GraphSyncRequestID, ipld.Link, chan AsyncLoadResult) LoadRequest New(LoadAttempter) *LoadAttemptQueue } } package unverifiedblockstore { class UnverifiedBlockStore { AddUnverifiedBlock(ipld.Link, []byte) PruneBlocks(func(ipld.Link) bool) VerifyBlock(ipld.Link) ([]byte, error) } object "Package Public Functions" as goUnverifiedBlockStore { New(Storer) *UnverifiedBlockStore } } package responsecache { class ResponseCache { FinishRequest(GraphSyncRequestID) AttemptLoad(GraphSyncRequestID, ipld.Link) ([]byte, error) ProcessResponse(map[GraphSyncRequestID]Metadata, []blocks.Block) } object "Package Public Functions" as goResponseCachePF { New(UnverifiedBlockStore) *ResponseCache } ResponseCache *-- LinkTracker ResponseCache *-- UnverifiedBlockStore ResponseCache .. goLinkTrackerPF } class AsyncLoader { StartRequest(GraphSyncRequestID) ProcessResponse(map[gsmsg.GraphSyncRequestID]metadata.Metadata, []blocks.Block) AsyncLoad(requestID gsmsg.GraphSyncRequestID, link ipld.Link) AsyncLoadResult CompleteResponsesFor(GraphSyncRequestID) CleanupRequest(GraphSyncRequestID) } object "Package Public Functions" as goAsyncLoaderPF { New(context.Context, ipld.Loader, ipld.Storer) *AsyncLoader } AsyncLoader *-- LoadAttemptQueue AsyncLoader *-- ResponseCache AsyncLoader *-- Loader AsyncLoader *-- Storer AsyncLoader .. goUnverifiedBlockStore AsyncLoader .. goResponseCachePF AsyncLoader .. goLoadAttemptQueuePF } class RequestManager { SetDelegate(peerHandler PeerMessageManager) SendRequest(ctx context.Context, p peer.ID, cidRootedSelector Node) chan ResponseProgress, chan error ProcessResponses(peer.ID, []GraphSyncResponse, []blocks.Block) } object "Package Public Functions" as goRequestManagerPF { New(ctx context.Context, asyncLoader AsyncLoader, ipldBridge ipldbridge.IPLDBridge) *RequestManager } RequestManager *-- AsyncLoader RequestManager *-- PeerManager RequestManager .. goRequestLoaderPF GraphSync *-- RequestManager GraphSync .. goRequestManagerPF } package responsemanager { package peertaskqueue { package peertask { class Task { } class TaskBlock { MarkPrunable(Identifier) PruneTasks() Index() SetIndex(int) } interface Identifier { } object "Package Public Functions" as goPeerTaskPF { FIFOCompare(a, b *TaskBlock) bool PriorityCompare(a, b *TaskBlock) bool WrapCompare(func(a, b *TaskBlock) bool) func(a, b pq.Elem) bool NewTaskBlock([]Task, int, peer.ID, func([]Task)) *TaskBlock } } package peertracker { class PeerTracker { StartTask(Identifier) TaskDone(Identifier) Index() SetIndex(int) PushBlock(peer.ID, []Task, func([]Task)) PopBlock() *TaskBlock Remove(Identifier) Freeze() Thaw() bool FullThaw() IsFrozen() bool } object "Package Public Functions" as goPeerTrackerPF { New() *PeerTracker PeerCompare(a, b pq.Elem) bool } PeerTracker *-- TaskBlock PeerTracker .. goPeerTaskPF } class PeerTaskQueue { PushBlock(to peer.ID, tasks ...Task) PopBlock() *TaskBlock Remove(identifier Identifier, p peer.ID) ThawRound() FullThaw() } PeerTaskQueue *-- PeerTracker PeerTaskQueue .. goPeerTrackerPF object "Package Public Functions" as goPeerTaskQueuePF { New() *PeerTaskQueue } GraphSync .. goPeerTaskQueuePF } package "loader" as resLoader { object "Package Public Functions" as goResponseLoaderPF { WrapLoader(Loader,GraphSyncRequestID, PeerResponseSender) Loader } } package responsebuilder { class ResponseBuilder { AddBlock(Block) AddLink(GraphSyncRequestID, Link, bool) AddCompletedRequest(GraphSyncRequestID, GraphSyncResponseStatusCode) Empty() bool Build(IPLDBridge) ([]GraphSyncResponse, []Block, error) } object "Package Public Functions" as goResponseBuilderPF { New() *ResponseBuilder } } package peerresponsemanager { class PeerResponseManager { SenderForPeer(p peer.ID) PeerResponseSender } class PeerResponseSender { Startup() Shutdown() SendResponse(GraphSyncRequestID,Link,[]byte) FinishRequest(GraphSyncRequestID) FinishWithError(GraphSyncRequestID, GraphSyncResponseStatusCode) } object "Package Public Functions" as goPeerResponseManagerPF { New(Context, func(Context, peer.ID) PeerResponseSender) *PeerResponseManager NewResponseSender(Context, peer.ID, PeerMessageManager, IPLDBridge) PeerResponseSender } PeerResponseManager *-- PeerResponseSender PeerResponseSender *-- LinkTracker PeerResponseSender *-- ResponseBuilder PeerResponseSender *-- PeerMessageManager PeerResponseSender .. goLinkTrackerPF PeerResponseSender .. goResponseBuilderPF GraphSync .. goPeerResponseManagerPF } class ResponseManager { ProcessRequests(context, peer.ID, []GraphSyncRequests) } object "Package Public Functions" as goResponseManagerPF { New(Context, Loader, IPLDBridge, PeerResponseManager, PeerTaskQueue) *ResponseManager } GraphSync *-- ResponseManager ResponseManager *-- Loader ResponseManager *-- PeerResponseManager ResponseManager *-- PeerTaskQueue ResponseManager .. goResponseLoaderPF GraphSync .. goResponseManagerPF } package message { object "Package Public Functions" as goGraphSyncMessagePF { func FromPBReader(pbr ggio.Reader) (GraphSyncMessage, error) func FromNet(r io.Reader) (GraphSyncMessage, error) func New() GraphSyncMessage func NewRequest(GraphSyncRequestID, []byte, GraphSyncPriority) GraphSyncRequest func CancelRequest(GraphSyncRequestID) GraphSyncRequest func NewResponse(GraphSyncRequestID, GraphSyncResponseStatusCode, []byte) GraphSyncResponse } goGraphSyncMessagePF .. libP2PGraphSyncNetwork class GraphSyncRequest { Selector() []bytes Priority() Priority ID() int IsCancel() bool } class GraphSyncResponse { RequestID() int Status() GraphSyncStatus Extra() []bytes } interface GraphSyncMessage { Requests() : []GraphSyncRequest Responses() : []GraphSyncResponse Blocks() : []Blocks AddRequest(GraphSyncRequest) AddResponse(GraphSyncResponse) AddBlock(Block) } interface Exportable { ToProto() ToNet(w io.Writer) error } Exportable --|> GraphSyncMessage GraphSyncRequest --* GraphSyncMessage GraphSyncResponse --* GraphSyncMessage } package ipldbridge { interface IPLDBridge { BuildNode(func(NodeBuilder) ipld.Node) (ipld.Node, error) ValidateSelectorSpec(rootedSelector ipld.Node) []error EncodeNode(ipld.Node) ([]byte, error) DecodeNode([]byte) (ipld.Node, error) DecodeSelectorSpec(cidRootedSelector ipld.Node) (ipld.Node, Selector, error) Traverse(ctx context.Context, loader Loader, root ipld.Node, s Selector, fn AdvVisitFn) error } GraphSync *-- IPLDBridge RequestManager *-- IPLDBridge ResponseManager *-- IPLDBridge PeerResponseSender *-- IPLDBridge class ipldBridge { } object "PackagePublicFunctions" as goIPLDBridge { NewIPLDBridge() IPLDBridge } IPLDBridge <|-- ipldBridge goIPLDBridge .. ipldBridge ipldBridge *-- MulticodecDecodeTable ipldBridge *-- NodeBuilderChooser ipldBridge .. TraversalProgress ipldBridge .. goSelectorPF ipldBridge .. goIPLDReposePf } object "PackagePublicFunctions" as goGraphsyncPf { New(ctx context.Context, network GraphSyncNetwork, ipldBridge IPLDBridge, loader Loader) GraphSync LoaderFromCid2BlockFn(cid2BlockFn Cid2BlockFn) Loader SelectorSpecFromCidAndPath(lnk cid.Cid, pathSegments []string) (ipld.Node, error) } } package "go-filecoin" { class "go-filecoin" { } "go-filecoin" *-- GraphSync "go-filecoin" .. goGraphsyncPf "go-filecoin" .. goGraphSyncNetworkPF "go-filecoin" .. goIPLDBridge "go-filecoin" *-- RawLoader "go-filecoin" *-- MulticodecDecodeTable "go-filecoin" *-- NodeBuilderChooser } @enduml