-
-
Notifications
You must be signed in to change notification settings - Fork 96
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
Migrating an endpoint that uses a database. #1046
base: feat/add-tutorials
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
@samwho is attempting to deploy a commit to the Effect Team on Vercel. A member of the Team first needs to authorize it. |
content/src/content/docs/learn/tutorials/hooking-up-a-database.mdx
Outdated
Show resolved
Hide resolved
content/src/content/docs/learn/tutorials/hooking-up-a-database.mdx
Outdated
Show resolved
Hide resolved
content/src/content/docs/learn/tutorials/hooking-up-a-database.mdx
Outdated
Show resolved
Hide resolved
content/src/content/docs/learn/tutorials/hooking-up-a-database.mdx
Outdated
Show resolved
Hide resolved
content/src/content/docs/learn/tutorials/hooking-up-a-database.mdx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few minor comments for today! Great work @samwho - it's coming along very nicely!
content/src/content/docs/learn/tutorials/hooking-up-a-database.mdx
Outdated
Show resolved
Hide resolved
content/src/content/docs/learn/tutorials/hooking-up-a-database.mdx
Outdated
Show resolved
Hide resolved
content/src/content/docs/learn/tutorials/hooking-up-a-database.mdx
Outdated
Show resolved
Hide resolved
content/src/content/docs/learn/tutorials/hooking-up-a-database.mdx
Outdated
Show resolved
Hide resolved
….mdx Co-authored-by: Maxwell Brown <[email protected]>
….mdx Co-authored-by: Maxwell Brown <[email protected]>
….mdx Co-authored-by: Maxwell Brown <[email protected]>
….mdx Co-authored-by: Maxwell Brown <[email protected]>
With this information we can ensure, and get TypeScript to verify for us, | ||
that things do not go wrong in unexpected ways. | ||
|
||
```ts twoslash | ||
// @errors: 2375 | ||
import { Effect } from "effect" | ||
|
||
const effect = Effect.succeed(1).pipe( | ||
Effect.tryMap({ | ||
try: (n) => n + 1, | ||
catch: () => new Error(), | ||
}), | ||
) | ||
|
||
const noError: Effect.Effect<number, never, never> = effect |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This transition felt a bit abrupt to me. To me, it might feel more natural if you insert one of the "aside"-esque comments you've had previously (recall the pipe
aside). Perhaps "An aside on errors in Effect" or something?
Also, before now Effect.tryMap
has not even been mentioned but now we're using it all of a sudden.
Might be worth using the user fetch code from above for these samples instead of the random tryMap
code, given that you also insert it into the final snippet later anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did wonder about whether to explicitly call out Effect.tryMap
and landed on not doing so. It felt like because we've already covered Effect.map
, and we looked at Effect.try
in the previous section, the reader wouldn't flinch at Effect.tryMap
being casually used without explanation.
A small nod to it might be the way to go, though. I need to start being careful, I've not spent more time with Effect than the reader and am likely prone to thinking they'll understand things they might not. 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My take reading through this is that this section would honestly be more clear to me if you just stick with the chunk of code from before:
Effect.tryPromise({
try: () => db.query("SELECT * FROM users"),
catch: (cause) => new UserFetchError("failed to fetch users", { cause }),
})
This effectively recreates the behaviour of throwing an exception. Defects are | ||
critical errors that you don't want to handle. If you were to create a defect in | ||
an Effect handler, the result would be a 500 error returned to the user. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth one more sentence or something here providing a clear distinction between "expected" errors, which are part of the program's domain, and "defects" which are critical errors (as you explained).
//---cut--- | ||
class UserFetchError extends Error {} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a variety of reasons, I would advise against this pattern.
For one, the lack of a discriminator in the type (e.g. a _tag
) means that another error which extends Error
can be directly assignable to the UserFetchError
: https://effect.website/play#55cd56ec464d.
My recommendation would be to either:
- Take the time to introduce creating your own domain-specific errors more properly here via
Data.TaggedError
https://effect.website/docs/data-types/data/#taggederror - Just make the error an interface in this case for now if you want to keep it simple
interface UserFetchError {
readonly _tag: "UserFetchError"
readonly message: string
readonly cause: unknown
}
I personally think it might be good to go for the first option given that Data.TaggedError
will automatically attach a _tag
to our error type and also extends Error
for us by default, but I leave that decision to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agonised over this, because tags do feel like they deserve special attention and I'll soon get to them when I talk about services. I wanted to wait for a place I needed to use them in error handling to introduce them. I also don't want to wander too far away from the purpose of this section: to migrate an endpoint that calls an external API.
This section in its entirety is still very early, probably the earliest I've pushed a section up for review. I'm not tightly committed to any part of it. If you think we really should introduce tags here, I don't think it would be impossible to do so. I do think we'll have to cut something else to make room for them, though, and it might have to be services.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally understand, and honestly I don't want to impose my opinion too much on the direction you take here.
My only advice would be that if you want to avoid introducing Data.TaggedError
, etc., maybe just add a _tag
property or something to your custom error type and do another one of those "this is important but we'll discuss it later" things. Just to ensure you have a discriminator for the type in place, and you don't create an unintentional footgun with multiple error types that are assignable to one another.
Type
Description
Currently still a work in progress.