Skip to content

Commit

Permalink
Merge pull request #232 from LordMike/add-cancellationtokens
Browse files Browse the repository at this point in the history
Add cancellation-tokens to async methods
  • Loading branch information
LordMike authored Jan 15, 2018
2 parents d381703 + 5c0f175 commit 37ceaab
Show file tree
Hide file tree
Showing 26 changed files with 427 additions and 367 deletions.
6 changes: 4 additions & 2 deletions TMDbLib/Client/TMDbClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using RestClient = TMDbLib.Rest.RestClient;
using RestRequest = TMDbLib.Rest.RestRequest;
using System.Net;
using System.Threading;

namespace TMDbLib.Client
{
Expand Down Expand Up @@ -131,12 +132,13 @@ public bool ThrowErrorOnExeedingMaxCalls
/// Check <see cref="Utilities.TMDbAPIProxy"/> for more information.
/// </remarks>
public IWebProxy WebProxy { get; private set; }

/// <summary>
/// Used internally to assign a session id to a request. If no valid session is found, an exception is thrown.
/// </summary>
/// <param name="req">Request</param>
/// <param name="targetType">The target session type to set. If set to Unassigned, the method will take the currently set session.</param>
/// <param name="parameterType">The location of the paramter in the resulting query</param>
private void AddSessionId(RestRequest req, SessionType targetType = SessionType.Unassigned, ParameterType parameterType = ParameterType.QueryString)
{
if ((targetType == SessionType.Unassigned && SessionType == SessionType.GuestSession) ||
Expand Down Expand Up @@ -165,7 +167,7 @@ private void AddSessionId(RestRequest req, SessionType targetType = SessionType.

public void GetConfig()
{
TMDbConfig config = _client.Create("configuration").ExecuteGet<TMDbConfig>().Result;
TMDbConfig config = _client.Create("configuration").ExecuteGet<TMDbConfig>(CancellationToken.None).Result;

if (config == null)
throw new Exception("Unable to retrieve configuration");
Expand Down
57 changes: 30 additions & 27 deletions TMDbLib/Client/TMDbClientAccount.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using TMDbLib.Utilities;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using TMDbLib.Objects.Account;
using TMDbLib.Objects.Authentication;
Expand All @@ -18,19 +19,20 @@ public partial class TMDbClient
/// <param name="mediaType">The type of media to influence</param>
/// <param name="mediaId">The id of the movie/tv show to influence</param>
/// <param name="isFavorite">True if you want the specified movie to be marked as favorite, false if not</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>True if the the movie's favorite status was successfully updated, false if not</returns>
/// <remarks>Requires a valid user session</remarks>
/// <exception cref="UserSessionRequiredException">Thrown when the current client object doens't have a user session assigned.</exception>
public async Task<bool> AccountChangeFavoriteStatusAsync(MediaType mediaType, int mediaId, bool isFavorite)
public async Task<bool> AccountChangeFavoriteStatusAsync(MediaType mediaType, int mediaId, bool isFavorite, CancellationToken cancellationToken = default(CancellationToken))
{
RequireSessionId(SessionType.UserSession);

RestRequest request = _client.Create("account/{accountId}/favorite") ;
RestRequest request = _client.Create("account/{accountId}/favorite");
request.AddUrlSegment("accountId", ActiveAccount.Id.ToString(CultureInfo.InvariantCulture));
request.SetBody(new { media_type = mediaType.GetDescription(), media_id = mediaId, favorite = isFavorite });
AddSessionId(request, SessionType.UserSession);

PostReply response = await request.ExecutePost<PostReply>().ConfigureAwait(false);
PostReply response = await request.ExecutePost<PostReply>(cancellationToken).ConfigureAwait(false);

// status code 1 = "Success" - Returned when adding a movie as favorite for the first time
// status code 13 = "The item/record was deleted successfully" - When removing an item as favorite, no matter if it exists or not
Expand All @@ -44,19 +46,20 @@ public async Task<bool> AccountChangeFavoriteStatusAsync(MediaType mediaType, in
/// <param name="mediaType">The type of media to influence</param>
/// <param name="mediaId">The id of the movie/tv show to influence</param>
/// <param name="isOnWatchlist">True if you want the specified movie to be part of the watchlist, false if not</param>
/// <param name="cancellationToken">A cancellation token</param>
/// <returns>True if the the movie's status on the watchlist was successfully updated, false if not</returns>
/// <remarks>Requires a valid user session</remarks>
/// <exception cref="UserSessionRequiredException">Thrown when the current client object doens't have a user session assigned.</exception>
public async Task<bool> AccountChangeWatchlistStatusAsync(MediaType mediaType, int mediaId, bool isOnWatchlist)
public async Task<bool> AccountChangeWatchlistStatusAsync(MediaType mediaType, int mediaId, bool isOnWatchlist, CancellationToken cancellationToken = default(CancellationToken))
{
RequireSessionId(SessionType.UserSession);

RestRequest request = _client.Create("account/{accountId}/watchlist");
RestRequest request = _client.Create("account/{accountId}/watchlist");
request.AddUrlSegment("accountId", ActiveAccount.Id.ToString(CultureInfo.InvariantCulture));
request.SetBody(new { media_type = mediaType.GetDescription(), media_id = mediaId, watchlist = isOnWatchlist });
AddSessionId(request, SessionType.UserSession);

PostReply response = await request.ExecutePost<PostReply>().ConfigureAwait(false);
PostReply response = await request.ExecutePost<PostReply>(cancellationToken).ConfigureAwait(false);

// status code 1 = "Success"
// status code 13 = "The item/record was deleted successfully" - When removing an item from the watchlist, no matter if it exists or not
Expand All @@ -69,14 +72,14 @@ public async Task<bool> AccountChangeWatchlistStatusAsync(MediaType mediaType, i
/// </summary>
/// <remarks>Requires a valid user session</remarks>
/// <exception cref="UserSessionRequiredException">Thrown when the current client object doens't have a user session assigned.</exception>
public async Task<AccountDetails> AccountGetDetailsAsync()
public async Task<AccountDetails> AccountGetDetailsAsync(CancellationToken cancellationToken = default(CancellationToken))
{
RequireSessionId(SessionType.UserSession);

RestRequest request = _client.Create("account");
AddSessionId(request, SessionType.UserSession);

AccountDetails response = await request.ExecuteGet<AccountDetails>().ConfigureAwait(false);
AccountDetails response = await request.ExecuteGet<AccountDetails>(cancellationToken).ConfigureAwait(false);

return response;
}
Expand All @@ -90,9 +93,9 @@ public async Task<SearchContainer<SearchMovie>> AccountGetFavoriteMoviesAsync(
int page = 1,
AccountSortBy sortBy = AccountSortBy.Undefined,
SortOrder sortOrder = SortOrder.Undefined,
string language = null)
string language = null, CancellationToken cancellationToken = default(CancellationToken))
{
return await GetAccountList<SearchMovie>(page, sortBy, sortOrder, language, AccountListsMethods.FavoriteMovies).ConfigureAwait(false);
return await GetAccountList<SearchMovie>(page, sortBy, sortOrder, language, AccountListsMethods.FavoriteMovies, cancellationToken).ConfigureAwait(false);
}

/// <summary>
Expand All @@ -104,9 +107,9 @@ public async Task<SearchContainer<SearchTv>> AccountGetFavoriteTvAsync(
int page = 1,
AccountSortBy sortBy = AccountSortBy.Undefined,
SortOrder sortOrder = SortOrder.Undefined,
string language = null)
string language = null, CancellationToken cancellationToken = default(CancellationToken))
{
return await GetAccountList<SearchTv>(page, sortBy, sortOrder, language, AccountListsMethods.FavoriteTv).ConfigureAwait(false);
return await GetAccountList<SearchTv>(page, sortBy, sortOrder, language, AccountListsMethods.FavoriteTv, cancellationToken).ConfigureAwait(false);
}

/// <summary>
Expand All @@ -115,7 +118,7 @@ public async Task<SearchContainer<SearchTv>> AccountGetFavoriteTvAsync(
/// </summary>
/// <remarks>Requires a valid user session</remarks>
/// <exception cref="UserSessionRequiredException">Thrown when the current client object doens't have a user session assigned.</exception>
public async Task<SearchContainer<AccountList>> AccountGetListsAsync(int page = 1, string language = null)
public async Task<SearchContainer<AccountList>> AccountGetListsAsync(int page = 1, string language = null, CancellationToken cancellationToken = default(CancellationToken))
{
RequireSessionId(SessionType.UserSession);

Expand All @@ -132,7 +135,7 @@ public async Task<SearchContainer<AccountList>> AccountGetListsAsync(int page =
if (!string.IsNullOrWhiteSpace(language))
request.AddQueryString("language", language);

SearchContainer<AccountList> response = await request.ExecuteGet<SearchContainer<AccountList>>().ConfigureAwait(false);
SearchContainer<AccountList> response = await request.ExecuteGet<SearchContainer<AccountList>>(cancellationToken).ConfigureAwait(false);

return response;
}
Expand All @@ -146,9 +149,9 @@ public async Task<SearchContainer<SearchMovie>> AccountGetMovieWatchlistAsync(
int page = 1,
AccountSortBy sortBy = AccountSortBy.Undefined,
SortOrder sortOrder = SortOrder.Undefined,
string language = null)
string language = null, CancellationToken cancellationToken = default(CancellationToken))
{
return await GetAccountList<SearchMovie>(page, sortBy, sortOrder, language, AccountListsMethods.MovieWatchlist).ConfigureAwait(false);
return await GetAccountList<SearchMovie>(page, sortBy, sortOrder, language, AccountListsMethods.MovieWatchlist, cancellationToken).ConfigureAwait(false);
}

/// <summary>
Expand All @@ -160,9 +163,9 @@ public async Task<SearchContainer<SearchMovieWithRating>> AccountGetRatedMoviesA
int page = 1,
AccountSortBy sortBy = AccountSortBy.Undefined,
SortOrder sortOrder = SortOrder.Undefined,
string language = null)
string language = null, CancellationToken cancellationToken = default(CancellationToken))
{
return await GetAccountList<SearchMovieWithRating>(page, sortBy, sortOrder, language, AccountListsMethods.RatedMovies).ConfigureAwait(false);
return await GetAccountList<SearchMovieWithRating>(page, sortBy, sortOrder, language, AccountListsMethods.RatedMovies, cancellationToken).ConfigureAwait(false);
}

/// <summary>
Expand All @@ -174,9 +177,9 @@ public async Task<SearchContainer<AccountSearchTvEpisode>> AccountGetRatedTvShow
int page = 1,
AccountSortBy sortBy = AccountSortBy.Undefined,
SortOrder sortOrder = SortOrder.Undefined,
string language = null)
string language = null, CancellationToken cancellationToken = default(CancellationToken))
{
return await GetAccountList<AccountSearchTvEpisode>(page, sortBy, sortOrder, language, AccountListsMethods.RatedTvEpisodes).ConfigureAwait(false);
return await GetAccountList<AccountSearchTvEpisode>(page, sortBy, sortOrder, language, AccountListsMethods.RatedTvEpisodes, cancellationToken).ConfigureAwait(false);
}

/// <summary>
Expand All @@ -188,9 +191,9 @@ public async Task<SearchContainer<AccountSearchTv>> AccountGetRatedTvShowsAsync(
int page = 1,
AccountSortBy sortBy = AccountSortBy.Undefined,
SortOrder sortOrder = SortOrder.Undefined,
string language = null)
string language = null, CancellationToken cancellationToken = default(CancellationToken))
{
return await GetAccountList<AccountSearchTv>(page, sortBy, sortOrder, language, AccountListsMethods.RatedTv).ConfigureAwait(false);
return await GetAccountList<AccountSearchTv>(page, sortBy, sortOrder, language, AccountListsMethods.RatedTv, cancellationToken).ConfigureAwait(false);
}

/// <summary>
Expand All @@ -202,16 +205,16 @@ public async Task<SearchContainer<SearchTv>> AccountGetTvWatchlistAsync(
int page = 1,
AccountSortBy sortBy = AccountSortBy.Undefined,
SortOrder sortOrder = SortOrder.Undefined,
string language = null)
string language = null, CancellationToken cancellationToken = default(CancellationToken))
{
return await GetAccountList<SearchTv>(page, sortBy, sortOrder, language, AccountListsMethods.TvWatchlist).ConfigureAwait(false);
return await GetAccountList<SearchTv>(page, sortBy, sortOrder, language, AccountListsMethods.TvWatchlist, cancellationToken).ConfigureAwait(false);
}

private async Task<SearchContainer<T>> GetAccountList<T>(int page, AccountSortBy sortBy, SortOrder sortOrder, string language, AccountListsMethods method)
private async Task<SearchContainer<T>> GetAccountList<T>(int page, AccountSortBy sortBy, SortOrder sortOrder, string language, AccountListsMethods method, CancellationToken cancellationToken = default(CancellationToken))
{
RequireSessionId(SessionType.UserSession);

RestRequest request = _client.Create("account/{accountId}/" + method.GetDescription());
RestRequest request = _client.Create("account/{accountId}/" + method.GetDescription());
request.AddUrlSegment("accountId", ActiveAccount.Id.ToString(CultureInfo.InvariantCulture));
AddSessionId(request, SessionType.UserSession);

Expand All @@ -228,7 +231,7 @@ private async Task<SearchContainer<T>> GetAccountList<T>(int page, AccountSortBy
if (!string.IsNullOrWhiteSpace(language))
request.AddParameter("language", language);

SearchContainer<T> response = await request.ExecuteGet<SearchContainer<T>>().ConfigureAwait(false);
SearchContainer<T> response = await request.ExecuteGet<SearchContainer<T>>(cancellationToken).ConfigureAwait(false);

return response;
}
Expand Down
26 changes: 14 additions & 12 deletions TMDbLib/Client/TMDbClientAuthentication.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
using System;
using System.Threading.Tasks;
using System.Net;
using System.Threading;
using TMDbLib.Objects.Authentication;
using TMDbLib.Rest;

namespace TMDbLib.Client
{
public partial class TMDbClient
{
public async Task<GuestSession> AuthenticationCreateGuestSessionAsync()
public async Task<GuestSession> AuthenticationCreateGuestSessionAsync(CancellationToken cancellationToken = default(CancellationToken))
{
RestRequest request = _client.Create("authentication/guest_session/new");
//{
// DateFormat = "yyyy-MM-dd HH:mm:ss UTC"
//};

RestResponse<GuestSession> response = await request.ExecuteGet<GuestSession>().ConfigureAwait(false);
RestResponse<GuestSession> response = await request.ExecuteGet<GuestSession>(cancellationToken).ConfigureAwait(false);

return response;
}

public async Task<UserSession> AuthenticationGetUserSessionAsync(string initialRequestToken)
public async Task<UserSession> AuthenticationGetUserSessionAsync(string initialRequestToken, CancellationToken cancellationToken = default(CancellationToken))
{
RestRequest request = _client.Create("authentication/session/new");
request.AddParameter("request_token", initialRequestToken);

RestResponse<UserSession> response = await request.ExecuteGet<UserSession>().ConfigureAwait(false);
RestResponse<UserSession> response = await request.ExecuteGet<UserSession>(cancellationToken).ConfigureAwait(false);

if (response.StatusCode == HttpStatusCode.Unauthorized)
throw new UnauthorizedAccessException();
Expand All @@ -38,26 +39,27 @@ public async Task<UserSession> AuthenticationGetUserSessionAsync(string initialR
/// </summary>
/// <param name="username">A valid TMDb username</param>
/// <param name="password">The passoword for the provided login</param>
public async Task<UserSession> AuthenticationGetUserSessionAsync(string username, string password)
/// <param name="cancellationToken">A cancellation token</param>
public async Task<UserSession> AuthenticationGetUserSessionAsync(string username, string password, CancellationToken cancellationToken = default(CancellationToken))
{
Token token = await AuthenticationRequestAutenticationTokenAsync().ConfigureAwait(false);
await AuthenticationValidateUserTokenAsync(token.RequestToken, username, password).ConfigureAwait(false);
return await AuthenticationGetUserSessionAsync(token.RequestToken).ConfigureAwait(false);
Token token = await AuthenticationRequestAutenticationTokenAsync(cancellationToken).ConfigureAwait(false);
await AuthenticationValidateUserTokenAsync(token.RequestToken, username, password, cancellationToken).ConfigureAwait(false);
return await AuthenticationGetUserSessionAsync(token.RequestToken, cancellationToken).ConfigureAwait(false);
}

public async Task<Token> AuthenticationRequestAutenticationTokenAsync()
public async Task<Token> AuthenticationRequestAutenticationTokenAsync(CancellationToken cancellationToken = default(CancellationToken))
{
RestRequest request = _client.Create("authentication/token/new");

RestResponse<Token> response = await request.ExecuteGet<Token>().ConfigureAwait(false);
RestResponse<Token> response = await request.ExecuteGet<Token>(cancellationToken).ConfigureAwait(false);
Token token = response;

token.AuthenticationCallback = response.GetHeader("Authentication-Callback");

return token;
}

public async Task AuthenticationValidateUserTokenAsync(string initialRequestToken, string username, string password)
public async Task AuthenticationValidateUserTokenAsync(string initialRequestToken, string username, string password, CancellationToken cancellationToken = default(CancellationToken))
{
RestRequest request = _client.Create("authentication/token/validate_with_login");
request.AddParameter("request_token", initialRequestToken);
Expand All @@ -67,7 +69,7 @@ public async Task AuthenticationValidateUserTokenAsync(string initialRequestToke
RestResponse response;
try
{
response = await request.ExecuteGet().ConfigureAwait(false);
response = await request.ExecuteGet(cancellationToken).ConfigureAwait(false);
}
catch (AggregateException ex)
{
Expand Down
Loading

0 comments on commit 37ceaab

Please # to comment.