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

PCTransportManager #909

Merged
merged 30 commits into from
Nov 21, 2023
Merged

PCTransportManager #909

merged 30 commits into from
Nov 21, 2023

Conversation

lukasIO
Copy link
Contributor

@lukasIO lukasIO commented Oct 26, 2023

Second phase for connection logic refactor.
This PR introduces a PCManager. The primary idea behind it is to

  • encapsulate PC related logic
  • and thus simplify logic handled in RTCEngine
  • surface connection state changes, where only changes of "required" PCs are taken into account (support for pub only / sub only)

@changeset-bot
Copy link

changeset-bot bot commented Oct 26, 2023

🦋 Changeset detected

Latest commit: d857e98

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
livekit-client Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Oct 26, 2023

size-limit report 📦

Path Size
dist/livekit-client.esm.mjs 78.21 KB (0%)
dist/livekit-client.umd.js 83.76 KB (0%)

@lukasIO lukasIO requested review from davidzhao and boks1971 and removed request for davidzhao November 13, 2023 09:47
Copy link
Contributor

@boks1971 boks1971 left a comment

Choose a reason for hiding this comment

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

First look, looks good! Much easier to follow. Left some minor comments.

I will read this again. One thing I noticed is a bunch more await. Example

 -     if (!this.publisher) {
 -       this.configure(joinResponse);
 +     if (!this.pcManager) {
 +       await this.configure(joinResponse);

Were those places not handling things properly or the new code needs that behaviour?

src/room/Room.ts Outdated Show resolved Hide resolved
src/room/Room.ts Outdated
return;
}
const previousAnswer = this.engine.pcManager.subscriber.getLocalDescription();
const previousOffer = this.engine.pcManager.subscriber.getRemoteDescription();
Copy link
Contributor

Choose a reason for hiding this comment

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

In publisher only case, will this be undefined? Now that subscriber PC is created always, wondering if these will be empty/undefined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, that would be undefined for publisher only. What do you think is the right way to handle this? Fall back to publisher if subscriber is undefined?

Copy link
Contributor

@boks1971 boks1971 Nov 13, 2023

Choose a reason for hiding this comment

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

Yeah, I think it should include the publisher parts. previousAnswer and previousOffer are subscriber specific things needed for migration. The code below returns if there is no previousAnswer. I think it should proceed to send the message, but just not fill out the fields that are nil/undefined. Server will see nil in those fields and ignore them, but will use publish_tracks and data_channels (publisher only data channels) from the message.

Copy link
Contributor

Choose a reason for hiding this comment

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

LocalParticipant.dataChannelsInfo() I believe should just populate with publisher side data channels as subscriber is not there. That should be fine.

src/room/PCTransport.ts Show resolved Hide resolved
src/room/PCTransport.ts Show resolved Hide resolved
src/room/PCTransport.ts Show resolved Hide resolved
src/room/PCTransportManager.ts Outdated Show resolved Hide resolved
src/room/PCTransportManager.ts Outdated Show resolved Hide resolved
return answer;
}

updateConfiguration(config: RTCConfiguration, iceRestart?: boolean) {
Copy link
Contributor

Choose a reason for hiding this comment

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

could there be separate configs for publisher, subscriber?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Previously we never had a way to set different configs either, so I assumed we want to keep the behaviour.
Can you think of a scenario where separate configs would be useful?

Copy link
Contributor

Choose a reason for hiding this comment

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

Can't think of any, but just wanted to check. We do have simulation scenarios where we change transport type. Wondering if we will have something down the line which will set different transport for different peer connection. So, was thinking about keeping it flexible. Can change if it is required down the line.

src/room/PCTransportManager.ts Show resolved Hide resolved
resolve();
});
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add Publisher or Subscriber to method names. Ended up doing that in transport manager on server side as I found it easier to understand from the caller (example). I agree that it is implicit for several functions, but adding to the method name reduced cognitive load for me :-) . For example, in this file, I believe addTransceiver, addTrack, removeTrack are all on publisher. Making them something like addPublisherTransceiver, addPublisherTrack` etc. makes it very clear (at least to me :-) )

Copy link
Contributor Author

Choose a reason for hiding this comment

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

should have read all your comments before writing mine. Yeah, that makes sense to me naming wise. As mentioned above the thought was to hide that fact within the pcManager. With your initial feeling that it's easier to reason about with publisher/subscriber in the method names, I'm happy to do that change. (the whole purpose is to make the whole thing easier to reason about, so thanks for that feedback)

@lukasIO lukasIO marked this pull request as ready for review November 13, 2023 16:45
Copy link
Member

@davidzhao davidzhao left a comment

Choose a reason for hiding this comment

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

Much cleaner! Nice work

src/room/PCTransportManager.ts Show resolved Hide resolved
src/room/RTCEngine.ts Show resolved Hide resolved
const previousState = this.state;

const connectionStates = this.requiredTransports.map((tr) => tr.getConnectionState());
if (connectionStates.every((st) => st === 'connected')) {
Copy link
Member

Choose a reason for hiding this comment

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

do we care about disconnected state at all? I know for Safari, it's not particularly reliable.

is it intentional we ignore disconnected as a state?

Copy link
Contributor Author

@lukasIO lukasIO Nov 20, 2023

Choose a reason for hiding this comment

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

Good question, previously we only reacted to failed. Might make sense though to include it. In that case, would you see value in an additional state for Disconnected in the PCTransportState enum or should we treat it as closed ?

Copy link
Member

Choose a reason for hiding this comment

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

I think ignoring it as you do is probably the right behavior, it'll always turn from disconnected to failed. so it's better to not introduce a new behavior as part of an already-large change.

@@ -1551,12 +1551,12 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
}

private sendSyncState() {
Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering if this could move into RTCEngine or TransportManager. I understand it'll need a list of Tracks, but perhaps that could be a function that Room provides to RTCEngine?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

addressed this in f57d7c1

@lukasIO
Copy link
Contributor Author

lukasIO commented Nov 21, 2023

Were those places not handling things properly or the new code needs that behaviour?

Hardly any new behaviour needed. The changes are just surfacing the fact that some of the underlying methods had been async before already. I don't think this was actually causing any issues, but even just for error handling, it felt better to await things where possible

@lukasIO lukasIO merged commit 6ecf576 into main Nov 21, 2023
2 checks passed
@lukasIO lukasIO deleted the lukas/pc-manager branch November 21, 2023 14:25
@github-actions github-actions bot mentioned this pull request Nov 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants