-
Notifications
You must be signed in to change notification settings - Fork 736
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
Refactor Requester
into multiple smaller classes
#697
Conversation
62eb088
to
7591215
Compare
|
||
/** | ||
* A builder pattern for making HTTP call and parsing its output. | ||
* A thin helper for {@link GitHubRequest.Builder} that includes {@link GitHubClient}. |
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.
This is the really the summary of this change - a refactoring from GitHub
and Requester
being monolithic centers of work to having the work split between GitHubClient
, GitHubRequest
, GitHubRequest.Builder
, GitHubResponse
, GitHubResponse.ResponseInfo
, and various *Iterables
and *Iterators
. Requester
still remains as a thin helper and GitHub
is still large but is mostly customer facing methods with GitHubClient
handling internals.
Requester
into multiple smaller classes
7591215
to
90489e4
Compare
*/ | ||
@Nonnull | ||
static URL getApiURL(String apiUrl, String tailApiUrl) throws MalformedURLException { | ||
if (tailApiUrl.startsWith("/")) { |
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.
Is there a circumstance where tailApiUrl
will not start with a "/"? I didn't see any tests in GitHubConnectionTest
that behave this way, so just wondering how we'd run up against this, and what it looks like when we do.
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.
Good question. There are a small number of cases where the API returns a URL that is then used for other things.
Also, for paginated result, the full url for the next page is provided in the Link
header , so when we call getApiURL
we want to use that url, whatever it happens to be.
I don't love this lack of clarity, but I didn't feel confident that I had tests for all cases where that URL didn't start with /
, so I've kept the behavior where this method just handles it. That said, I should change L77 to use setRawUrl
. Thanks!
// by convention Java constant names are upper cases, but github uses | ||
// lower-case constants. GitHub also uses '-', which in Java we always | ||
// replace with '_' | ||
return en.toString().toLowerCase(Locale.ENGLISH).replace('_', '-'); |
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.
Comments like this are super helpful. :)
Are there other places where we might need to do such a conversion? I only see one instance of replace('_', '-')
in the whole plugin. Might be fine, it just surprised me that there aren't more.
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.
The other places are mostly done automatically by Jackson.
Hm, the toLowerCase
may not be needed due to line 88. And line 89 means that, given a field like create_date
, Jackson will automatically look for a field with the name createdDate
and then fall back to create_date
if it doesn't find one.
However, this setting was only added recently, there are still a lot private fields with underscores in them.
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.
Opened #700 to clean this up.
} | ||
return (B) this; | ||
} | ||
|
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.
This is a somewhat arbitrary place for me to put this question, but it's as good as any. There are a lot of with(thing, thing)
methods here with different parameters. Why is that? I mean, I'm sure there's a perfectly good reason for it, I just am having trouble putting it together on my own.
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.
I'm not sure. These were here when I arrived. I'm not sure it they are still all needed, per se. I think I tried to remove them at one point and started getting errors ... but I don't remember now.
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.
Opened #699 to come back to this.
|
||
current = base.next(); | ||
wrapUp(current); | ||
if ((current == null || current.length <= pos) && base.hasNext()) { |
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.
Not really specific to this PR, but, I could use a quick overview of the relationships between current
, pos
, and base
. I thought I had it figured out for a minute but I guess I don't.
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.
I can pick better names for these and give them a little more commenting.
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.
Mostly this is me making sure I actually understand what's going on in here. :)
From my discussion of this with @kshultzCB - This is very much a refactor with no significant performance changes. |
@kshultzCB Thanks! Great feedback. Made updates to address and filed a couple of issue to track future work. |
We don't need two layers of PageIterator just to get the final response. Also made iterators thread-safe. And added more detailed comments.
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.
Things are getting pretty desperate when I'm left to nitpick at comments. :) I love the additional clarity here, especially in PagedIterator
, it's super helpful.
* If {@link #next} is not {@code null}, no further action is need. If {@link #next} is {@code null} and | ||
* {@link #nextRequest} is {@code null}, there are no more pages to fetch. |
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.
Pedantic documentation hat, engage: replace "need" with "needed."
* {@link #nextRequest} is {@code null}, there are no more pages to fetch. | ||
* </p> | ||
* <p> | ||
* Otherwise, a new response page is fetched using {@link #nextRequest}. The response is then check to see if there |
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.
Pedantic documentation hat once more: replace "check" with "checked."
These were not synchronized before we should leave them fix this in a future change
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.
+1 to leaving this as a refactor, and tabling the thread-safe idea for a different time.
Description
Refactoring from
GitHub
andRequester
being monolithic centers of work to having the work split among smaller classes.GitHub
is still the root of interactions, but holds a reference to aGitHubClient
that has all the connection and communication.Requester
still remains as a thin helper that will be removed in a future change.Improvements
HttpUrlConnection
interactions inGitHubHttpUrlConnectionClient
PagedIterable
is the sole entry point for retrieval of all item arrays, lists, or iterables.*Iterable
and*Iterator
classes encapsulate all the work done to retrieve pages of itemsThis change encapsulates most of the dependencies on
HttpUrlConnection
as much as possible, to allow moving to other more modern frameworks at some point. This also separates the concerns more clearly.There's still some work to be done here, but this change is more than enough for now.