Skip to content

Context-Scoped Sessions #7198

@Stebalien

Description

@Stebalien

Currently, bitswap sessions are hard to work with because we need to:

  1. Create a new session.
  2. 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

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:

  1. Store the exchange/fetcher in the context.
  2. Store an abstract session in the context.

Embedded Exchange

We could:

  1. Create a session.
  2. Store the session/"fetcher" in the context.
  3. 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:

  1. This is spooky action at a distance.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/enhancementA net-new feature or improvement to an existing feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions