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

Added GetRateLimits to MiscellaneousClient #848

Merged
merged 6 commits into from
Jul 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Octokit.Reactive/Clients/IObservableMiscellaneousClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,14 @@ public interface IObservableMiscellaneousClient
/// <param name="key"></param>
/// <returns>A <see cref="License" /> that includes the license key, text, and attributes of the license.</returns>
IObservable<License> GetLicense(string key);

/// <summary>
/// Gets API Rate Limits (API service rather than header info).
/// </summary>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>An <see cref="MiscellaneousRateLimit"/> of Rate Limits.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
IObservable<MiscellaneousRateLimit> GetRateLimits();

}
}
11 changes: 11 additions & 0 deletions Octokit.Reactive/Clients/ObservableMiscellaneousClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,16 @@ public IObservable<License> GetLicense(string key)
{
return _client.GetLicense(key).ToObservable();
}

/// <summary>
/// Gets API Rate Limits (API service rather than header info).
/// </summary>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>An <see cref="MiscellaneousRateLimit"/> of Rate Limits.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public IObservable<MiscellaneousRateLimit> GetRateLimits()
{
return _client.GetRateLimits().ToObservable();
}
}
}
33 changes: 33 additions & 0 deletions Octokit.Tests.Integration/Clients/MiscellaneousClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,37 @@ public async Task CanRetrieveListOfLicenses()
Assert.Equal("MIT License", result.Name);
}
}

public class TheGetResourceRateLimitsMethod
{
[IntegrationTest]
public async Task CanRetrieveResourceRateLimits()
{
var github = Helper.GetAuthenticatedClient();

var result = await github.Miscellaneous.GetRateLimits();

// Test the core limits
Assert.True(result.Resources.Core.Limit > 0);
Assert.True(result.Resources.Core.Remaining > -1);
Assert.True(result.Resources.Core.Remaining <= result.Resources.Core.Limit);
Assert.True(result.Resources.Core.ResetAsUtcEpochSeconds > 0);
Assert.NotNull(result.Resources.Core.Reset);

// Test the search limits
Assert.True(result.Resources.Search.Limit > 0);
Assert.True(result.Resources.Search.Remaining > -1);
Assert.True(result.Resources.Search.Remaining <= result.Resources.Search.Limit);
Assert.True(result.Resources.Search.ResetAsUtcEpochSeconds > 0);
Assert.NotNull(result.Resources.Search.Reset);

// Test the depreciated rate limits
Assert.True(result.Rate.Limit > 0);
Assert.True(result.Rate.Remaining > -1);
Assert.True(result.Rate.Remaining <= result.Rate.Limit);
Assert.True(result.Resources.Search.ResetAsUtcEpochSeconds > 0);
Assert.NotNull(result.Resources.Search.Reset);

}
}
}
58 changes: 58 additions & 0 deletions Octokit.Tests/Clients/MiscellaneousClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using NSubstitute;
using Octokit.Internal;
using Xunit;
using System.Globalization;

namespace Octokit.Tests.Clients
{
Expand Down Expand Up @@ -58,6 +59,63 @@ public async Task RequestsTheEmojiEndpoint()
}
}

public class TheGetResourceRateLimitsMethod
{
[Fact]
public async Task RequestsTheRecourceRateLimitEndpoint()
{
IApiResponse<MiscellaneousRateLimit> response = new ApiResponse<MiscellaneousRateLimit>
(
new Response(),
new MiscellaneousRateLimit(
new ResourceRateLimit(
new RateLimit(5000, 4999, 1372700873),
new RateLimit(30, 18, 1372700873)
),
new RateLimit(100, 75, 1372700873)
)
);
var connection = Substitute.For<IConnection>();
connection.Get<MiscellaneousRateLimit>(Args.Uri, null, null).Returns(Task.FromResult(response));
var client = new MiscellaneousClient(connection);

var result = await client.GetRateLimits();

// Test the core limits
Assert.Equal(5000, result.Resources.Core.Limit);
Assert.Equal(4999, result.Resources.Core.Remaining);
Assert.Equal(1372700873, result.Resources.Core.ResetAsUtcEpochSeconds);
var expectedReset = DateTimeOffset.ParseExact(
"Mon 01 Jul 2013 5:47:53 PM -00:00",
"ddd dd MMM yyyy h:mm:ss tt zzz",
CultureInfo.InvariantCulture);
Assert.Equal(expectedReset, result.Resources.Core.Reset);

// Test the search limits
Assert.Equal(30, result.Resources.Search.Limit);
Assert.Equal(18, result.Resources.Search.Remaining);
Assert.Equal(1372700873, result.Resources.Search.ResetAsUtcEpochSeconds);
expectedReset = DateTimeOffset.ParseExact(
"Mon 01 Jul 2013 5:47:53 PM -00:00",
"ddd dd MMM yyyy h:mm:ss tt zzz",
CultureInfo.InvariantCulture);
Assert.Equal(expectedReset, result.Resources.Search.Reset);

// Test the depreciated rate limits
Assert.Equal(100, result.Rate.Limit);
Assert.Equal(75, result.Rate.Remaining);
Assert.Equal(1372700873, result.Rate.ResetAsUtcEpochSeconds);
expectedReset = DateTimeOffset.ParseExact(
"Mon 01 Jul 2013 5:47:53 PM -00:00",
"ddd dd MMM yyyy h:mm:ss tt zzz",
CultureInfo.InvariantCulture);
Assert.Equal(expectedReset, result.Rate.Reset);

connection.Received()
.Get<MiscellaneousRateLimit>(Arg.Is<Uri>(u => u.ToString() == "rate_limit"), null, null);
}
}

public class TheCtor
{
[Fact]
Expand Down
8 changes: 8 additions & 0 deletions Octokit/Clients/IMiscellaneousClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,13 @@ public interface IMiscellaneousClient
/// <param name="key"></param>
/// <returns>A <see cref="License" /> that includes the license key, text, and attributes of the license.</returns>
Task<License> GetLicense(string key);

/// <summary>
/// Gets API Rate Limits (API service rather than header info).
/// </summary>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>An <see cref="MiscellaneousRateLimit"/> of Rate Limits.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
Task<MiscellaneousRateLimit> GetRateLimits();
}
}
13 changes: 13 additions & 0 deletions Octokit/Clients/MiscellaneousClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,18 @@ public async Task<License> GetLicense(string key)
.ConfigureAwait(false);
return response.Body;
}

/// <summary>
/// Gets API Rate Limits (API service rather than header info).
/// </summary>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>An <see cref="MiscellaneousRateLimit"/> of Rate Limits.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public async Task<MiscellaneousRateLimit> GetRateLimits()
{
var endpoint = new Uri("rate_limit", UriKind.Relative);
var response = await _connection.Get<MiscellaneousRateLimit>(endpoint, null, null).ConfigureAwait(false);
return response.Body;
}
}
}
9 changes: 9 additions & 0 deletions Octokit/Helpers/UnixTimeStampExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,14 @@ public static DateTimeOffset FromUnixTime(this long unixTime)
{
return new DateTimeOffset(unixTime * TimeSpan.TicksPerSecond + unixEpochTicks, TimeSpan.Zero);
}

/// <summary>
/// Convert <see cref="DateTimeOffset"/> with UTC offset to a Unix tick
/// </summary>
/// <param name="date">Date Time with UTC offset</param>
public static long ToUnixTime(this DateTimeOffset date)
{
return (date.Ticks - unixEpochTicks) / TimeSpan.TicksPerSecond;
}
}
}
33 changes: 33 additions & 0 deletions Octokit/Http/RateLimit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
using Octokit.Helpers;
using System.Diagnostics;
using System.Globalization;
using Octokit.Internal;

namespace Octokit
{
#if !NETFX_CORE
[Serializable]
#endif
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class RateLimit
#if !NETFX_CORE
: ISerializable
#endif
{
public RateLimit() {}

public RateLimit(IDictionary<string, string> responseHeaders)
{
Expand All @@ -23,6 +28,17 @@ public RateLimit(IDictionary<string, string> responseHeaders)
Reset = GetHeaderValueAsInt32Safe(responseHeaders, "X-RateLimit-Reset").FromUnixTime();
}

public RateLimit(int limit, int remaining, long reset)
{
Ensure.ArgumentNotNull(limit, "limit");
Ensure.ArgumentNotNull(remaining, "remaining");
Ensure.ArgumentNotNull(reset, "reset");

Limit = limit;
Remaining = remaining;
Reset = reset.FromUnixTime();
}

/// <summary>
/// The maximum number of requests that the consumer is permitted to make per hour.
/// </summary>
Expand All @@ -36,8 +52,16 @@ public RateLimit(IDictionary<string, string> responseHeaders)
/// <summary>
/// The date and time at which the current rate limit window resets
/// </summary>
[ParameterAttribute(Key = "ignoreThisField")]
public DateTimeOffset Reset { get; private set; }

/// <summary>
/// The date and time at which the current rate limit window resets - in UTC epoch seconds
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
[ParameterAttribute(Key = "reset")]
public long ResetAsUtcEpochSeconds { get { return Reset.ToUnixTime(); } private set { Reset = value.FromUnixTime(); } }

static long GetHeaderValueAsInt32Safe(IDictionary<string, string> responseHeaders, string key)
{
string value;
Expand Down Expand Up @@ -66,5 +90,14 @@ public virtual void GetObjectData(SerializationInfo info, StreamingContext conte
info.AddValue("Reset", Reset.Ticks);
}
#endif

internal string DebuggerDisplay
{
get
{
return String.Format(CultureInfo.InvariantCulture, "Limit {0}, Remaining {1}, Reset {2} ", Limit, Remaining, Reset);
}
}

}
}
43 changes: 43 additions & 0 deletions Octokit/Models/Response/MiscellaneousRateLimit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Octokit
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class MiscellaneousRateLimit
{
public MiscellaneousRateLimit() {}

public MiscellaneousRateLimit(ResourceRateLimit resources, RateLimit rate)
{
Ensure.ArgumentNotNull(resources, "resource");
Ensure.ArgumentNotNull(rate, "rate");

Resources = resources;
Rate = rate;
}

/// <summary>
/// Object of resources rate limits
/// </summary>
public ResourceRateLimit Resources { get; private set; }

/// <summary>
/// Legacy rate limit - to be depreciated - https://developer.github.com/v3/rate_limit/#deprecation-notice
/// </summary>
public RateLimit Rate { get; private set; }

internal string DebuggerDisplay
{
get
{
return Resources == null ? "No rates found" : String.Format(CultureInfo.InvariantCulture, Resources.DebuggerDisplay);
}
}
}
}
42 changes: 42 additions & 0 deletions Octokit/Models/Response/ResourceRateLimit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Diagnostics;
using System.Globalization;

using Octokit.Helpers;

namespace Octokit
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class ResourceRateLimit
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd rather we just use RateLimit and not this class. The name of this class is too similar to ResourceRateLimits. The data we show in this response and in the headers are the same and not likely to change (as we try and avoid breaking changes).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed now to use RateLimit

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure where we ended up with this - is it ResourceRateLimit or RateLimit?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Three models in use:

  1. Originally MiscRateLimit -> Changed to MiscellaneousRateLimit to avoid abbreviation
  2. Originally ResourceRateLimits -> Changes to ResourceRateLimit
  3. Originally ResourceRateLimit -> Changes to use existing RateLimit

Hopefully that makes sense

Copy link
Contributor

Choose a reason for hiding this comment

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

👍

{
public ResourceRateLimit() {}

public ResourceRateLimit(RateLimit core, RateLimit search)
{
Ensure.ArgumentNotNull(core, "core");
Ensure.ArgumentNotNull(search, "search");

Core = core;
Search = search;
}

/// <summary>
/// Rate limits for core API (rate limit for everything except Search API)
/// </summary>
public RateLimit Core { get; private set; }

/// <summary>
/// Rate Limits for Search API
/// </summary>
public RateLimit Search { get; private set; }

internal string DebuggerDisplay
{
get
{
return String.Format(CultureInfo.InvariantCulture, "Core: {0}; Search: {1} ", Core.DebuggerDisplay, Search.DebuggerDisplay);
}
}
}

}
2 changes: 2 additions & 0 deletions Octokit/Octokit-Mono.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@
<Compile Include="Exceptions\TwoFactorAuthorizationException.cs" />
<Compile Include="Http\HttpMessageHandlerFactory.cs" />
<Compile Include="Models\Response\TeamMembership.cs" />
<Compile Include="Models\Response\ResourceRateLimit.cs" />
<Compile Include="Models\Response\MiscellaneousRateLimit.cs" />
<Compile Include="Exceptions\RepositoryFormatException.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
Expand Down
2 changes: 2 additions & 0 deletions Octokit/Octokit-MonoAndroid.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,8 @@
<Compile Include="Models\Request\RepositoryHookTestRequest.cs" />
<Compile Include="Http\HttpMessageHandlerFactory.cs" />
<Compile Include="Models\Response\TeamMembership.cs" />
<Compile Include="Models\Response\ResourceRateLimit.cs" />
<Compile Include="Models\Response\MiscellaneousRateLimit.cs" />
<Compile Include="Exceptions\RepositoryFormatException.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
Expand Down
2 changes: 2 additions & 0 deletions Octokit/Octokit-Monotouch.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@
<Compile Include="Models\Request\RepositoryHookTestRequest.cs" />
<Compile Include="Http\HttpMessageHandlerFactory.cs" />
<Compile Include="Models\Response\TeamMembership.cs" />
<Compile Include="Models\Response\ResourceRateLimit.cs" />
<Compile Include="Models\Response\MiscellaneousRateLimit.cs" />
<Compile Include="Exceptions\RepositoryFormatException.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.MonoTouch.CSharp.targets" />
Expand Down
2 changes: 2 additions & 0 deletions Octokit/Octokit-Portable.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,8 @@
<Compile Include="Exceptions\TwoFactorAuthorizationException.cs" />
<Compile Include="Http\HttpMessageHandlerFactory.cs" />
<Compile Include="Models\Response\TeamMembership.cs" />
<Compile Include="Models\Response\ResourceRateLimit.cs" />
<Compile Include="Models\Response\MiscellaneousRateLimit.cs" />
<Compile Include="Exceptions\RepositoryFormatException.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions Octokit/Octokit-netcore45.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,8 @@
<Compile Include="Exceptions\TwoFactorAuthorizationException.cs" />
<Compile Include="Http\HttpMessageHandlerFactory.cs" />
<Compile Include="Models\Response\TeamMembership.cs" />
<Compile Include="Models\Response\ResourceRateLimit.cs" />
<Compile Include="Models\Response\MiscellaneousRateLimit.cs" />
<Compile Include="Exceptions\RepositoryFormatException.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
Loading