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

Add support for CancellationTokens within client and services methods. #33

Merged
merged 6 commits into from
Oct 5, 2023
Merged
11 changes: 7 additions & 4 deletions src/Todoist.Net.Tests/RateLimitAwareRestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

using Xunit.Abstractions;
Expand Down Expand Up @@ -55,17 +56,19 @@ public async Task<HttpResponseMessage> ExecuteRequest(Func<Task<HttpResponseMess

public async Task<HttpResponseMessage> PostAsync(
string resource,
IEnumerable<KeyValuePair<string, string>> parameters)
IEnumerable<KeyValuePair<string, string>> parameters,
CancellationToken cancellationToken = default)
{
return await ExecuteRequest(() => _restClient.PostAsync(resource, parameters)).ConfigureAwait(false);
return await ExecuteRequest(() => _restClient.PostAsync(resource, parameters, cancellationToken)).ConfigureAwait(false);
}

public async Task<HttpResponseMessage> PostFormAsync(
string resource,
IEnumerable<KeyValuePair<string, string>> parameters,
IEnumerable<ByteArrayContent> files)
IEnumerable<ByteArrayContent> files,
CancellationToken cancellationToken = default)
{
return await ExecuteRequest(() => _restClient.PostFormAsync(resource, parameters, files))
return await ExecuteRequest(() => _restClient.PostFormAsync(resource, parameters, files, cancellationToken))
.ConfigureAwait(false);
}

Expand Down
31 changes: 27 additions & 4 deletions src/Todoist.Net/IAdvancedTodoistClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

using Todoist.Net.Models;
Expand All @@ -18,20 +20,37 @@ internal interface IAdvancedTodoistClient : ITodoistClient
/// </returns>
/// <exception cref="System.ArgumentNullException">Value cannot be null - commands.</exception>
/// <exception cref="System.AggregateException">Command execution exception.</exception>
/// <exception cref="ArgumentException">Value cannot be an empty collection.</exception>
/// <exception cref="HttpRequestException">API exception.</exception>
Task<string> ExecuteCommandsAsync(params Command[] commands);

/// <summary>
/// Executes the commands asynchronous.
/// </summary>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <param name="commands">The commands.</param>
/// <returns>
/// Returns <see cref="Task{TResult}" />. The task object representing the asynchronous operation
/// that at completion returns the commands execution sync_token.
/// </returns>
/// <exception cref="System.ArgumentNullException">Value cannot be null - commands.</exception>
/// <exception cref="System.AggregateException">Command execution exception.</exception>
/// <exception cref="ArgumentException">Value cannot be an empty collection.</exception>
/// <exception cref="HttpRequestException">API exception.</exception>
Task<string> ExecuteCommandsAsync(CancellationToken cancellationToken, params Command[] commands);

/// <summary>
/// Posts the request asynchronous.
/// </summary>
/// <typeparam name="T">Type of the result.</typeparam>
/// <param name="resource">The resource.</param>
/// <param name="parameters">The parameters.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>
/// The result.
/// </returns>
/// <exception cref="HttpRequestException">API exception.</exception>
Task<T> PostAsync<T>(string resource, ICollection<KeyValuePair<string, string>> parameters);
Task<T> PostAsync<T>(string resource, ICollection<KeyValuePair<string, string>> parameters, CancellationToken cancellationToken = default);

/// <summary>
/// Posts the asynchronous and returns a raw content.
Expand All @@ -40,36 +59,40 @@ internal interface IAdvancedTodoistClient : ITodoistClient
/// <param name="resource">The resource.</param>
/// <param name="parameters">The parameters.</param>
/// <param name="files">The files.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>
/// The result.
/// </returns>
/// <exception cref="HttpRequestException">API exception.</exception>
Task<T> PostFormAsync<T>(
string resource,
ICollection<KeyValuePair<string, string>> parameters,
IEnumerable<ByteArrayContent> files);
IEnumerable<ByteArrayContent> files,
CancellationToken cancellationToken = default);

/// <summary>
/// Posts the asynchronous and returns a raw content.
/// </summary>
/// <param name="resource">The resource.</param>
/// <param name="parameters">The parameters.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>
/// The result.
/// </returns>
/// <exception cref="HttpRequestException">API exception.</exception>
Task<string> PostRawAsync(string resource, ICollection<KeyValuePair<string, string>> parameters);
Task<string> PostRawAsync(string resource, ICollection<KeyValuePair<string, string>> parameters, CancellationToken cancellationToken = default);

/// <summary>
/// Processes the request asynchronous.
/// </summary>
/// <typeparam name="T">The type of the result.</typeparam>
/// <param name="resource">The resource.</param>
/// <param name="parameters">The parameters.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>
/// The result of the operation.
/// </returns>
/// <exception cref="HttpRequestException">API exception.</exception>
Task<T> ProcessPostAsync<T>(string resource, ICollection<KeyValuePair<string, string>> parameters);
Task<T> ProcessPostAsync<T>(string resource, ICollection<KeyValuePair<string, string>> parameters, CancellationToken cancellationToken = default);
}
}
27 changes: 27 additions & 0 deletions src/Todoist.Net/ITodoistClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

using Todoist.Net.Models;
Expand Down Expand Up @@ -135,6 +136,18 @@ public interface ITodoistClient
/// <exception cref="ArgumentNullException"><paramref name="resourceTypes"/> is <see langword="null"/></exception>
Task<Resources> GetResourcesAsync(params ResourceType[] resourceTypes);

/// <summary>
/// Gets the resources asynchronous. Returns all resources if zero resource type were passed.
/// </summary>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <param name="resourceTypes">The resource types.</param>
/// <returns>
/// The requested resources.
/// </returns>
/// <exception cref="HttpRequestException">API exception.</exception>
/// <exception cref="ArgumentNullException"><paramref name="resourceTypes"/> is <see langword="null"/></exception>
Task<Resources> GetResourcesAsync(CancellationToken cancellationToken, params ResourceType[] resourceTypes);

/// <summary>
/// Gets the resources asynchronous. Returns all resources if zero resource type were passed.
/// When sync token is passed in only tasks that have changed since last Sync will be returned.
Expand All @@ -147,5 +160,19 @@ public interface ITodoistClient
/// <exception cref="HttpRequestException">API exception.</exception>
/// <exception cref="ArgumentNullException"><paramref name="resourceTypes"/> is <see langword="null"/></exception>
Task<Resources> GetResourcesAsync(string syncToken, params ResourceType[] resourceTypes);

/// <summary>
/// Gets the resources asynchronous. Returns all resources if zero resource type were passed.
/// When sync token is passed in only tasks that have changed since last Sync will be returned.
/// </summary>
/// <param name="syncToken">The sync token returned from Todoist for increment sync</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <param name="resourceTypes">The resource types.</param>
/// <returns>
/// The requested resources.
/// </returns>
/// <exception cref="HttpRequestException">API exception.</exception>
/// <exception cref="ArgumentNullException"><paramref name="resourceTypes"/> is <see langword="null"/></exception>
Task<Resources> GetResourcesAsync(string syncToken, CancellationToken cancellationToken, params ResourceType[] resourceTypes);
}
}
11 changes: 8 additions & 3 deletions src/Todoist.Net/ITodoistRestClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace Todoist.Net
Expand All @@ -15,20 +16,24 @@ public interface ITodoistRestClient : IDisposable
/// </summary>
/// <param name="resource">The resource.</param>
/// <param name="parameters">The parameters.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>Returns <see cref="T:System.Threading.Tasks.Task" />.The task object representing the asynchronous operation.</returns>
/// <exception cref="System.ArgumentException">Value cannot be null or empty - resource</exception>
/// <exception cref="ArgumentNullException"><paramref name="parameters" /> is <see langword="null" /></exception>
Task<HttpResponseMessage> PostAsync(string resource, IEnumerable<KeyValuePair<string, string>> parameters);
Task<HttpResponseMessage> PostAsync(string resource, IEnumerable<KeyValuePair<string, string>> parameters, CancellationToken cancellationToken = default);

/// <summary>
/// Posts the form asynchronous.
/// </summary>
/// <param name="resource">The resource.</param>
/// <param name="parameters">The parameters.</param>
/// <param name="files">The files.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>The response.</returns>
Task<HttpResponseMessage> PostFormAsync(
string resource,
IEnumerable<KeyValuePair<string, string>> parameters,
IEnumerable<ByteArrayContent> files);
IEnumerable<ByteArrayContent> files,
CancellationToken cancellationToken = default);
}
}
14 changes: 9 additions & 5 deletions src/Todoist.Net/ITodoistTokenlessClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

using Todoist.Net.Exceptions;
Expand All @@ -17,6 +18,7 @@ public interface ITodoistTokenlessClient
/// </summary>
/// <param name="email">The email.</param>
/// <param name="password">The password.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>
/// A new instance of Todoist client.
/// </returns>
Expand All @@ -27,13 +29,14 @@ public interface ITodoistTokenlessClient
/// </exception>
/// <exception cref="HttpRequestException">API exception.</exception>
/// <exception cref="TodoistException">Unable to get token.</exception>
Task<TodoistClient> LoginAsync(string email, string password);
Task<TodoistClient> LoginAsync(string email, string password, CancellationToken cancellationToken = default);

/// <summary>
/// Logins user and returns a new instance of Todoist client.
/// </summary>
/// <param name="email">The email.</param>
/// <param name="oauthToken">The oauth token.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>
/// A new instance of Todoist client.
/// </returns>
Expand All @@ -44,17 +47,18 @@ public interface ITodoistTokenlessClient
/// </exception>
/// <exception cref="TodoistException">API exception.</exception>
/// <exception cref="HttpRequestException">API exception.</exception>
Task<TodoistClient> LoginWithGoogleAsync(string email, string oauthToken);
Task<TodoistClient> LoginWithGoogleAsync(string email, string oauthToken, CancellationToken cancellationToken = default);

/// <summary>
/// Registers a new user.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>
/// The user info.
/// </returns>
/// <exception cref="ArgumentNullException"><paramref name="user" /> is <see langword="null" /></exception>
/// <exception cref="HttpRequestException">API exception.</exception>
Task<UserInfo> RegisterUserAsync(UserBase user);
Task<UserInfo> RegisterUserAsync(UserBase user, CancellationToken cancellationToken = default);
}
}
}
16 changes: 5 additions & 11 deletions src/Todoist.Net/Services/ActivityService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

using Todoist.Net.Models;
Expand All @@ -18,18 +18,12 @@ internal ActivityService(IAdvancedTodoistClient todoistClient)
_todoistClient = todoistClient;
}

/// <summary>
/// Gets list of activity logs.
/// </summary>
/// <param name="filter">The filter.</param>
/// <returns>The activity log entries.</returns>
/// <exception cref="HttpRequestException">API exception.</exception>
/// <remarks>The activity log is only available for Todoist Premium.</remarks>
public Task<Activity> GetAsync(LogFilter filter = null)
/// <inheritdoc/>
public Task<Activity> GetAsync(LogFilter filter = null, CancellationToken cancellationToken = default)
{
var parameters = filter != null ? filter.ToParameters() : new List<KeyValuePair<string, string>>();

return _todoistClient.PostAsync<Activity>("activity/get", parameters);
return _todoistClient.PostAsync<Activity>("activity/get", parameters, cancellationToken);
}
}
}
16 changes: 6 additions & 10 deletions src/Todoist.Net/Services/BackupService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

using Todoist.Net.Models;
Expand All @@ -18,17 +18,13 @@ internal BackupService(IAdvancedTodoistClient todoistClient)
_todoistClient = todoistClient;
}

/// <summary>
/// Gets list of recent backup archives asynchronous.
/// </summary>
/// <returns>The backups information.</returns>
/// <remarks>Todoist creates a backup archive of users' data on a daily basis. Backup archives can also be accessed from the web app (Todoist Settings -> Backups).</remarks>
/// <exception cref="HttpRequestException">API exception.</exception>
public Task<IEnumerable<Backup>> GetAsync()
/// <inheritdoc/>
public Task<IEnumerable<Backup>> GetAsync(CancellationToken cancellationToken = default)
{
return _todoistClient.PostAsync<IEnumerable<Backup>>(
"backups/get",
new List<KeyValuePair<string, string>>());
new List<KeyValuePair<string, string>>(),
cancellationToken);
}
}
}
8 changes: 5 additions & 3 deletions src/Todoist.Net/Services/CommandServiceBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

using Todoist.Net.Models;
Expand Down Expand Up @@ -40,14 +41,15 @@ internal Command CreateEntityCommand(CommandType commandType, ComplexId id)
/// Executes the command asynchronous.
/// </summary>
/// <param name="command">The command.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>Returns <see cref="T:System.Threading.Tasks.Task" />.The task object representing the asynchronous operation.</returns>
/// <exception cref="HttpRequestException">API exception.</exception>
/// <exception cref="AggregateException">Command execution exception.</exception>
internal async Task ExecuteCommandAsync(Command command)
internal async Task ExecuteCommandAsync(Command command, CancellationToken cancellationToken = default)
{
if (_queue == null)
{
await TodoistClient.ExecuteCommandsAsync(command).ConfigureAwait(false);
await TodoistClient.ExecuteCommandsAsync(cancellationToken, command).ConfigureAwait(false);
return;
}

Expand Down
28 changes: 7 additions & 21 deletions src/Todoist.Net/Services/EmailService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

using Todoist.Net.Models;
Expand All @@ -20,34 +20,20 @@ internal EmailService(IAdvancedTodoistClient todoistClient)
_todoistClient = todoistClient;
}

/// <summary>
/// Disables an email address for an object.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <param name="objectId">The object identifier.</param>
/// <returns>Returns <see cref="T:System.Threading.Tasks.Task" />.The task object representing the asynchronous operation.</returns>
/// <exception cref="HttpRequestException">API exception.</exception>
public Task DisableAsync(ObjectType objectType, ComplexId objectId)
/// <inheritdoc/>
public Task DisableAsync(ObjectType objectType, ComplexId objectId, CancellationToken cancellationToken = default)
{
var parameters = CreateParameters(objectType, objectId);

return _todoistClient.PostRawAsync("emails/disable", parameters);
return _todoistClient.PostRawAsync("emails/disable", parameters, cancellationToken);
}

/// <summary>
/// Creates a new email address for an object, or gets an existing email.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <param name="objectId">The object identifier.</param>
/// <returns>
/// The email information.
/// </returns>
/// <exception cref="HttpRequestException">API exception.</exception>
public Task<EmailInfo> GetOrCreateAsync(ObjectType objectType, ComplexId objectId)
/// <inheritdoc/>
public Task<EmailInfo> GetOrCreateAsync(ObjectType objectType, ComplexId objectId, CancellationToken cancellationToken = default)
{
var parameters = CreateParameters(objectType, objectId);

return _todoistClient.PostAsync<EmailInfo>("emails/get_or_create", parameters);
return _todoistClient.PostAsync<EmailInfo>("emails/get_or_create", parameters, cancellationToken);
}

private static List<KeyValuePair<string, string>> CreateParameters(ObjectType objectType, ComplexId objectId)
Expand Down
Loading