api: refactor the low level cmd/src GraphQL functionality into a new api package #258
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
This PR moves the
apiRequesttype and its associated functions incmd/srcout into a newinternal/apipackage.Why?
I'm working on https://github.com/sourcegraph/sourcegraph/issues/12333, and want to keep as much of the business logic of interacting with the campaign backend out of
cmd/srcas possible: ideally, I wantcmd/srcto be the "view" layer — handling flags and managing output — and haveinternal/campaignsbe the service layer that implements all the actual logic. I believe this separation will allow for better testing and code quality. (And, if I'm honest, this is also partly because I was starting to have to be very careful about prefixing identifiers incmd/src, and that was making for seriously unwieldy type and variable names.)In order to do this,
internal/campaignshas to be able to issue GraphQL requests. Just makingapiRequestand friends public doesn't totally address this: it sets up potential circular dependencies, andapiRequestis tied to global state via its use ofcfg, which makes it hard to reason about, and to mock for future testing purposes as I work on https://github.com/sourcegraph/sourcegraph/issues/12333.What's changed
I haven't significantly changed the internals of issuing GraphQL requests: the code in
api.Request's methods will look extremely familiar to anyone who's looked atapiRequest.do()previously.There are a handful of specific changes that I think are improvements, but are open to discussion (just like everything else, of course):
There's no longer a concept of a
donefield: the requestDomethods instead return abool, errortuple that indicate whether the result was filled out (with the case where it's not being when-get-curlis enabled). This means that functions that make GraphQL requests that previously useddoneare now written in a more top-down, procedural way, which I think is easier to read, but at the expense of a slightly more complicatedifstatement to check iferr != nil || !okin many cases.dontUnpackErrorshas been replaced with a parallel set ofDomethods: one does the normal default unwrapping of the GraphQL response, and one doesn't. I think this is clearer, but this is certainly a matter of taste.Contexts are now propagated consistently through the API package, although I haven't done any work to really take advantage of that thus far.
What does this allow in the future
We can now test the API implementation more easily than when it lived in
cmd/src, since it no longer relies on global state.As
ClientandRequestare interfaces, we can easily mock GraphQL requests in other tests withinsrc-cli; I expect to add such a helper as I work on https://github.com/sourcegraph/sourcegraph/issues/12333.This gives us some options for figuring out what context behaviour we think should be the default when executing
srccommands: we could now start looking at providing consistent options for timeouts and signal handling.cc: @chrispine