Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upProposal: cleaning up exceptions #139
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
tsuna
Feb 26, 2013
Contributor
I think this would be a nice improvement. Do you expect everything to be a Failure or will there be more case classes? I'm curious also as to whether it's better to put retryable and interrupted directly in Failure or to compose traits?
I like the sources, to essentially help tack on arbitrary annotations on exceptions/failures, but it also means that recipients of the exception will have to sort of inspect the sources for known keys they may care about, and because these are strings they may change and you wouldn't know, etc. Is there a way to retain this general purpose annotation mechanism yet provide a statically typed mechanism for important annotations that we expect to always be there (for instance the remote address of a socket from which an exception originated)?
|
I think this would be a nice improvement. Do you expect everything to be a I like the |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
bmatheny
Feb 26, 2013
Contributor
Like @tsuna I also think this is a nice improvement. My feedback would be to consider using a config class (like you do for builders and such) along with Failure. It seems like the list of options could grow beyond retryable and interrupted, and not having to change existing code to support that growth would be nice.
|
Like @tsuna I also think this is a nice improvement. My feedback would be to consider using a config class (like you do for builders and such) along with Failure. It seems like the list of options could grow beyond retryable and interrupted, and not having to change existing code to support that growth would be nice. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mariusae
Feb 26, 2013
Contributor
I like the sources, to essentially help tack on arbitrary annotations on exceptions/failures, but it also means that recipients of the exception will have to sort of inspect the sources for known keys they may care about, and because these are strings they may change and you wouldn't know, etc. Is there a way to retain this general purpose annotation mechanism yet provide a statically typed mechanism for important annotations that we expect to always be there (for instance the remote address of a socket from which an exception originated)?
I think that programmatic inspection will be rare; these will mostly be used for exception reporting and stats. In these cases, we can simply treat some names as special (remoteAddress, clientName) to recover useful provenance information.
I think that programmatic inspection will be rare; these will mostly be used for exception reporting and stats. In these cases, we can simply treat some names as special (remoteAddress, clientName) to recover useful provenance information. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mariusae
Feb 26, 2013
Contributor
Like @tsuna I also think this is a nice improvement. My feedback would be to consider using a config class (like you do for builders and such) along with Failure. It seems like the list of options could grow beyond retryable and interrupted, and not having to change existing code to support that growth would be nice.
Agreed: I may just make the case class constructor private, to enforce using the "builder style".
Agreed: I may just make the case class constructor private, to enforce using the "builder style". |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mariusae
Feb 26, 2013
Contributor
I think this would be a nice improvement. Do you expect everything to be a Failure or will there be more case classes? I'm curious also as to whether it's better to put retryable and interrupted directly in Failure or to compose traits?
The main reason for preferring a case class over mixins in this case is that it allows us to treat exceptions like a transformable value, without the need to resort to reflection or code generation tricks. This allows us to push sources and other annotations like "retryable" without altering the semantics of the exceptions:
service(req) rescue {
case f: Failure =>
Future.exception(f.withSource("mysource", blah))
}
The main reason for preferring a case class over mixins in this case is that it allows us to treat exceptions like a transformable value, without the need to resort to reflection or code generation tricks. This allows us to push sources and other annotations like "retryable" without altering the semantics of the exceptions:
|
added a commit
that referenced
this issue
Apr 17, 2014
added a commit
to suncelesta/finagle
that referenced
this issue
Feb 19, 2015
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mosesn
May 27, 2016
Contributor
This was implemented and rolled out a long time ago. We're migrating to Failure lazily. cc @roanta
|
This was implemented and rolled out a long time ago. We're migrating to Failure lazily. cc @roanta |
mariusae commentedFeb 26, 2013
The current exception hierarchy used by finagle has several problems:
WriteExceptionwhere applicable. Failing to do so leaves retry opportunities on the table;And finally, a point of terminology: they aren't really exceptions — these aren't exceptional events; many operations fail regularly — they are failures.
I propose to change exceptions around a bit to:
¶
We define a toplevel exception as a case class:
It does not have any stack traces by default, and maintains a set of mutually exclusive labels (
retryable,interrupted). Furthermore, it has a number of sources — key-value pairs. These are meant to reveal the provenance of the exception itself. A simple example is for the client to store the remote address of the host to which it was attempting to send a request("remoteAddress", inetSocketAddress)A number of convenience constructors and matchers are also provided, for example:
So that exceptions can be constructed and taken apart easily:
This has some neat properties:
ServiceFactoryexception, soFactoryToServicecan simplyrescueexceptions, returningexc.withRetryable(true).SocketAddressof the host from which the failure originated. The same is true with client names: at the top of theServicestack, we can insert a filter sourcing the name of that client.