Skip to content

Commit f0cc850

Browse files
committed
Add CancellationToken support
1 parent b0bb4cc commit f0cc850

5 files changed

Lines changed: 69 additions & 45 deletions

File tree

CloudConvert.API/CloudConvertAPI.cs

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,30 @@
1010
using CloudConvert.API.Models.JobModels;
1111
using CloudConvert.API.Models.TaskModels;
1212
using CloudConvert.API.Models;
13+
using System.Threading;
1314

1415
namespace CloudConvert.API
1516
{
1617
public interface ICloudConvertAPI
1718
{
1819
#region Jobs
19-
Task<ListResponse<JobResponse>> GetAllJobsAsync(JobListFilter jobFilter);
20-
Task<Response<JobResponse>> CreateJobAsync(JobCreateRequest request);
21-
Task<Response<JobResponse>> GetJobAsync(string id);
22-
Task<Response<JobResponse>> WaitJobAsync(string id);
23-
Task DeleteJobAsync(string id);
20+
Task<ListResponse<JobResponse>> GetAllJobsAsync(JobListFilter jobFilter, CancellationToken cancellationToken = default);
21+
Task<Response<JobResponse>> CreateJobAsync(JobCreateRequest request, CancellationToken cancellationToken = default);
22+
Task<Response<JobResponse>> GetJobAsync(string id, CancellationToken cancellationToken = default);
23+
Task<Response<JobResponse>> WaitJobAsync(string id, CancellationToken cancellationToken = default);
24+
Task DeleteJobAsync(string id, CancellationToken cancellationToken = default);
2425
#endregion
2526

2627
#region Tasks
27-
Task<ListResponse<TaskResponse>> GetAllTasksAsync(TaskListFilter jobFilter);
28-
Task<Response<TaskResponse>> CreateTaskAsync<T>(string operation, T request);
29-
Task<Response<TaskResponse>> GetTaskAsync(string id, string include = null);
30-
Task<Response<TaskResponse>> WaitTaskAsync(string id);
31-
Task DeleteTaskAsync(string id);
28+
Task<ListResponse<TaskResponse>> GetAllTasksAsync(TaskListFilter jobFilter, CancellationToken cancellationToken = default);
29+
Task<Response<TaskResponse>> CreateTaskAsync<T>(string operation, T request, CancellationToken cancellationToken = default);
30+
Task<Response<TaskResponse>> GetTaskAsync(string id, string include = null, CancellationToken cancellationToken = default);
31+
Task<Response<TaskResponse>> WaitTaskAsync(string id, CancellationToken cancellationToken = default);
32+
Task DeleteTaskAsync(string id, CancellationToken cancellationToken = default);
3233
#endregion
3334

34-
Task<string> UploadAsync(string url, byte[] file, string fileName, object parameters);
35-
Task<string> UploadAsync(string url, Stream file, string fileName, object parameters);
35+
Task<string> UploadAsync(string url, byte[] file, string fileName, object parameters, CancellationToken cancellationToken = default);
36+
Task<string> UploadAsync(string url, Stream file, string fileName, object parameters, CancellationToken cancellationToken = default);
3637
bool ValidateWebhookSignatures(string payloadString, string signature, string signingSecret);
3738
string CreateSignedUrl(string baseUrl, string signingSecret, JobCreateRequest job, string cacheKey = null);
3839
}
@@ -114,26 +115,32 @@ private HttpRequestMessage GetMultipartFormDataRequest(string endpoint, HttpMeth
114115
/// List all jobs. Requires the task.read scope.
115116
/// </summary>
116117
/// <param name="jobFilter"></param>
118+
/// <param name="cancellationToken"></param>
117119
/// <returns>
118120
/// The list of jobs. You can find details about the job model response in the documentation about the show jobs endpoint.
119121
/// </returns>
120-
public Task<ListResponse<JobResponse>> GetAllJobsAsync(JobListFilter jobFilter) => _restHelper.RequestAsync<ListResponse<JobResponse>>(GetRequest($"{_apiUrl}/jobs?filter[status]={jobFilter.Status}&filter[tag]={jobFilter.Tag}&include={jobFilter.Include}&per_page={jobFilter.PerPage}&page={jobFilter.Page}", HttpMethod.Get));
122+
public Task<ListResponse<JobResponse>> GetAllJobsAsync(JobListFilter jobFilter, CancellationToken cancellationToken = default)
123+
=> _restHelper.RequestAsync<ListResponse<JobResponse>>(GetRequest($"{_apiUrl}/jobs?filter[status]={jobFilter.Status}&filter[tag]={jobFilter.Tag}&include={jobFilter.Include}&per_page={jobFilter.PerPage}&page={jobFilter.Page}", HttpMethod.Get), cancellationToken);
121124

122125
/// <summary>
123126
/// Create a job with one ore more tasks. Requires the task.write scope.
124127
/// </summary>
125128
/// <param name="model"></param>
129+
/// <param name="cancellationToken"></param>
126130
/// <returns>
127131
/// The created job. You can find details about the job model response in the documentation about the show jobs endpoint.
128132
/// </returns>
129-
public Task<Response<JobResponse>> CreateJobAsync(JobCreateRequest model) => _restHelper.RequestAsync<Response<JobResponse>>(GetRequest($"{_apiUrl}/jobs", HttpMethod.Post, model));
133+
public Task<Response<JobResponse>> CreateJobAsync(JobCreateRequest model, CancellationToken cancellationToken = default)
134+
=> _restHelper.RequestAsync<Response<JobResponse>>(GetRequest($"{_apiUrl}/jobs", HttpMethod.Post, model), cancellationToken);
130135

131136
/// <summary>
132137
/// Show a job. Requires the task.read scope.
133138
/// </summary>
134139
/// <param name="id"></param>
140+
/// <param name="cancellationToken"></param>
135141
/// <returns></returns>
136-
public Task<Response<JobResponse>> GetJobAsync(string id) => _restHelper.RequestAsync<Response<JobResponse>>(GetRequest($"{_apiUrl}/jobs/{id}", HttpMethod.Get));
142+
public Task<Response<JobResponse>> GetJobAsync(string id, CancellationToken cancellationToken = default)
143+
=> _restHelper.RequestAsync<Response<JobResponse>>(GetRequest($"{_apiUrl}/jobs/{id}", HttpMethod.Get), cancellationToken);
137144

138145
/// <summary>
139146
/// Wait until the job status is finished or error. This makes the request block until the job has been completed. Requires the task.read scope.
@@ -145,20 +152,24 @@ private HttpRequestMessage GetMultipartFormDataRequest(string endpoint, HttpMeth
145152
/// Using an asynchronous approach with webhooks is beneficial in such cases.
146153
/// </summary>
147154
/// <param name="id"></param>
155+
/// <param name="cancellationToken"></param>
148156
/// <returns>
149157
/// The finished or failed job, including tasks. You can find details about the job model response in the documentation about the show job endpoint.
150158
/// </returns>
151-
public Task<Response<JobResponse>> WaitJobAsync(string id) => _restHelper.RequestAsync<Response<JobResponse>>(GetRequest($"{_apiSyncUrl}/jobs/{id}", HttpMethod.Get));
159+
public Task<Response<JobResponse>> WaitJobAsync(string id, CancellationToken cancellationToken = default)
160+
=> _restHelper.RequestAsync<Response<JobResponse>>(GetRequest($"{_apiSyncUrl}/jobs/{id}", HttpMethod.Get), cancellationToken);
152161

153162
/// <summary>
154163
/// Delete a job, including all tasks and data. Requires the task.write scope.
155164
/// Jobs are deleted automatically 24 hours after they have ended.
156165
/// </summary>
157166
/// <param name="id"></param>
167+
/// <param name="cancellationToken"></param>
158168
/// <returns>
159169
/// An empty response with HTTP Code 204.
160170
/// </returns>
161-
public Task DeleteJobAsync(string id) => _restHelper.RequestAsync<object>(GetRequest($"{_apiUrl}/jobs/{id}", HttpMethod.Delete));
171+
public Task DeleteJobAsync(string id, CancellationToken cancellationToken = default)
172+
=> _restHelper.RequestAsync<object>(GetRequest($"{_apiUrl}/jobs/{id}", HttpMethod.Delete), cancellationToken);
162173

163174
#endregion
164175

@@ -168,28 +179,34 @@ private HttpRequestMessage GetMultipartFormDataRequest(string endpoint, HttpMeth
168179
/// List all tasks with their status, payload and result. Requires the task.read scope.
169180
/// </summary>
170181
/// <param name="taskFilter"></param>
182+
/// <param name="cancellationToken"></param>
171183
/// <returns>
172184
/// The list of tasks. You can find details about the task model response in the documentation about the show tasks endpoint.
173185
/// </returns>
174-
public Task<ListResponse<TaskResponse>> GetAllTasksAsync(TaskListFilter taskFilter) => _restHelper.RequestAsync<ListResponse<TaskResponse>>(GetRequest($"{_apiUrl}/tasks?filter[job_id]={taskFilter.JobId}&filter[status]={taskFilter.Status}&filter[operation]={taskFilter.Operation}&include={taskFilter.Include}&per_page={taskFilter.PerPage}&page={taskFilter.Page}", HttpMethod.Get));
186+
public Task<ListResponse<TaskResponse>> GetAllTasksAsync(TaskListFilter taskFilter, CancellationToken cancellationToken = default)
187+
=> _restHelper.RequestAsync<ListResponse<TaskResponse>>(GetRequest($"{_apiUrl}/tasks?filter[job_id]={taskFilter.JobId}&filter[status]={taskFilter.Status}&filter[operation]={taskFilter.Operation}&include={taskFilter.Include}&per_page={taskFilter.PerPage}&page={taskFilter.Page}", HttpMethod.Get), cancellationToken);
175188

176189
/// <summary>
177190
/// Create task.
178191
/// </summary>
179192
/// <typeparam name="T"></typeparam>
180193
/// <param name="model"></param>
194+
/// <param name="cancellationToken"></param>
181195
/// <returns>
182196
/// The created task. You can find details about the task model response in the documentation about the show tasks endpoint.
183197
/// </returns>
184-
public Task<Response<TaskResponse>> CreateTaskAsync<T>(string operation, T model) => _restHelper.RequestAsync<Response<TaskResponse>>(GetRequest($"{_apiUrl}/{operation}", HttpMethod.Post, model));
198+
public Task<Response<TaskResponse>> CreateTaskAsync<T>(string operation, T model, CancellationToken cancellationToken = default)
199+
=> _restHelper.RequestAsync<Response<TaskResponse>>(GetRequest($"{_apiUrl}/{operation}", HttpMethod.Post, model), cancellationToken);
185200

186201
/// <summary>
187202
/// Show a task. Requires the task.read scope.
188203
/// </summary>
189204
/// <param name="id"></param>
190205
/// <param name="include"></param>
206+
/// <param name="cancellationToken"></param>
191207
/// <returns></returns>
192-
public Task<Response<TaskResponse>> GetTaskAsync(string id, string include = null) => _restHelper.RequestAsync<Response<TaskResponse>>(GetRequest($"{_apiUrl}/tasks/{id}?include={include}", HttpMethod.Get));
208+
public Task<Response<TaskResponse>> GetTaskAsync(string id, string include = null, CancellationToken cancellationToken = default)
209+
=> _restHelper.RequestAsync<Response<TaskResponse>>(GetRequest($"{_apiUrl}/tasks/{id}?include={include}", HttpMethod.Get), cancellationToken);
193210

194211
/// <summary>
195212
/// Wait until the task status is finished or error. This makes the request block until the task has been completed. Requires the task.read scope.
@@ -201,26 +218,32 @@ private HttpRequestMessage GetMultipartFormDataRequest(string endpoint, HttpMeth
201218
/// Using an asynchronous approach with webhooks is beneficial in such cases.
202219
/// </summary>
203220
/// <param name="id"></param>
221+
/// <param name="cancellationToken"></param>
204222
/// <returns>
205223
/// The finished or failed task. You can find details about the task model response in the documentation about the show tasks endpoint.
206224
/// </returns>
207-
public Task<Response<TaskResponse>> WaitTaskAsync(string id) => _restHelper.RequestAsync<Response<TaskResponse>>(GetRequest($"{_apiSyncUrl}/tasks/{id}", HttpMethod.Get));
225+
public Task<Response<TaskResponse>> WaitTaskAsync(string id, CancellationToken cancellationToken = default)
226+
=> _restHelper.RequestAsync<Response<TaskResponse>>(GetRequest($"{_apiSyncUrl}/tasks/{id}", HttpMethod.Get), cancellationToken);
208227

209228
/// <summary>
210229
/// Delete a task, including all data. Requires the task.write scope.
211230
/// Tasks are deleted automatically 24 hours after they have ended.
212231
/// </summary>
213232
/// <param name="id"></param>
233+
/// <param name="cancellationToken"></param>
214234
/// <returns>
215235
/// An empty response with HTTP Code 204.
216236
/// </returns>
217-
public Task DeleteTaskAsync(string id) => _restHelper.RequestAsync<object>(GetRequest($"{_apiUrl}/tasks/{id}", HttpMethod.Delete));
237+
public Task DeleteTaskAsync(string id, CancellationToken cancellationToken = default)
238+
=> _restHelper.RequestAsync<object>(GetRequest($"{_apiUrl}/tasks/{id}", HttpMethod.Delete), cancellationToken);
218239

219240
#endregion
220241

221-
public Task<string> UploadAsync(string url, byte[] file, string fileName, object parameters) => _restHelper.RequestAsync(GetMultipartFormDataRequest(url, HttpMethod.Post, new ByteArrayContent(file), fileName, GetParameters(parameters)));
242+
public Task<string> UploadAsync(string url, byte[] file, string fileName, object parameters, CancellationToken cancellationToken)
243+
=> _restHelper.RequestAsync(GetMultipartFormDataRequest(url, HttpMethod.Post, new ByteArrayContent(file), fileName, GetParameters(parameters)), cancellationToken);
222244

223-
public Task<string> UploadAsync(string url, Stream stream, string fileName, object parameters) => _restHelper.RequestAsync(GetMultipartFormDataRequest(url, HttpMethod.Post, new StreamContent(stream), fileName, GetParameters(parameters)));
245+
public Task<string> UploadAsync(string url, Stream stream, string fileName, object parameters, CancellationToken cancellationToken = default)
246+
=> _restHelper.RequestAsync(GetMultipartFormDataRequest(url, HttpMethod.Post, new StreamContent(stream), fileName, GetParameters(parameters)), cancellationToken);
224247

225248
public string CreateSignedUrl(string baseUrl, string signingSecret, JobCreateRequest job, string cacheKey = null)
226249
{

CloudConvert.API/RestHelper.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Net.Http;
22
using System.Text.Json;
3+
using System.Threading;
34
using System.Threading.Tasks;
45

56
namespace CloudConvert.API
@@ -19,18 +20,18 @@ internal RestHelper(HttpClient httpClient)
1920
_httpClient = httpClient;
2021
}
2122

22-
public async Task<T> RequestAsync<T>(HttpRequestMessage request)
23+
public async Task<T> RequestAsync<T>(HttpRequestMessage request, CancellationToken cancellationToken)
2324
{
24-
var response = await _httpClient.SendAsync(request);
25-
var responseRaw = await response.Content.ReadAsStringAsync();
25+
var response = await _httpClient.SendAsync(request, cancellationToken);
26+
var responseRaw = await response.Content.ReadAsStringAsync(cancellationToken);
2627

2728
return JsonSerializer.Deserialize<T>(responseRaw, DefaultJsonSerializerOptions.SerializerOptions);
2829
}
2930

30-
public async Task<string> RequestAsync(HttpRequestMessage request)
31+
public async Task<string> RequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
3132
{
32-
var response = await _httpClient.SendAsync(request);
33-
return await response.Content.ReadAsStringAsync();
33+
var response = await _httpClient.SendAsync(request, cancellationToken);
34+
return await response.Content.ReadAsStringAsync(cancellationToken);
3435
}
3536
}
3637
}

CloudConvert.API/WebApiHandler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,19 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
2525
{
2626
if (writeLog)
2727
{
28-
var requestString = request.Content != null ? await request.Content.ReadAsStringAsync() : string.Empty;
28+
var requestString = request.Content != null ? await request.Content.ReadAsStringAsync(cancellationToken) : string.Empty;
2929
}
3030

3131
var response = await base.SendAsync(request, cancellationToken);
3232

3333
if (writeLog)
3434
{
35-
string responseString = (await response.Content.ReadAsStringAsync()).TrimLengthWithEllipsis(20000);
35+
string responseString = (await response.Content.ReadAsStringAsync(cancellationToken)).TrimLengthWithEllipsis(20000);
3636
}
3737

3838
if ((int)response.StatusCode >= 400)
3939
{
40-
throw new WebApiException((await response.Content.ReadAsStringAsync()).TrimLengthWithEllipsis(20000));
40+
throw new WebApiException((await response.Content.ReadAsStringAsync(cancellationToken)).TrimLengthWithEllipsis(20000));
4141
}
4242

4343
return response;

CloudConvert.Test/TestJobs.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public async Task GetAllJobs()
2323

2424
var path = @"Responses/jobs.json";
2525
string json = File.ReadAllText(path);
26-
_cloudConvertAPI.Setup(cc => cc.GetAllJobsAsync(filter))
26+
_cloudConvertAPI.Setup(cc => cc.GetAllJobsAsync(filter, default))
2727
.ReturnsAsync(JsonSerializer.Deserialize<ListResponse<JobResponse>>(json, DefaultJsonSerializerOptions.SerializerOptions));
2828

2929
var jobs = await _cloudConvertAPI.Object.GetAllJobsAsync(filter);
@@ -55,7 +55,7 @@ public async Task CreateJob()
5555

5656
var path = AppDomain.CurrentDomain.BaseDirectory + @"Responses/job_created.json";
5757
string json = File.ReadAllText(path);
58-
_cloudConvertAPI.Setup(cc => cc.CreateJobAsync(req))
58+
_cloudConvertAPI.Setup(cc => cc.CreateJobAsync(req, default))
5959
.ReturnsAsync(JsonSerializer.Deserialize<Response<JobResponse>>(json, DefaultJsonSerializerOptions.SerializerOptions));
6060

6161
var job = await _cloudConvertAPI.Object.CreateJobAsync(req);
@@ -72,7 +72,7 @@ public async Task GetJob()
7272

7373
var path = AppDomain.CurrentDomain.BaseDirectory + @"Responses/job.json";
7474
string json = File.ReadAllText(path);
75-
_cloudConvertAPI.Setup(cc => cc.GetJobAsync(id))
75+
_cloudConvertAPI.Setup(cc => cc.GetJobAsync(id, default))
7676
.ReturnsAsync(JsonSerializer.Deserialize<Response<JobResponse>>(json, DefaultJsonSerializerOptions.SerializerOptions));
7777

7878
var job = await _cloudConvertAPI.Object.GetJobAsync(id);
@@ -89,7 +89,7 @@ public async Task WaitJob()
8989

9090
var path = AppDomain.CurrentDomain.BaseDirectory + @"Responses/job_finished.json";
9191
string json = File.ReadAllText(path);
92-
_cloudConvertAPI.Setup(cc => cc.WaitJobAsync(id))
92+
_cloudConvertAPI.Setup(cc => cc.WaitJobAsync(id, default))
9393
.ReturnsAsync(JsonSerializer.Deserialize<Response<JobResponse>>(json, DefaultJsonSerializerOptions.SerializerOptions));
9494

9595
var job = await _cloudConvertAPI.Object.WaitJobAsync(id);
@@ -104,7 +104,7 @@ public async Task DeleteJob()
104104
{
105105
string id = "cd82535b-0614-4b23-bbba-b24ab0e892f7";
106106

107-
_cloudConvertAPI.Setup(cc => cc.DeleteJobAsync(id));
107+
_cloudConvertAPI.Setup(cc => cc.DeleteJobAsync(id, default));
108108

109109
await _cloudConvertAPI.Object.DeleteJobAsync(id);
110110
}

0 commit comments

Comments
 (0)