You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It's possible to just store the underlying OpenFgaApi as a variable and use that, but that also requires a level of indirection that is unecessary. Point is - the APIClient should have the API methods attached to it directly, and this is best achieved by embedding the underlying interface.
typeAPIClientstruct {
...OpenFgaApiOpenFgaApi
}
changes to
typeAPIClientstruct {
...OpenFgaApi
}
Make the API surface more idiomatic, streamlined, and RPC style
The Go SDK is currently very verbose and not idiomatic. Building a Go integration with the OpenFGA Go SDK involved non-standard Go idioms, and this makes consuming the libraries API surface more challenging than other Go SDKs for other APIs.
Our API is an RPC style API, and most Go clients that are idiomatic define client interfaces with request inputs and response outputs like so:
In fact, if you look at the Go gRPC generated client stubs this is what generated code like this gets produced as. I acknowledge that our HTTP API defines custom mappings to our RPC API, and so we'd need to generate this structure off of the OpenAPI definition instead of inheriting the default HTTP-->gRPC transcoding mapping, but it would be nice to stay within this idiom.
Drop the HTTP response param from the return list
Our code currently returns the raw HTTP response as part of the method signatures. I suppose this isn't necessarily a bad thing, but it's definitely a Go idiom I have not particularly seen that used in the wild. I would also argue that exposing the raw HTTP response is counter productive to the Go SDK in the first place. The SDK is supposed to be abstracting the underlying HTTP API, and this makes it possible for client applications to build integrations they depend on with the raw HTTP API. That makes this part of the API surface another thing we have to maintain compatibility with even though the SDK is purposefully trying to abstract it.
I recommend we drop the HTTP response object from the response altogether and depend upon the error usage pattern to appropriately capture the error semantics of the underlying HTTP response behavior. Lots of Go API client libs define an APIError structure and it implements the error interface, and they return this with the status and any underlying error message (if status is non 200). Also, if you need access to the Headers (for rate limiting for example), then it's also a common Go idiom to embed those in the response object.
varclient openfga.OpenFgaApi// current designreadResp, httpResp, err:=client.Read(context.Background()).Body(...).Execute()
ifhttpResp.StatusCode!=http.StatusOK {
// handle error behavior
}
ifremaining:=httpResp.Header.Get("x-ratelimit-remaining"); remaining>1 {
// do next request, for example
}
// recommended designtypeAPIErrorStatusint// enum set of codes for consummable API errorstypeAPIErrorstruct {
...// other metadata as neededStatusAPIErrorStatusMessagestring
}
typeAPIResponse[Tany] interface {
GetResponse() (T, error)
GetHeaders http.Header
}
readResp, err:=client.Read(context.Background(), &openfga.ReadRequest{...})
iferr!=nil {
iferrors.Is(err, openfga.APIError) {
// handle specific `APIErrorStatus`
}
}
ifremaining:=readResp.GetHeaders()["x-ratelimit-remaining"]; remaining>1 {
// do next request, for example
}
A great example of a widely used Go SDK that follows some common Go idioms and is very easy to consume is the Stripe Go SDK (https://github.com/stripe/stripe-go). There are examples of this ^^ in that SDK.
The text was updated successfully, but these errors were encountered:
Reduce the stutter of client invocations
The underlying
OpenFgaApi
client interface should be embedded. For example,It's possible to just store the underlying
OpenFgaApi
as a variable and use that, but that also requires a level of indirection that is unecessary. Point is - theAPIClient
should have the API methods attached to it directly, and this is best achieved by embedding the underlying interface.changes to
Make the API surface more idiomatic, streamlined, and RPC style
The Go SDK is currently very verbose and not idiomatic. Building a Go integration with the OpenFGA Go SDK involved non-standard Go idioms, and this makes consuming the libraries API surface more challenging than other Go SDKs for other APIs.
Our API is an RPC style API, and most Go clients that are idiomatic define client interfaces with request inputs and response outputs like so:
In fact, if you look at the Go gRPC generated client stubs this is what generated code like this gets produced as. I acknowledge that our HTTP API defines custom mappings to our RPC API, and so we'd need to generate this structure off of the OpenAPI definition instead of inheriting the default HTTP-->gRPC transcoding mapping, but it would be nice to stay within this idiom.
For example
Drop the HTTP response param from the return list
Our code currently returns the raw HTTP response as part of the method signatures. I suppose this isn't necessarily a bad thing, but it's definitely a Go idiom I have not particularly seen that used in the wild. I would also argue that exposing the raw HTTP response is counter productive to the Go SDK in the first place. The SDK is supposed to be abstracting the underlying HTTP API, and this makes it possible for client applications to build integrations they depend on with the raw HTTP API. That makes this part of the API surface another thing we have to maintain compatibility with even though the SDK is purposefully trying to abstract it.
I recommend we drop the HTTP response object from the response altogether and depend upon the
error
usage pattern to appropriately capture the error semantics of the underlying HTTP response behavior. Lots of Go API client libs define anAPIError
structure and it implements theerror
interface, and they return this with the status and any underlying error message (if status is non 200). Also, if you need access to the Headers (for rate limiting for example), then it's also a common Go idiom to embed those in the response object.A great example of a widely used Go SDK that follows some common Go idioms and is very easy to consume is the Stripe Go SDK (https://github.com/stripe/stripe-go). There are examples of this ^^ in that SDK.
The text was updated successfully, but these errors were encountered: