-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
Currently, bitswap sessions are hard to work with because we need to:
- Create a new session.
- Pass this session to all services that need access to the exchange.
Usually 2 involves re-creating these services. This can be very painful and we have many places in go-ipfs where we simply aren't doing this.
Instead, we should associate a session with a context. That way, whenever we use the context, we use the session. When we cancel the context, we cancel the session.
PRs
- switch to storing sessions in the context go-ipfs-exchange-interface#9
- Context-based sessions go-bitswap#401
- feat: use new exchange session logic go-merkledag#55
- feat: use the context to thread sessions through all commands #7201
Design
Store a session "key" in the session to identify the session.
// SessionID is an opaque type uniquely identifying a session.
type SessionID struct {
// Opaque type to ensure users don't cook this up and break things.
// Sequentially and atomically allocated.
id uint64
}
// IsZero returns true if this SessionId is the zero value (not a valid session
// ID).
func (id SessionID) IsZero() bool {
return id.id == 0
}
// NewSession registers a new session with the context. The session will be
// closed when the passed-in context is canceled.
//
// If there's already a session associated with the context, the existing
// session will be used.
//
// This function does not initialize any state, it just reserves a new SessionID
// associates it with the context.
func NewSession(ctx context.Context) context.Context {
...
}
// GetOrCreateSession loads the session from the context, or creates one if
// there is no associated session.
//
// This function also returns the context used to create the session. The
// session should be stopped when this context is canceled.
func GetOrCreateSession(ctx context.Context) (SessionID, context.Context) {
...
}Alternatives
I've considered two alternatives:
- Store the exchange/fetcher in the context.
- Store an abstract session in the context.
Embedded Exchange
We could:
- Create a session.
- Store the session/"fetcher" in the context.
- Use this session inside the blockservice instead of the actual exchange.
On one hand, this is nice because we can embed alternative exchanges for a specific request. For example, we could embed an offline exchange to perform an offline lookup.
On the other hand:
- This is spooky action at a distance.
- This only solves this particular problem and doesn't help services exchange information related to sessions.
Abstract Session
We could also store an abstract session object in the context (#6525). However, this would require building a general-purpose, abstract session/state manager. The session-key design lets us do everything the abstract session proposal does, without requiring a general-purpose anything.