-
Notifications
You must be signed in to change notification settings - Fork 112
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
Evaluate Style Guide #53
Comments
Especially on user-facing types, use the familar request/response terminology instead of sender/receiver. See #53.
It's Go - every read from/write to the network can hang until the request times out. 🤷🏽♂️ I discussed this on #26 in the context of streams, but it's a general problem. When working on $PROXY at $PREVIOUS_TAXI_COMPANY, we used the
|
Can't move it to a different package from the We could move a bunch of stuff into an exported subpackage (e.g., |
Future-proofing concerns are 100% valid. Let's discuss those in person and document results here. |
I'd disagree with this one, I don't think it's in line with our codebase |
Especially on user-facing types, use the familar request/response terminology instead of sender/receiver. See #53.
Pending your API review down the road, we decided to copy the standard lib and go with |
@amckinney and I discussed the future compatibility issues above.
|
As discussed in #53, we're dropping the Simple/Full nomenclature. For clients, we keep the `NewPingServiceClient` function, which returns the `PingServiceClient` struct. The two client interfaces change to `WrappedPingServiceClient` (simple) and `UnwrappedPingServiceClient` (full-featured). For handlers, we drop the simplified interface completely - it was purely for documentation, and wasn't ever referenced. Instead, we name the server-side interface `PingService`, and we export the adaptive constructor as `NewPingService`. We un-export the strongly-typed constructor. The server changes seem like they'd greatly reduce safety, but that's not the case. Today, grpc-go servers almost always embed `UnimplementedPingServiceServer`. Even if the actual method implementations have a typo, the compiler will still be happy. With our system, users get more flexibility and the same guarantees in practice.
As discussed in #53, we're dropping the Simple/Full nomenclature. For clients, we keep the `NewPingServiceClient` function, which returns the `PingServiceClient` struct. The two client interfaces change to `WrappedPingServiceClient` (simple) and `UnwrappedPingServiceClient` (full-featured). For handlers, we drop the simplified interface completely - it was purely for documentation, and wasn't ever referenced. Instead, we name the server-side interface `PingService`, and we export the adaptive constructor as `NewPingService`. We un-export the strongly-typed constructor. The server changes seem like they'd greatly reduce safety, but that's not the case. Today, grpc-go servers almost always embed `UnimplementedPingServiceServer`. Even if the actual method implementations have a typo, the compiler will still be happy. With our system, users get more flexibility and the same guarantees in practice.
As discussed in #53, we're dropping the Simple/Full nomenclature. For clients, we keep the `NewPingServiceClient` function, which returns the `PingServiceClient` struct. The two client interfaces change to `WrappedPingServiceClient` (simple) and `UnwrappedPingServiceClient` (full-featured). For handlers, we drop the simplified interface completely - it was purely for documentation, and wasn't ever referenced. Instead, we name the server-side interface `PingService`, and we export the adaptive constructor as `NewPingService`. We un-export the strongly-typed constructor. The server changes seem like they'd greatly reduce safety, but that's not the case. Today, grpc-go servers almost always embed `UnimplementedPingServiceServer`. Even if the actual method implementations have a typo, the compiler will still be happy. With our system, users get more flexibility and the same guarantees in practice.
Especially on user-facing types, use the familar request/response terminology instead of sender/receiver. See #53.
As discussed in #53, we're dropping the Simple/Full nomenclature. For clients, we keep the `NewPingServiceClient` function, which returns the `PingServiceClient` struct. The two client interfaces change to `WrappedPingServiceClient` (simple) and `UnwrappedPingServiceClient` (full-featured). For handlers, we drop the simplified interface completely - it was purely for documentation, and wasn't ever referenced. Instead, we name the server-side interface `PingService`, and we export the adaptive constructor as `NewPingService`. We un-export the strongly-typed constructor. The server changes seem like they'd greatly reduce safety, but that's not the case. Today, grpc-go servers almost always embed `UnimplementedPingServiceServer`. Even if the actual method implementations have a typo, the compiler will still be happy. With our system, users get more flexibility and the same guarantees in practice.
Especially on user-facing types, use the familar request/response terminology instead of sender/receiver. See #53.
As discussed in #53, we're dropping the Simple/Full nomenclature. For clients, we keep the `NewPingServiceClient` function, which returns the `PingServiceClient` struct. The two client interfaces change to `WrappedPingServiceClient` (simple) and `UnwrappedPingServiceClient` (full-featured). For handlers, we drop the simplified interface completely - it was purely for documentation, and wasn't ever referenced. Instead, we name the server-side interface `PingService`, and we export the adaptive constructor as `NewPingService`. We un-export the strongly-typed constructor. The server changes seem like they'd greatly reduce safety, but that's not the case. Today, grpc-go servers almost always embed `UnimplementedPingServiceServer`. Even if the actual method implementations have a typo, the compiler will still be happy. With our system, users get more flexibility and the same guarantees in practice.
Package Structure
codec
andcompress
packages are split out so that we can more easily add a separate package for theProtocol
abstraction (e.g. gRPC, gRPC-Web, Connect) without introducing an import cycle.clientstream
andhandlerstream
packages are split out so that we can tidy up names for these types. Otherwise, you'd have names likeNewClientClientStream
(the client's view of a client streaming endpoint).compress.Gzip
instead ofcompress.GzipCompressor
.compress/gzip.Compressor
.Method Naming
ReceivedHeader
method to distinguish itself from the request headers. Should we instead just name thisResponseHeader
for clarity?RequestHeader
andResponseHeader
.WrappedPingClient
andUnwrappedPingClient
interfaces.PingClient
is reserved for the type that users interact with.PingService
(acts upon generic types), andNewPingService
(acts uponany
). Comments are left in-line to describe how to implement the simple, non-generic method signatures.Future Proofing
Codec
andCompressor
) are propagated through theclientCfg
and into theprotocol
abstraction via a catch-allprotocolClientParams
. If we eventually plan to export theprotocol
abstraction and include it as aClientOption
, the relationship here is fuzzy.protocol
that doesn't interact with all of theprotocolClientParams
types - is it a no-op, an error, or a silent failure?protocol
individually to clear these relationships up, but we end up with some more repetition (i.e. we need to repeat the same options for similar protocols like gRPC and gRPC-Web). For example, each of the gRPC and gRPC-Webprotocols
would have aCodec
option.connect-api
branch, we were able to get around this because the protocols were separate client implementations, and they could each individually own what options they exposed (e.g. here).proto.Any
, and Akshay had some ideas around this - we could rename the methods to includeAny
so it leaves room for us to add other types later (e.g.AddAnyDetail
). The abstraction violation between the pluggableCodec
and theproto.Any
sucks, but I know we're at mercy to the gRPC protocol here.1.0 Features
health
andreflection
packages are valuable, but they aren't really necessary to begin with. We should consider whether or not these packages should exist in a separate repository (similar to gRPC middleware repositories).RegistrationName
in the generated code. If we were to drop this support to begin with, we'd need to reintroduce this as aHandlerOption
later, and that's tied to theconnect
library itself. It's not immediately obvious how this would work.health
andreflection
are staying where they are. We need these features for easy gRPC user adoption. To be clear,health
is non-optional.reflection
is a huge quality of life improvement and its (nearly) part of the gRPC specification at this point.connect.MaxHeaderBytes
is kinda nice, but doesn't feel necessary and is prone to change across different protocols.connect.ReceiveResponse
be in aninternal
package? It's only used twice and otherwise distracts from the API that users ought to interact with. This might already be your plan based on the conversations we had earlier about the user-facing API and connect internals.ReceiveRequest
needs to be exported for the generated code, so I can see an argument to export it for symmetry.IsValidHeaderKey
andIsValidHeaderValue
.Implementation Details
connect-api
branch, I left a note for myself about whether or not thediscard
helper function can hang forever (e.g.discard(cs.response.Body)
). This might have happened when I introduced the gRPC testing suite, but I can't recall. We need to make sure this can't happen.http.Response.Body
to completion to reuse the connection. This is also just an implementation detail, so it's not blocking regardless.The text was updated successfully, but these errors were encountered: