-
Notifications
You must be signed in to change notification settings - Fork 374
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
Add tapErrorZIO and tapErrorCauseZIO to Route and Routes #2755
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## main #2755 +/- ##
==========================================
- Coverage 64.42% 64.34% -0.08%
==========================================
Files 148 148
Lines 8668 8678 +10
Branches 1589 1545 -44
==========================================
Hits 5584 5584
- Misses 3084 3094 +10 ☔ View full report in Codecov by Sentry. |
self match { | ||
case Provided(route, env) => Provided(route.tapErrorCauseZIO(f), env) | ||
case Augmented(route, aspect) => Augmented(route.tapErrorCauseZIO(f), aspect) | ||
case Handled(routePattern, handler, location) => Handled(routePattern, handler, location) |
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.
iirc, ensures handled that the typed error is handled. But a cause (defect) might still happen. So I think there should be a tap on the handler here.
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.
That doesn't seem to work as the Handled.handler
's failure type is Response
whereas f
's failure type is Err
which is not necessarily a Response
.
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.
You can catch the Cause[Err]
, and if it contains an Err
, then you rethrow it. But if it's really a Cause[Nothing]
, i.e. pure defect, without an Err
inside it, then you can allow that to be caught by f
, since f
can handle those (Cause[Nothing]
is a subtype of Cause[Err]
).
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.
@tjarvstrand This does need to be fixed, and then will be good to merge!
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.
Sorry, busy week! :/
I've been struggling a bit with the error case of f
which, unless I'm mistaken, must be a Response
. Does something like this make sense?
/**
* Effectfully peeks at the unhandled failure cause of this Route.
*/
final def tapErrorCauseZIO[Err1 >: Err](
f: Cause[Err] => ZIO[Any, Err1, Any],
)(implicit trace: Trace): Route[Env, Err1] =
self match {
case Provided(route, env) => Provided(route.tapErrorCauseZIO(f), env)
case Augmented(route, aspect) => Augmented(route.tapErrorCauseZIO(f), aspect)
case Handled(routePattern, handler, location) =>
Handled(
routePattern,
handler.tapErrorCauseZIO {
case cause0: Cause[Err] => f(cause0).catchAllCause(cause => ZIO.fail(Response.fromCause(cause)))
case _ => ZIO.unit
},
location,
)
case Unhandled(rpm, handler, zippable, location) =>
Unhandled(rpm, handler.tapErrorCauseZIO(f), zippable, location)
}
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.
When you get cause0
, do errorOrCause
, and if it's an error, you have to refail that, but if it's a Cause[Nothing]
, you can feed it to f
.
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.
Maybe I'm slow, but shouldn't handler.tapErrorCauseZIO
leave the error channel of the original effect intact so that I don't have to refail it?
Not trying to be difficult. I just want to make sure I understand what's going on.
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.
Ah yes, of course! Forgot the point of this function, which is tapping not recovering. 🤦♂️
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.
👍
Tried to move too fast and now the build is failing. I'll have another look at this as soon as I can.
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'm afraid I think I'm in need of some assistance.
There are warnings in Scala 3 (which I have actually not used yet):
[warn] -- Unchecked Warning: /Users/tjarvstrand/src/zio-http/zio-http/shared/src/main/scala/zio/http/Route.scala:134:17
[warn] 134 | case err: Fail[Err] => f(err.value).catchAllCause(cause => ZIO.fail(Response.fromCause(cause)))
[warn] | ^
[warn] |the type test for zio.Cause.Fail[Err] cannot be checked at runtime because its type arguments can't be determined from zio.Cause[zio.http.Response]
I'm assuming this is related to type erasure somehow, but I'm not sure why there's no warning in Scala 2. Any tips on how to proceed?
006b320
to
1194943
Compare
Useful for things like error logging or reporting to external services such as Sentry.