Skip to content
This repository was archived by the owner on Jan 8, 2024. It is now read-only.

Add the ability to instrument a graphql request#8

Open
edersonmf wants to merge 2 commits into
masterfrom
ederson/refactor
Open

Add the ability to instrument a graphql request#8
edersonmf wants to merge 2 commits into
masterfrom
ederson/refactor

Conversation

@edersonmf

Copy link
Copy Markdown

A Chain of Responsibility pattern is employed to allow
callers adding custom instrumentation targeting graphql
request and response objects.
A couple good use cases for this are request logging,
caching, and certain kinds of auth (e.g. bearer token renewal).

In order to proceed of this kind of support a small refactor
was required. So, there are somee changes that impact directly
the previous structure of this module.

Comment thread chain.go Outdated
Comment on lines +57 to +71
ResponseParser interface {
parseResponse() (*GraphResponse, Error)
}

Action interface {
call() ResponseParser
}

Validated interface {
createRequest() Action
}

Init interface {
validate() Validated
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need all these different interfaces for defining private methods from a private struct? Defining public interfaces with private methods seems a bit off to me.

Maybe keeping this as different interfaces, but having the methods public and their implementations separated could be a better approach? This way we could allow the users of our lib to only substitute a part of the chain (e.g. they could annotate one of the steps with a custom error handler, counter, etc) instead of requiring them to re-implement the whole lib.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point and I was wondering that as well.
Let me submit another version of it. Let me know your thoughts.
Thanks!

A Chain of Responsibility pattern is employed to allow
callers adding custom instrumentation targeting graphql
request and response objects.
A couple good use cases for this are request logging,
caching, and certain kinds of auth (e.g. bearer token renewal).

In order to proceed of this kind of support a small refactor
was required. So, there are somee changes that impact directly
the previous structure of this module.
Comment thread chain.go
c.logf("<< %s", buf.String())
resp := c.operation.ResponseBodyAs()
var gr *GraphResponse
if c.operation.IsMutation() {

@GiancarloJung GiancarloJung Feb 15, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created the Mutation struct to make the result.Successful field control if the request was of the Request (query) or Mutation type and based on the type of the request this flow decided what flow was gonna be used. If you think is easier to control this by a boolean flag we could also remove some of that logic and merge the Operation and Request interfaces and make the naming simpler, wdyt?

Comment thread request.go
)

// Request is a GraphQL request.
// queryOperation is a GraphQL defaultRequest.

@GiancarloJung GiancarloJung Feb 15, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// queryOperation is a GraphQL defaultRequest.

✂️

Comment thread request.go
Comment on lines +53 to +55
)
// Deprecated: in favor of NewGraphOperation
func NewRequest(q string) Operation {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
)
// Deprecated: in favor of NewGraphOperation
func NewRequest(q string) Operation {
)
// Deprecated: in favor of NewGraphOperation
func NewRequest(q string) Operation {

Comment thread request.go
Mutation struct {
Req *Req
// queryOperation is the regular graphQL query operation
queryOperation struct {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A request could be either a query or a mutation if struct can be both my suggestion is to name it defaultOperation, the field queryName could also be just name. wdyt?

@GiancarloJung GiancarloJung left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The refactor looks great, and I like the chain principle, could you also provide some examples on how to use its benefits on some tests? I also got a little confused between the names on the request.go file between the interfaces and the structs, but I left a comment about the operation that could make this simpler =]

Comment thread chain.go
Comment on lines +60 to +61
// client.log = func(s string) { log.Println(s) }
log func(s string)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this have a setter function? I'm not sure we could do this since this is a private field 🤔

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants