Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Typesafe error propagation in signal connection path#1747

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
lukasIO merged 47 commits intomainfromlukas/neverthrow-signal
Nov 21, 2025

Conversation

@lukasIO
Copy link
Contributor

No description provided.

@changeset-bot
Copy link

changeset-botbot commentedNov 14, 2025
edited
Loading

🦋 Changeset detected

Latest commit:90d9eca

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

This PR includes changesets to release 1 package
NameType
livekit-clientPatch

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-actionsbot commentedNov 14, 2025
edited
Loading

size-limit report 📦

PathSize
dist/livekit-client.esm.mjs86.94 KB (0%)
dist/livekit-client.umd.js95.48 KB (0%)

Comment on lines 30 to +37
exportclassWebSocketStream<TextendsArrayBuffer|string=ArrayBuffer|string>{
readonlyurl:string;

readonlyopened:Promise<WebSocketConnection<T>>;
readonlyopened:ResultAsync<WebSocketConnection<T>,WebSocketError>;

readonlyclosed:Promise<WebSocketCloseInfo>;
readonlyclosed:ResultAsync<WebSocketCloseInfo,WebSocketError>;

readonlyclose:(closeInfo?:WebSocketCloseInfo)=>void;
readonlyclose!:(closeInfo?:WebSocketCloseInfo)=>void;
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: if the plan is to eventually migrate to the in-built browserWebsocketStream (and from what I can see, it is onsome sort ofstandards track), it might be worth treating this like vendored code that shouldn't be modified and doing theseResultAsync patches where this is being used in the signal client code.

I can think of pros and cons to both approaches though so I'd be curious to hear your rationale if there is a reason why doing this would be overly burdensome.

Copy link
ContributorAuthor

@lukasIOlukasIONov 18, 2025
edited
Loading

Choose a reason for hiding this comment

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

Fair point. Was thinking about this too. I have currently less confidence into adapting the standard proposal any time soon. Given that, I think starting with the error propagation at the lowest level sounded like the right choice to me

1egoman reacted with thumbs up emoji
Copy link
Contributor

@xianshijing-lkxianshijing-lk left a comment
edited
Loading

Choose a reason for hiding this comment

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

some minor comments.

From the general code structure perspective, I think it is the right direction to setup a pattern where the code will throw.
I think moving the throw code to upper layer sounds a good idea, assuming the lower level codestop throwing for expected errors.

lukasIO reacted with thumbs up emoji
Copy link
Contributor

@1egoman1egoman left a comment

Choose a reason for hiding this comment

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

Looks good to me! Just generally, I think I'm realizing there's some fairly nuanced behavior with neverthrow that doesn't carry over 1:1 with how rust handles errors, so I think I'll need to spend some time digging into some of those nuances.

Comment on lines +274 to +277
constself=this;

consthandleSignalConnected=(
connection:WebSocketConnection,
firstMessage?:SignalResponse,
)=>{
this.handleSignalConnected(connection,wsTimeout,firstMessage);
};
returnwithMutex(
safeTry<U,ConnectionError>(asyncfunction*(){
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion(non-blocking): When I was first trying to parse through this I saw you swapped allthis ->self and it took me a second to figure out exactly whereself was being assigned and why you had done this. It looks like (from what I can tell) it's due to the generator function creating a new explicitthis scope.

I wanted to propose another option instead - something likeasync function* () {}.bind(this). There's some discussion here on the pros/cons:supermacro/neverthrow#632. At least as somebody coming into reading this code for the first time, I think it would help but it's minor and something I don't have a strong opinion on.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Generally 50:50 on both, but reading through the issue you linked it mentions two steps being necessary for typescript today to properly bind it, i.e.:return safeTry(function* (this: CurrentClass) {}).bind(this) which would sway me to leave it as is.

reason:unknown,
validateUrl:string,
):Promise<ConnectionError>{
):Promise<Result<never,ConnectionError>>{
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: I think this should beResultAsync instead and the returns from this function updated to beerrAsync?

UPDATE: reading a little further, this might actually be intended. I'm still leaving this comment though because I think it's relevant to a future comment.

returnResultAsync.fromPromise(Promise.race(settledPromises),(e)=>easE);
}

exporttypeResultAsyncLike<T,E>=ResultAsync<T,E>|Promise<Result<T,E>>;
Copy link
Contributor

Choose a reason for hiding this comment

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

question: Interesting - in mylast comment I had assumed thatPromise<Result<T, E>> was a mistake, but this line implies this is very much intentional. Is this a pattern because of async functions always returning promises, ie, the same type of topic asthis issue?

Just thinking out loud but I wonder if handling this difference at this level of abstraction is the right place to do it (naively as somebody who hasn't really dug too much intoneverthrow in depth yet, this semantic difference is surprising), or if it would be better to write a utility function which can convert anyPromise<Result<T, E>> to aResultAsync<T, E>.

I think I'd need to play around with it a bit on my own to develop a stronger opinion so feel free to keep it how it is for now and we can discuss it in the future once I've been able to dig in further.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

yeah, it's on purpose but mostly as an intermediate step until we have ported all async internals to the result type.

The helper function is a nice idea, we'd then have to have it include a genericError though as thePromise could still through and would have to be unwrapped safely.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Is this a pattern because of async functions always returning promises, ie, the same type of topic assupermacro/neverthrow#42?

yes, this was the reason and for the helpers I thought having a helper type to accept both would be nice

Comment on lines +1044 to +1045
constself=this;
constrestartResultAsync=safeTry(asyncfunction*(){
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion(non-blocking): another instance ofhttps://github.com/livekit/client-sdk-js/pull/1747/files#r2546082926 - consider maybe also using.bind(this) here.

@lukasIOlukasIO merged commit8b8ddbd intomainNov 21, 2025
5 checks passed
@lukasIOlukasIO deleted the lukas/neverthrow-signal branchNovember 21, 2025 12:07
lukasIO added a commit that referenced this pull requestNov 21, 2025
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@xianshijing-lkxianshijing-lkxianshijing-lk left review comments

@1egoman1egoman1egoman approved these changes

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

4 participants

@lukasIO@1egoman@xianshijing-lk

[8]ページ先頭

©2009-2025 Movatter.jp