ipfs / boxo

A set of reference libraries for building IPFS applications and implementations in Go.
https://github.com/ipfs/boxo#readme
Other
214 stars 95 forks source link

[ipfs/go-bitswap] Sync sessions and received blocks #92

Open dirkmc opened 4 years ago

dirkmc commented 4 years ago

Currently the synchronization between block receipt and sessions is not quite air-tight, leading to some race conditions.

Background

When IPFS wants a block it

When Bitswap receives a block it

There are overlapping concerns handled in different places (SessionInterestManager vs "notifier") and non-atomic operations, and the code is complex and hard to follow.

Proposal

Create a unified Notifier interface that can synchronize operations and ensure atomicity.

Notifier

Subscription

ResponseMessage is a struct with public fields for blocks, HAVEs and DONT_HAVEs.

When IPFS asks a Bitswap Session for a block, the Session will call Subscribe() on the Notifier:

When a request is cancelled the Session will call Unsubscribe() for those keys. When the Session shuts down it will call Unsubscribe() with the session id.

Stebalien commented 4 years ago

Subscribe(ctx context.Context, sesid uint64, keys ...cid.Cid) <-chan ResponseMessage

I assume we'll have to change this to something like:

Subscribe(chan <- ResponseMessage, keys ...cid.Cid) (where keys can be nil to cancel).

Unsubscribe(sesid uint64, keys ...cid.Cid)

Having unsubscribe trigger a cancel but not having subscribe trigger a want is weird. I'm wondering if we should just make this interface session agnostic.

Note that because operations on the blockstore are slow

Note 1: there should already be a cache. IMO, we should let the application do this for us. Note 2: we may need to improve some contention issues in the cache, but I'm not sure if it's actually an issue.

dirkmc commented 4 years ago

I updated the original post to change the interfaces a little.

I think we can tackle streaming GetBlocks() separately, but it shouldn't be a bit lift to change it.

I'll put together a PR to see what this looks like in practice and post it as a WIP.