ipfs / ipfs/kubo

Context-Scoped Sessions

Open
#7,198 3 comments 2 reactions 0 assignees View on GitHub
kind/enhancement
Dominant language
Go
Stars
17.1k
Forks
3.2k
Avg merge
3d 18h
Merged PRs (30d)
11

Description

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

* [ ] https://github.com/ipfs/go-ipfs-exchange-interface/pull/9
* [ ] https://github.com/ipfs/go-bitswap/pull/401
* [ ] https://github.com/ipfs/go-merkledag/pull/55
* [ ] https://github.com/ipfs/go-ipfs/pull/7201

## Design

Store a session "key" in the session to identify the session.

```go
// 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 (https://github.com/ipfs/go-ipfs/issues/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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.