-
Notifications
You must be signed in to change notification settings - Fork 5
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
Error policies, huge refactors, and a lot of other breaking changes #480
Conversation
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.
Nice implementation! Thanks for taking care of this.
@@ -3,7 +3,7 @@ | |||
|
|||
package clue.data | |||
|
|||
import io.circe.Json | |||
// import io.circe.Json |
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.
Commented import
} | ||
|
||
protected def subscribeInternal[D: Decoder]( | ||
// def subscribe_( |
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.
Commented code.
@@ -118,16 +127,16 @@ object Demo extends IOApp.Simple { | |||
withLogger[IO].use { implicit logger => | |||
withStreamingClient[IO].use { implicit client => | |||
for { | |||
result <- client.request(Query) | |||
result <- client.request(Query) // (ErrorPolicyInfo.RaiseAlwaysInfo) |
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.
Commented code
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.
A pass of comments/questions. I'm a bit confused about the Sync
upgrade.
} | ||
|
||
sealed trait ErrorPolicyProcessor[D, R] { | ||
def process[F[_]: Sync](result: GraphQLCombinedResponse[D]): F[R] |
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.
Why does this need Sync
? Can the delay
s below just be pure, in which case ApplicativeThrow
is all that is needed?
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 sounds right, good catch too.
class ConnectionException() extends GraphQLException("Could not establish connection") | ||
case object ConnectionException extends GraphQLException("Could not establish connection") | ||
|
||
class DisconnectedException() extends GraphQLException("Connection was closed") | ||
case object DisconnectedException extends GraphQLException("Connection was closed") |
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.
Exception
s that are case object
s can extend scala.util.control.NoStackTrace
since their stack trace would be confusing since it's not related to the 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.
Ah good catch, maybe they should't be objects then, stack traces may be useful.
This PR address #475, #476 and #477, and partially #341.
Regarding the handling of the case when both
data
anderrors
(#476), the solution could easily be extended to address (optionally) not stopping a subscription on error (#475).The solution I sought aimed to allow
data
+errors
handling, but allow users to ignore this cases, raising all errors if desired and simplifying the interface when the invoked service is known not to return these cases. I think it's simpler to deal with anF[Data]
than with anF[Ior[GraphQLErrors, Data]]
.The approach taken was to add a new
ErrorPolicy
implicit parameter to all queries and subscriptions. This determines how to handle errors and therefore the return types of queries and subscriptions.Return types are determined via path-dependent types. This results in the caveat that the
ErrorPolicy
must be statically known at the call sites for the compiler to be able to solve the return type into a useful type.For example,
ErrorPolicy.RaiseAlways
determines that a query return type isF[Data]
. The compiler won't be able to solve this if theErrorPolicy
was passed as a parameter to the a method from where the query is made. In practice, this means that we can have a global error policy and import it everywhere queries and subscriptions are made (or pass it explicitly).Regarding extensions (#477): they are now supported in the protocol, paving the way for clients that makes use of it.
Regarding spec compliance (#341): I've reached the conclusion that's it's neither easy nor trivial to pursue modeling the base GraphQL specification. We should still seek to adhere to the HTTP and WS specs. There are number of changes towards that goal, but there's still work to do, especially untangling the WS protocol from the connection and reconnection logic.
A number of other refactors were made to better adjust types.
Changes to documentation were done by "search and replace", the documentation is still heavily outdated.
The
Demo
was updated and now it runs again (at least as long as we have the oldlucuma-odb
development server up).