Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: close streams gracefully #57

Merged
merged 3 commits into from
Aug 3, 2023
Merged

Conversation

achingbrain
Copy link
Collaborator

  • Updates all libp2p related deps
  • Refactors YamuxStream class to extend AbstractStream similar to other stream muxers
  • Stream close methods are now async

BREAKING CHANGE: stream close methods are now asyc, requires libp2p@0.46.x or later

- Updates all libp2p related deps
- Refactors `YamuxStream` class to extend `AbstractStream` similar to other stream muxers
- Stream close methods are now async

BREAKING CHANGE: stream close methods are now asyc, requires libp2p@0.46.x or later
@achingbrain achingbrain force-pushed the feat/close-streams-gracefully branch from bdc198f to 61ba47b Compare August 1, 2023 09:27
src/muxer.ts Outdated Show resolved Hide resolved
src/stream.ts Show resolved Hide resolved
src/stream.ts Outdated
},
onAbort: () => {
this.readState = HalfStreamState.Reset
this.writeState = HalfStreamState.Reset
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems before we were checking the read/write states before overwriting them.
Eg: if (this.readState === Open) this.readState = Reset
Not sure if that is still necessary or not

Copy link
Collaborator Author

@achingbrain achingbrain Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary since aborting a stream closes if for reading and writing.

I guess you could close the read end (for example) then abort but I don't know if this is a big deal or not.

The super class has similar .readStatus/.writeStatus fields so maybe these can be removed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, they don't seem to be used anywhere now

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed them and updated the tests to assert on .readStatus/.writeStatus instead.

/**
* Send a data message to the remote muxer
*/
async sendData (buf: Uint8ArrayList, options: AbortOptions = {}): Promise<void> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is this getting called?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the .sink method of AbstractStream

Comment on lines -227 to -238
switch (this.state) {
case StreamState.Finished:
return
case StreamState.Init:
// we haven't sent anything, so we don't need to send a reset.
break
case StreamState.SYNSent:
case StreamState.SYNReceived:
case StreamState.Established:
// at least one direction is open, we need to send a reset.
this.sendReset()
break
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this behavior still respected?

Copy link
Collaborator Author

@achingbrain achingbrain Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stream is opened on the remote by sending the first window update. This happens in the .newStream method on the yamux muxer before the stream is returned to the caller, so there's no way to call .abort(err) on the stream before the state has gone from StreamState.Init to StreamState.SYNSent.

Similarly .state is updated to StreamState.Finished after the readable and writable ends are both closed at which point .abort(err) is a no-op so this method is not called.

* Send a message to the remote muxer informing them a new stream is being
* opened
*/
async sendNewStream (): Promise<void> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we don't need this because we sent a SYN flag along with the first data to be sent? maybe worth commenting here

Copy link
Collaborator Author

@achingbrain achingbrain Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sort of, yeah - the stream is opened by the .newStream method in the muxer before any data is sent.

Was this intentional? If the sendWindowUpdate call is removed from the muxer it can switch to the behaviour of the other muxers which is to lazily signal opening the stream before the first data message is sent, in which case this method just needs to call this.sendWindowUpdate().

Though that can be done in a follow-up if it's desirable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the method comment to this effect.

name?: string
stat: StreamStat
metadata: Record<string, any>

state: StreamState
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this used anymore?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for example in .getSendFlags

@wemeetagain wemeetagain merged commit 2bd88a8 into master Aug 3, 2023
16 checks passed
@wemeetagain wemeetagain deleted the feat/close-streams-gracefully branch August 3, 2023 15:19
github-actions bot pushed a commit that referenced this pull request Aug 3, 2023
## [5.0.0](v4.0.2...v5.0.0) (2023-08-03)

### ⚠ BREAKING CHANGES

* stream close methods are now asyc, requires libp2p@0.46.x or later

* chore: pr comments

* chore: remove readState/writeState as they are not used any more

### Features

* close streams gracefully ([#57](#57)) ([2bd88a8](2bd88a8))
@github-actions
Copy link

github-actions bot commented Aug 3, 2023

🎉 This PR is included in version 5.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants