Description
Background
The point of data transfer sessions is to handle the logic around discovering peers that might have the data you need and which peers to ask for which subset of the data. It does this by making assumptions/guesses around the association of various requests (i.e. these 10 block requests are all associated with the same HTTP gateway request). Historically getting the plumbing right here to actually have one session in code per logical session has been a pain resulting in multiple sessions being created within single requests (e.g. gateway requests).
On top of this long standing issue we're also seeing some issues with blockservice wrappers not working nicely with sessions ipfs-shipyard/nopfs#34 due to how the abstraction layers are entangled.
Options
There have been a few recent and older proposals, most of them involve embedding session information in the context (e.g. ipfs/kubo#7198, #549 although it's incomplete on it's own).
Some of the concrete approaches some of them (along with a brief description) are:
- blockservice: move session handling as part of the interface #563 -> Put the concept of sessions in the blockservice interface
- blockservice: move to single unique struct and add
WithContentBlocker
option #561 -> Remove the abstraction of a blockservice interface and whenever someone needs more functionality it means more options passed into the boxo.BlockService struct's constructor - Context-Scoped Sessions kubo#7198 -> Make the concept of sessions global, but basically just a uint64, individual layers of the stack (e.g. bitswap or something higher level if that emerges) can then choose to locally associate state with
- Do nothing (pre blockservice: add
NewSessionContext
andEmbedSessionInContext
#549) -> Make the user create a shallow clone of the stack of components for every session
Analysis
- Doing nothing/asking the user to create one "stack" per request isn't working
- blockservice: move to single unique struct and add
WithContentBlocker
option #561 is less flexible than blockservice: move session handling as part of the interface #563
The main difference between #561 and ipfs/kubo#7198 is a tradeoff between cleanup complexity and adding more propagation of sessions everywhere.
- blockservice: move session handling as part of the interface #563
- When the context gets cleaned up by Go's GC the session object will get cleaned up as well
- Sessions need to be handled by: Session consumers (e.g. bitswap), Session creators (e.g. gateway), everything in between (e.g. boxo.blockservice, nopfs, dagservice, fetcher, etc.)
- Context-Scoped Sessions kubo#7198
- Needs to manually manage and synchronise state (
uint64
→*session
) in all session consumers - A goroutine would need to get spun up to handle cleanup on context cancellation.
- Could be a long lived one (as is currently the case in the bitswap implementation) or a short lived one via https://pkg.go.dev/context#AfterFunc
- Sessions need to be handled by: Session consumers (e.g. bitswap), Session creators (e.g. gateway)
- Needs to manually manage and synchronise state (
Let's decide which change to make going forward.
Activity