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

fix: always throw errors & always use named Error classes #1985

Merged
merged 35 commits into from
Nov 21, 2024

Conversation

KyleAMathews
Copy link
Contributor

Fixes #1983

@KyleAMathews KyleAMathews changed the title fix: always throw errors & alway use named Error classes fix: always throw errors & always use named Error classes Nov 16, 2024
Copy link

netlify bot commented Nov 16, 2024

Deploy Preview for electric-next ready!

Name Link
🔨 Latest commit 983815c
🔍 Latest deploy log https://app.netlify.com/sites/electric-next/deploys/6737ee51bb0612000826b9b9
😎 Deploy Preview https://deploy-preview-1985--electric-next.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@KyleAMathews
Copy link
Contributor Author

I'm skeptical now too of our passing errors to the subscribe functions. We have no way of recovering from the errors and also try/catch is the normal way of seeing errors. I'll remove those in another pr unless people disagree.

@KyleAMathews
Copy link
Contributor Author

It'd be nice to have an observable style interface as well but we're not using that anywhere so in practice right now we just lose the errors. Observables are the exception so people should opt into that interface.

@KyleAMathews
Copy link
Contributor Author

KyleAMathews commented Nov 16, 2024

Also if we do observables we need the third parameter for the stream complete callback.

Copy link

netlify bot commented Nov 17, 2024

Deploy Preview for electric-next ready!

Name Link
🔨 Latest commit 728b3b2
🔍 Latest deploy log https://app.netlify.com/sites/electric-next/deploys/673cd73baaf15b000841b160
😎 Deploy Preview https://deploy-preview-1985--electric-next.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@KyleAMathews
Copy link
Contributor Author

I need to update a few tests to catch errors that are thrown.

@KyleAMathews
Copy link
Contributor Author

Hmm actually these are all 404s — which suggests they're related to the multi-tenant work?

Copy link
Contributor

@kevin-dp kevin-dp left a comment

Choose a reason for hiding this comment

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

LGTM!

export class MissingShapeUrlError extends Error {
constructor() {
super(`Invalid shape options: missing required url parameter`)
this.name = `MissingShapeUrlError`
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we also overwrite this.name in FetchBackoffAbortError?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh right, yeah missed that one.

@kevin-dp
Copy link
Contributor

Hmm actually these are all 404s — which suggests they're related to the multi-tenant work?

If they are multi tenant related they should be gone once we extract multi tenancy to a separate app.
Planning to finish that today, once it's in main we could rebase to see if the errors persist.

Copy link
Contributor

@thruflo thruflo left a comment

Choose a reason for hiding this comment

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

This looks much clearer and more explicit and great to have the specific errors documented.

One observation is that this leads to two places where there is similar error handling: one is on instantiation and one is in the subscribe handler. I see the types of error handling may be different for the two locations -- I.e.: validate params on instantiate, handle FetchError ongoing. So I think this makes sense. But just to float the alternative, it could perhaps be possible to have a single try catch around a stream.run() function.

I know you're questioning the subscribe handler in the comments here. I do think it would be helpful to have a definitive pattern for how to handle 4xx errors from downstream Shape / useShape style functions.

In reality, there are circumstances where 4xx errors are transient or fixed on retry. For example, where they will be fixed by time passing or a new auth token, etc. When you have a component with a useShape binding in a local app, the sync binding needs to be absolutely bulletproof.

So I think we are going to have to expose a "handle FetchErrror when running" callback and I think we should have the result of that callback be able to determine whether the client continues with a backoff algorithm and also to potentially change the shape options. This could then be the mechanism to "restart" the shape stream, because actually if the return value is [true, {...updated_options...}] (or whatever) then the stream actually never stops.

@KyleAMathews
Copy link
Contributor Author

KyleAMathews commented Nov 18, 2024

But just to float the alternative, it could perhaps be possible to have a single try catch around a stream.run() function.

That's the Elixir client :-P — for JS, when you start a new ShapeStream, it immediately starts running.

I hear you about needing to make transient 401 errors easier to handle — you can handle it with a try/catch which then restarts the stream — the problem with this of course is then you have to restart the fetching every time and it's not particularly ergonomic.

Exposing a way to customize error handling makes sense too — it'd be easy to mess up the shape stream that way but the server would protect against that by forcing the client to refetch.

These are separate problems from what this PR is trying to fix so let's continue the discussion in #1982

@thruflo
Copy link
Contributor

thruflo commented Nov 18, 2024

Cool, let's get this merged.

N.b.:

when you start a new ShapeStream, it immediately starts running.

When I read this I immediately thought: if you don't immediately pass the stream to a shape, you may miss messages from the stream that are fired before you register subscribers. Presumably this is an "add it when people ask for it" feature but an autoRun: false option + stream.run() combo may be useful at some point.

@KyleAMathews
Copy link
Contributor Author

Ok I hadn't wrapped my head around this when I banged this out Friday evening — but yeah — calling run() from the constructor does mean that a try/catch around the new ShapeStream call won't catch any errors thrown while the stream is running...

So autoRun false would work or... just disable autoRun and make .run() an explicit step as then error catching is neatly split between constructing the class and running the class.

@balegas
Copy link
Contributor

balegas commented Nov 18, 2024

So autoRun false would work or... just disable autoRun and make .run() an explicit step as then error catching is neatly split between constructing the class and running the class.

I'm a strong advocate for separating creating and running the stream. There are errors you want to catch early because those are fatal errors and it's worthless to start the stream. In general any side effects from a constructor are hard to work with because you cannot await.

(cc @msfstef )

@KyleAMathews
Copy link
Contributor Author

@balegas yeah I added an autoRun option but we could just make the two step process the default. This is a breaking change but now's the time to do that.

@KyleAMathews
Copy link
Contributor Author

Let's reconvene tomorrow to chat about this

@KyleAMathews
Copy link
Contributor Author

Not sure why all the react hook tests are failing 🤔

@KyleAMathews
Copy link
Contributor Author

@kevin-dp I incorporated your changes but commented out the retry logic as that'll need tests & docs and this PR is getting way too long in the tooth as it is — so you or someone else can pick that up in a subsequent PR.

I'm out of time to work on this today — if someone wants to figure out why the react-hooks tests are all not working, that'd be great.

@kevin-dp kevin-dp assigned msfstef and unassigned msfstef Nov 20, 2024
@kevin-dp kevin-dp requested a review from msfstef November 20, 2024 14:03
Copy link
Contributor

@msfstef msfstef left a comment

Choose a reason for hiding this comment

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

Nice, I like the named errors! I've left some requests for changes (especially removing the autoStart mention in the changeset)

.changeset/fair-pants-pretend.md Outdated Show resolved Hide resolved
packages/typescript-client/src/client.ts Outdated Show resolved Hide resolved
packages/typescript-client/src/client.ts Outdated Show resolved Hide resolved
packages/typescript-client/src/client.ts Outdated Show resolved Hide resolved
packages/typescript-client/src/client.ts Outdated Show resolved Hide resolved
thruflo added a commit that referenced this pull request Nov 20, 2024
…2017)

Fixes #1996.

We remove `subscribeOnceToUpToDate` in favor of subscribing to the
stream and "waiting" for the first `up-to-date` control message. **This
is a breaking change.**
@kevin-dp
Copy link
Contributor

I cherry picked 12fd091 because it was conflicting with that PR which is in main and rebasing is a pain because of the enormous amounts of commits in the branch + some of those commits introduce the explicit start feature and then removes it in a commit later down the line which causes a lot of conflicts.

@KyleAMathews
Copy link
Contributor Author

Thanks for finishing this up @kevin-dp! I'm very much looking forward to always seeing nice clear errors now 😆

@KyleAMathews KyleAMathews merged commit 5a7866f into main Nov 21, 2024
21 of 26 checks passed
@KyleAMathews KyleAMathews deleted the throw-error branch November 21, 2024 13:52
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.

Audit errors in Typescript class
5 participants