Skip to content

Commit

Permalink
Merge pull request #16 from viagogo/cancellation-tokens
Browse files Browse the repository at this point in the history
Add cancellation support to IUserClient, ISellerListingsClient and IBatchClient
  • Loading branch information
akilburge committed Feb 15, 2016
2 parents 9340c1e + fa7c7e7 commit dbc6db1
Show file tree
Hide file tree
Showing 17 changed files with 174 additions and 46 deletions.
3 changes: 3 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
### New in 0.9.0 (Released 2016/02/13)
* Added support for cancelling requests in the ISellerListingClient, IBatchClient and IUserClient

### New in 0.8.2 (Released 2016/02/10)
* Fixed BatchClient issue generating the Uri for the batch endpoint

Expand Down
8 changes: 4 additions & 4 deletions SolutionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
[assembly: AssemblyProductAttribute("GogoKit")]
[assembly: AssemblyCompanyAttribute("viagogo")]
[assembly: AssemblyCopyrightAttribute("Copyright viagogo 2016")]
[assembly: AssemblyVersionAttribute("0.8.2")]
[assembly: AssemblyFileVersionAttribute("0.8.2")]
[assembly: AssemblyInformationalVersionAttribute("0.8.2")]
[assembly: AssemblyVersionAttribute("0.9.0")]
[assembly: AssemblyFileVersionAttribute("0.9.0")]
[assembly: AssemblyInformationalVersionAttribute("0.9.0")]
[assembly: ComVisibleAttribute(false)]
namespace System {
internal static class AssemblyVersionInformation {
internal const string Version = "0.8.2";
internal const string Version = "0.9.0";
}
}
64 changes: 52 additions & 12 deletions src/GogoKit/Clients/BatchClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using GogoLib;
using HalKit;
using HalKit.Http;
using HalKit.Json;
using HalKit.Models.Response;
using HalKit.Services;

namespace GogoKit.Clients
{
Expand All @@ -18,30 +21,50 @@ public class BatchClient : IBatchClient
private readonly IHttpConnection _httpConnection;
private readonly IApiResponseFactory _responseFactory;
private readonly IJsonSerializer _jsonSerializer;
private readonly ILinkResolver _linkResolver;
private readonly IHalKitConfiguration _configuration;

public BatchClient(
IHttpConnection connection,
IHttpConnection connection,
IApiResponseFactory responseFactory,
IJsonSerializer jsonSerializer)
IJsonSerializer jsonSerializer,
ILinkResolver linkResolver)
{
_responseFactory = responseFactory;
_httpConnection = connection;
_configuration = connection.Configuration;
_jsonSerializer = jsonSerializer;
_linkResolver = linkResolver;
}

public async Task<IReadOnlyList<IApiResponse<TResponse>>> SendBatch<TResponse>(IEnumerable<IApiRequest> requests)
public Task<IReadOnlyList<IApiResponse<TResponse>>> SendBatch<TResponse>(IEnumerable<IApiRequest> requests)
{
var httpBatchRequest = CreateBatchRequest(requests);
var httpBatchResponse = await _httpConnection.Client.SendAsync(httpBatchRequest).ConfigureAwait(_configuration);
return SendBatch<TResponse>(
requests,
new Dictionary<string, string>(),
new Dictionary<string, IEnumerable<string>>(),
CancellationToken.None);
}

public async Task<IReadOnlyList<IApiResponse<TResponse>>> SendBatch<TResponse>(
IEnumerable<IApiRequest> requests,
IDictionary<string, string> parameters,
IDictionary<string, IEnumerable<string>> headers,
CancellationToken cancellationToken)
{
var httpBatchRequest = CreateBatchRequest(requests, parameters, headers);
var httpBatchResponse = await _httpConnection.Client.SendAsync(httpBatchRequest, cancellationToken)
.ConfigureAwait(_configuration);

var apiResponses = await ParseBatchResponse<TResponse>(httpBatchResponse).ConfigureAwait(_configuration);

return apiResponses;
}

private HttpRequestMessage CreateBatchRequest(IEnumerable<IApiRequest> requests)
private HttpRequestMessage CreateBatchRequest(
IEnumerable<IApiRequest> requests,
IDictionary<string, string> parameters,
IDictionary<string, IEnumerable<string>> headers)
{
var batchRequestContent = new MultipartContent("mixed", $"batch_{Guid.NewGuid()}");

Expand All @@ -50,8 +73,8 @@ private HttpRequestMessage CreateBatchRequest(IEnumerable<IApiRequest> requests)
var contentType = "application/hal+json";
var innerRequest = new HttpRequestMessage(request.Method, request.Uri);

var headers = request.Headers ?? new Dictionary<string, IEnumerable<string>>();
foreach (var header in headers)
var innerRequestHeaders = request.Headers ?? new Dictionary<string, IEnumerable<string>>();
foreach (var header in innerRequestHeaders)
{
if (header.Key == "Content-Type")
{
Expand All @@ -67,11 +90,28 @@ private HttpRequestMessage CreateBatchRequest(IEnumerable<IApiRequest> requests)
batchRequestContent.Add(new BatchRequestContent(innerRequest));
}

var batchEndpointUri = new Uri(_configuration.RootEndpoint, $"{_configuration.RootEndpoint}/batch");
return new HttpRequestMessage(HttpMethod.Post, batchEndpointUri)
var batchLink = new Link
{
HRef = new Uri(_configuration.RootEndpoint, $"{_configuration.RootEndpoint}/batch").AbsoluteUri
};
var batchEndpointUri = _linkResolver.ResolveLink(batchLink, parameters);
var batchRequest = new HttpRequestMessage(HttpMethod.Post, batchEndpointUri)
{
Content = batchRequestContent
};

headers = headers ?? new Dictionary<string, IEnumerable<string>>();
foreach (var header in headers)
{
Content = batchRequestContent
};
if (header.Key == "Content-Type")
{
continue;
}

batchRequest.Headers.Add(header.Key, header.Value);
}

return batchRequest;
}

private async Task<IReadOnlyList<IApiResponse<TResponse>>> ParseBatchResponse<TResponse>(HttpResponseMessage httpBatchResponse)
Expand Down
14 changes: 9 additions & 5 deletions src/GogoKit/Clients/IBatchClient.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using HalKit.Http;

namespace GogoKit.Clients
{
public interface IBatchClient
{
Task<IReadOnlyList<IApiResponse<TResponse>>> SendBatch<TResponse>(IEnumerable<IApiRequest> batchRequests);
Task<IReadOnlyList<IApiResponse<TResponse>>> SendBatch<TResponse>(IEnumerable<IApiRequest> requests);

Task<IReadOnlyList<IApiResponse<TResponse>>> SendBatch<TResponse>(
IEnumerable<IApiRequest> requests,
IDictionary<string, string> parameters,
IDictionary<string, IEnumerable<string>> headers,
CancellationToken cancellationToken);
}
}
3 changes: 3 additions & 0 deletions src/GogoKit/Clients/ISellerListingsClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using GogoKit.Models.Request;
using GogoKit.Models.Response;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using HalKit.Http;

Expand All @@ -20,6 +21,8 @@ public interface ISellerListingsClient

Task<IReadOnlyList<SellerListing>> GetAllAsync(SellerListingRequest request);

Task<IReadOnlyList<SellerListing>> GetAllAsync(SellerListingRequest request, CancellationToken cancellationToken);

Task<ListingConstraints> GetConstraintsAsync(int sellerListingId);

Task<ListingConstraints> GetConstraintsAsync(int sellerListingId, ListingConstraintsRequest request);
Expand Down
5 changes: 4 additions & 1 deletion src/GogoKit/Clients/IUserClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
using GogoKit.Models.Request;
using GogoKit.Models.Response;

Expand All @@ -7,6 +8,8 @@ namespace GogoKit.Clients
public interface IUserClient
{
Task<User> GetAsync();
Task<User> GetAsync(UserRequest request);
Task<User> GetAsync(UserRequest request, CancellationToken cancellationToken);
Task<User> UpdateAsync(UserUpdate userUpdate);
}
}
4 changes: 3 additions & 1 deletion src/GogoKit/Clients/OAuth2Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using GogoKit.Models.Response;
using HalKit.Http;
Expand Down Expand Up @@ -43,7 +44,8 @@ public async Task<OAuth2Token> GetAccessTokenAsync(
new Dictionary<string, IEnumerable<string>>
{
{"Accept", new[] {"application/json"}}
}).ConfigureAwait(_configuration);
},
CancellationToken.None).ConfigureAwait(_configuration);
var token = response.BodyAsObject;

token.IssueDate = response.Headers.ContainsKey("Date")
Expand Down
15 changes: 12 additions & 3 deletions src/GogoKit/Clients/SellerListingsClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using GogoKit.Models.Request;
using GogoKit.Models.Response;
Expand Down Expand Up @@ -54,10 +55,18 @@ public Task<IReadOnlyList<SellerListing>> GetAllAsync()
return GetAllAsync(new SellerListingRequest());
}

public async Task<IReadOnlyList<SellerListing>> GetAllAsync(SellerListingRequest request)
public Task<IReadOnlyList<SellerListing>> GetAllAsync(SellerListingRequest request)
{
var user = await _userClient.GetAsync().ConfigureAwait(_halClient);
return await _halClient.GetAllPagesAsync<SellerListing>(user.SellerListingsLink, request).ConfigureAwait(_halClient);
return GetAllAsync(request, CancellationToken.None);
}

public async Task<IReadOnlyList<SellerListing>> GetAllAsync(SellerListingRequest request, CancellationToken cancellationToken)
{
var user = await _userClient.GetAsync(new UserRequest(), cancellationToken).ConfigureAwait(_halClient);
return await _halClient.GetAllPagesAsync<SellerListing>(
user.SellerListingsLink,
request,
cancellationToken).ConfigureAwait(_halClient);
}

public Task<ListingConstraints> GetConstraintsAsync(int sellerListingId)
Expand Down
20 changes: 17 additions & 3 deletions src/GogoKit/Clients/UserClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
using GogoKit.Models.Request;
using GogoKit.Models.Response;
using HalKit;
Expand All @@ -16,10 +17,23 @@ public UserClient(IHalClient halClient)
_halClient = halClient;
}

public async Task<User> GetAsync()
public Task<User> GetAsync()
{
return GetAsync(new UserRequest());
}

public Task<User> GetAsync(UserRequest request)
{
return GetAsync(request, CancellationToken.None);
}

public async Task<User> GetAsync(UserRequest request, CancellationToken cancellationToken)
{
var root = await _halClient.GetRootAsync().ConfigureAwait(_halClient);
return await _halClient.GetAsync<User>(root.UserLink).ConfigureAwait(_halClient);
return await _halClient.GetAsync<User>(
root.UserLink,
request,
cancellationToken).ConfigureAwait(_halClient);
}

public async Task<User> UpdateAsync(UserUpdate userUpdate)
Expand Down
39 changes: 36 additions & 3 deletions src/GogoKit/Extensions/HalClientExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using GogoKit.Models.Response;
using HalKit;
Expand Down Expand Up @@ -31,19 +32,48 @@ public static Task<IReadOnlyList<T>> GetAllPagesAsync<T>(
this IHalClient client,
Link link,
IRequestParameters request) where T : Resource
{
return GetAllPagesAsync<T>(
client,
link,
request,
CancellationToken.None);
}

public static Task<IReadOnlyList<T>> GetAllPagesAsync<T>(
this IHalClient client,
Link link,
IRequestParameters request,
CancellationToken cancellationToken) where T : Resource
{
return GetAllPagesAsync<T>(
client,
link,
request.Parameters,
request.Headers);
request.Headers,
cancellationToken);
}

public static async Task<IReadOnlyList<T>> GetAllPagesAsync<T>(
public static Task<IReadOnlyList<T>> GetAllPagesAsync<T>(
this IHalClient client,
Link link,
IDictionary<string, string> parameters,
IDictionary<string, IEnumerable<string>> headers) where T : Resource
{
return GetAllPagesAsync<T>(
client,
link,
parameters,
headers,
CancellationToken.None);
}

public static async Task<IReadOnlyList<T>> GetAllPagesAsync<T>(
this IHalClient client,
Link link,
IDictionary<string, string> parameters,
IDictionary<string, IEnumerable<string>> headers,
CancellationToken cancellationToken) where T : Resource
{
Requires.ArgumentNotNull(client, nameof(client));
Requires.ArgumentNotNull(link, nameof(link));
Expand All @@ -65,10 +95,13 @@ public static async Task<IReadOnlyList<T>> GetAllPagesAsync<T>(
var hasAnotherPage = true;
while (hasAnotherPage)
{
cancellationToken.ThrowIfCancellationRequested();

var currentPage = await client.GetAsync<PagedResource<T>>(
currentLink,
currentParameters,
headers).ConfigureAwait(client.Configuration);
headers,
cancellationToken).ConfigureAwait(client.Configuration);

items.AddRange(currentPage.Items);

Expand Down
5 changes: 3 additions & 2 deletions src/GogoKit/GogoKit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
<Compile Include="Models\Request\SaleRequest.cs" />
<Compile Include="Models\Request\SellerListingRequest.cs" />
<Compile Include="Models\Request\SellerListingUpdate.cs" />
<Compile Include="Models\Request\UserRequest.cs" />
<Compile Include="Models\Request\VenueRequest.cs" />
<Compile Include="Models\Request\WebhookRequest.cs" />
<Compile Include="Models\Request\WebhookUpdate.cs" />
Expand Down Expand Up @@ -182,8 +183,8 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="HalKit, Version=0.6.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\HalKit.0.6.0\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\HalKit.dll</HintPath>
<Reference Include="HalKit, Version=0.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\HalKit.0.7.0\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\HalKit.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
Expand Down
6 changes: 6 additions & 0 deletions src/GogoKit/Models/Request/UserRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace GogoKit.Models.Request
{
public class UserRequest : RequestParameters<string, string>
{
}
}
5 changes: 4 additions & 1 deletion src/GogoKit/ViagogoClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ public ViagogoClient(
Webhooks = new WebhooksClient(User, Hypermedia, linkFactory);

var jsonSerializer = new DefaultJsonSerializer();
BatchClient = new BatchClient(apiConnection, new ApiResponseFactory(jsonSerializer, halKitConfiguration), jsonSerializer);
BatchClient = new BatchClient(apiConnection,
new ApiResponseFactory(jsonSerializer, halKitConfiguration),
jsonSerializer,
new LinkResolver());
}

public IGogoKitConfiguration Configuration { get; }
Expand Down
2 changes: 1 addition & 1 deletion src/GogoKit/packages.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="HalKit" version="0.6.0" targetFramework="portable45-net45+win8+wp8+wpa81" userInstalled="true" />
<package id="HalKit" version="0.7.0" targetFramework="portable45-net45+win8+wp8+wpa81" userInstalled="true" />
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="portable-monoandroid1+monotouch1+net45+win+wp8+wpa81+xamarinios1" userInstalled="true" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="portable-monoandroid1+monotouch1+net45+win+wp8+wpa81+xamarinios1" userInstalled="true" />
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="portable-monoandroid1+monotouch1+net45+win+wp8+wpa81+xamarinios1" userInstalled="true" />
Expand Down
Loading

0 comments on commit dbc6db1

Please sign in to comment.