Open Stebalien opened 4 years ago
Thanks for doing this work - in retrospect I should have written something like this at the beginning of the refactor :)
If you have some time, want to take a stab at filling this out? Or modifying it to match bitswap as-is? It should make it easier to reason about the changes.
Bitswap Architecture
This is a loose sketch of a potential bitswap architecture. It's mostly based on the current architecture (plus https://github.com/ipfs/go-bitswap/pull/398), but I've tried to simplify some things.
Really, this is mostly to help me understand how everything is (and could be) structured. Unfortunately, reality is complected so I'm missing a lot of edge cases including:
GetBlocks
A single "request" from the user, attached to a session.
want(cids, inBlockCh)
cancel(inBlockCh)
blocks(blocks)
Session
The session managers related wants/peers and makes all decisions concerning where/when to send wants.
uint64
(session id)map[cid]map[GetBlocks.inBlockCh]struct{}
(used when routing incoming blocks to GetBlocks calls)map[GetBlocks.inBlockCh]map[cid]struct{}
(used when canceling GetBlocks, not strictly necessary)receive(block, have, havenot)
available(peer)
gone(peer)
blocks(blocks)
want(cids, Session.blockInfoCh)
cancel(cids, Session.blockInfoCh)
cancelAll(session.blockInfoCh)
(cancels all requests by this session)interest(peers, Session.peerInfoCh)
cancel(peers, Session.peerInfoCh)
cancelAll(Session.peerInfoCh)
peerInfoCh
when sending these requests.send(Session.id, peers, wants, haves, peers)
broadcast(cids, peers, Session.id)
cancel(cids, Session.id)
cancelAll(Session.id)
BlockRouter
Routes blocks (and information about blocks) to the appropriate services. All incoming blocks pass through this service.
change: This was the WantRequestManager (mostly).
map[cid]map[Session.blockInfoCh]struct{}
(used to route incoming information)map[cid]map[Session.blockInfoCh]struct{}
(used to route incoming information)map[Session.blockInfoCh]map[cid]struct{}
(used for canceling, probably not necessary)want(cids, Session.blockInfoCh)
cancel(cids, Session.blockInfoCh)
cancelAll(Session.blockInfoCh)
(cancels all requests by this session)Session.blockInfoCh
when done to signal that the cancel is complete.message(from, blocks, haves, donthave)
blockPut(blocks)
message(from, blocks, haves, donthaves)
blocksAvailable(cids + block sizes)
PeerRouter
Routes incoming peer information to interested sessions.
map[peer]map[Session.peerCh]struct{}
// used to route incoming informationmap[Session.peerCh]map[cid]struct{}
// Used for canceling. Probably not necessaryinterest(peers, Session.peerInfoCh)
cancel(peers, Session.peerInfoCh)
cancelAll(Session.peerInfoCh)
Session.peerInfoCh
when done to signal that the cancel is complete.peerConnected(peer)
peerDisconnected(peer)
receive(block, have, havenot)
WantManager
Manages our outbound, per-peer wantlists (refcounting per session).
cidSessSet
map[peer]*peerWant
map[cid]map[peer]struct{}
send(Session.id, peers, wants, haves, peers)
broadcast(cids, peers, Session.id)
cancel(cids, Session.id)
cancelAll(Session.id)
Engine
Tracks inbound wantlists and sends back blocks.
wantlist(from, wantlist, cancels)
blocksAvailable(cids + sizes)
Network
Service to interact with the network. This one is kind of funky as there's no central event loop.
peerConnected(peer)
peerDisconnected(peer)
wantlist(from, wantlist, cancels)
message(from, blocks, haves, donthave)
Ledger
Tracks our debt ratio with our peers. Updated synchronously by both the Engine (when sending blocks) and the BlockRouter (when receiving blocks).
change: Currently, this is embedded in the Engine. It should be it's own thing. change: Currently, the ledger also tracks who wants what. Wantlists should be tracked in the engine.