Skip to content
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

Access to the last ApiInfo object #855

Merged
merged 11 commits into from
Aug 28, 2015
Merged

Access to the last ApiInfo object #855

merged 11 commits into from
Aug 28, 2015

Conversation

Red-Folder
Copy link
Contributor

As discussed in issue #504

Allows the user to get the contents of the last ApiInfo (so last Api call). Provided as a property of GitHubClient which calls a property of Connection then a property of HttpClientAdapter.

The most obvious use for it is to check the current rate limit without making a separate API call.

Two concerns for me:

  • Can't put a test in for the HttpClientAdapter. The underlying HttpClient is concrete and the send method is not virtual so can be substituted. Could abstract the HttpClient (interface and wrapper) - this would help to put more testing into for the HttpClientAdapter (currently quite light).
  • Must be a better design than having to implement a property through every layer

Thanks

/// <summary>
/// Provides a property for the Last recorded API infomation
/// </summary>
public interface IApiInfo
Copy link
Contributor

Choose a reason for hiding this comment

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

This sounds like an interface for the ApiInfo itself. What about IApiInfoProvider, it seems to be more in line with the comments as well?

@khellang
Copy link
Contributor

@Red-Folder I sent you a PR at Red-Folder#1, I still haven't addressed the threading issue, though.

@Red-Folder
Copy link
Contributor Author

@khellang Great stuff. I'll pull in over the weekend

@Red-Folder
Copy link
Contributor Author

Can anyone recommend a good Api call to use for the integration test?

I'm current using the Rate Limit call - but this doesn't include links, oauth scope, accepted oauth scope, & etag,in the ApiInfo. I'd like an Api call which will populate all of these for testing

@shiftkey
Copy link
Member

shiftkey commented Aug 2, 2015

@Red-Folder I'd suggest a couple of calls:

  • ETag can be found by creating a new repository - that should be easy enough
  • Links are a bit trickier (because most of our existing APIs are going to follow them as part of pagination). You might be able to check for the last value after the pagination is done - so something like "list your repos" might work for you.
  • X-OAuth-Scopes and X-Accepted-OAuth-Scopes require the caller to be configured with token authentication - that depends on the OCTOKIT_OAUTHTOKEN environment variable being set, but the caller might not have this setup.

}
private ApiInfo _lastApiInfo;
private readonly object LastApiInfoLocker = new object();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@khellang I've added this for the thread safety. Thoughts welcome

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, do we actually need locks here? If someone is reading the value just as another thread is writing the value, it sort of doesn't matter who wins. After all, the read value will only be slightly outdated.

In other words, I don't see any problems with race conditions in this case as this isn't data that's timing sensitive. I don't think torn reads are a problem because these are 32 bit references.

This value is going to be set on every request, I'd rather avoid a lock here unless it's absolutely needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@khellang @haacked I'm easy either way - with locking/ without

What's the preferred method of resolving coding decisions? A well argued debate between respectful & collaborate peers? Rocks/ Paper/ Scissors? A fight to the death?

(is it wrong to hope for the last one)

Copy link
Contributor

Choose a reason for hiding this comment

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

I've been taking the Benevolent Dictator role. 😛

I'd like to hear from @khellang if there are specific concerns with removing the locks. If not, let's remove them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(Off topic)

Please tell me someone out there is photoshoping the below - replacing with @haacked and the Octocat (not saying which way round)

image

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's fine to remove the locks, it's probably a bit too much. I just brought it up because there's now some shared, mutable state going on.

Copy link
Contributor

Choose a reason for hiding this comment

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

👍

Let's remove the locks, but make sure we comment it and explain why so if someone else comes along, they understand why there's shared mutable state.

Also, one idea we should do is to set LastApiInfo to a copy of the ApiInfo to reduce the sharing of mutable state. In fact, I think LastApiInfo should be a method GetLastApiInfo and it should always return a copy of the last ApiInfo

That way, Octokit is in control of the lifetime of that object and a consumer can't inadvertently keep the object around longer than expected. Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

SGTM 👍

@Red-Folder
Copy link
Contributor Author

@shiftkey Added further integration tests now - seems to cover all bases if a little repetitive. I've added a new test attribute for Personal Access Token - the OAuth/ AcceptedOAuth test uses that attribute.

@Red-Folder
Copy link
Contributor Author

Hi guys, any further feedback on this one?

I'm in danger of losing my dev environment in the next few days so would like to get this PR boxed off.

Thanks

// Seem to have to do this to pass a whole bunch of tests (for example Octokit.Tests.Clients.EventsClientTests.DeserializesCommitCommentEventCorrectly)
// I believe this has something to do with the Mocking framework.
if (this == null || this.Links == null || this.OauthScopes == null || this.RateLimit == null || this.Etag == null)
return null;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Extra points for explaining why I needed to add this null check. For some reason bundles of tests fail without it (comment and see what happens). I think it is something to do with how the mocking framework is handling the object - but can't understand why it touches it.

@Red-Folder
Copy link
Contributor Author

Could someone have a look over my cloning logic. Seems to work - but I could do with a fresh set of eyes on it.

Note that I'm having to do new String(originalString.ToCharArray()) as nothing else (string.Copy for example) seems to work with portable version.

{
// Seem to have to do this to pass a whole bunch of tests (for example Octokit.Tests.Clients.EventsClientTests.DeserializesCommitCommentEventCorrectly)
// I believe this has something to do with the Mocking framework.
if (this == null || this.Links == null || this.OauthScopes == null || this.RateLimit == null || this.Etag == null)
Copy link
Contributor

Choose a reason for hiding this comment

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

When would this be null though?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair point.

I really not sure why I need this line at all - but something blew up within the mocking framework so I added everything and kitchen sink.

Maybe went a tad overboard ;)

@haacked
Copy link
Contributor

haacked commented Aug 25, 2015

Looks good. The title suggests this is a WIP. Is that still the case or is this good to merge?

@Red-Folder
Copy link
Contributor Author

@haacked Sorry Phil, I'd not been chasing this. I'd lost my dev environment & between jobs (must find new job before wife makes me paint more fences).

Dev environment back up and running. Will make the two minor tweaks you mention above then should be good to merge. Probably today or tomorrow

@haacked
Copy link
Contributor

haacked commented Aug 26, 2015

@Red-Folder No problem! Thanks for continuing to work on this and good luck finding a new job!

@Red-Folder
Copy link
Contributor Author

Pops head above the parapet ... "Looks good to go"

(Prepares to duck back down quickly)

@Red-Folder Red-Folder changed the title [WIP] Access to the last ApiInfo object Access to the last ApiInfo object Aug 28, 2015
haacked added a commit that referenced this pull request Aug 28, 2015
Access to the last ApiInfo object
@haacked haacked merged commit 5a117fe into octokit:master Aug 28, 2015
@haacked
Copy link
Contributor

haacked commented Aug 28, 2015

Thanks!
selfie-0

@Red-Folder
Copy link
Contributor Author

Ah ... excellent. A second thumbs up to add to the collection.

I've added a whole section on my bio page for them ;)

http://www.red-folder.com/Home/MyBio (then scroll down). One day I'll setup the anchors, make the site size correctly, finish it, etc, etc, blah, blah

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants