Retry functionality not working for errors returned by server
The recovering function of the retry package only considers to retry an action when it throws an exception.
In Client.recoverFrom, certain server-generated errors (like ReadTimeout) are marked as recoverable. But these server-generated errors will never be thrown as an exception there, rather they will just be returned as an RsError Response, which will be thrown by a caller (like executeWithPrepare for prepared queries or runQ for QueryStrings).
I assume this is not by design, as the recoverFrom function explicitly mentions these errors.
This can be fixed in several ways and I'm not sure what's the preferred approach.
a) The least we can do is throw errors in the recovering do block of Client.mkRequest and turn exceptions into values again afterwards in this function. This is a local fix which shouldn't break any other behavior.
b) The fact that error responses are turned into exceptions in several functions, residing on different layers in the code, seem like an opportunity for simplification. mkRequest only seems to be used for requests that expect an RsResult. According to the CQL spec, these requests may only return an RsResult or RsError response. Hence, mkRequest could return a Result k a b instead of a Response k a b and throw an exception for errors (or UnexpectedResponse for any other response types). If we do that, we can reduce the number of checks and throwMs in the code, and the type system will ensure we only check for the wrong response type once. This will touch quite a bit more code and may turns some case statements into exception handling instead, which may not be desired.
There's probably other solutions between these extremes and I could be missing something. What's your opinion on this?