Skip to content

Added request cancellation support #879

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

Merged
merged 2 commits into from
Nov 17, 2020
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Controllers;
Expand Down Expand Up @@ -27,15 +28,16 @@ public TodoCollectionsController(
}

[HttpPatch("{id}")]
public override async Task<IActionResult> PatchAsync(Guid id, [FromBody] TodoItemCollection resource)
public override async Task<IActionResult> PatchAsync(Guid id, [FromBody] TodoItemCollection resource, CancellationToken cancellationToken)
{
if (resource.Name == "PRE-ATTACH-TEST")
{
var targetTodoId = resource.TodoItems.First().Id;
var todoItemContext = _dbResolver.GetContext().Set<TodoItem>();
await todoItemContext.Where(ti => ti.Id == targetTodoId).FirstOrDefaultAsync();
await todoItemContext.Where(ti => ti.Id == targetTodoId).FirstOrDefaultAsync(cancellationToken);
}
return await base.PatchAsync(id, resource);

return await base.PatchAsync(id, resource, cancellationToken);
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Controllers.Annotations;
Expand Down Expand Up @@ -58,18 +59,18 @@ public CustomJsonApiController(
}

[HttpGet]
public async Task<IActionResult> GetAsync()
public async Task<IActionResult> GetAsync(CancellationToken cancellationToken)
{
var resources = await _resourceService.GetAsync();
var resources = await _resourceService.GetAsync(cancellationToken);
return Ok(resources);
}

[HttpGet("{id}")]
public async Task<IActionResult> GetAsync(TId id)
public async Task<IActionResult> GetAsync(TId id, CancellationToken cancellationToken)
{
try
{
var resource = await _resourceService.GetAsync(id);
var resource = await _resourceService.GetAsync(id, cancellationToken);
return Ok(resource);
}
catch (ResourceNotFoundException)
Expand All @@ -79,11 +80,11 @@ public async Task<IActionResult> GetAsync(TId id)
}

[HttpGet("{id}/relationships/{relationshipName}")]
public async Task<IActionResult> GetRelationshipsAsync(TId id, string relationshipName)
public async Task<IActionResult> GetRelationshipsAsync(TId id, string relationshipName, CancellationToken cancellationToken)
{
try
{
var relationship = await _resourceService.GetRelationshipAsync(id, relationshipName);
var relationship = await _resourceService.GetRelationshipAsync(id, relationshipName, cancellationToken);
return Ok(relationship);
}
catch (ResourceNotFoundException)
Expand All @@ -93,35 +94,35 @@ public async Task<IActionResult> GetRelationshipsAsync(TId id, string relationsh
}

[HttpGet("{id}/{relationshipName}")]
public async Task<IActionResult> GetRelationshipAsync(TId id, string relationshipName)
public async Task<IActionResult> GetRelationshipAsync(TId id, string relationshipName, CancellationToken cancellationToken)
{
var relationship = await _resourceService.GetSecondaryAsync(id, relationshipName);
var relationship = await _resourceService.GetSecondaryAsync(id, relationshipName, cancellationToken);
return Ok(relationship);
}

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody] T resource)
public async Task<IActionResult> PostAsync([FromBody] T resource, CancellationToken cancellationToken)
{
if (resource == null)
return UnprocessableEntity();

if (_options.AllowClientGeneratedIds && !string.IsNullOrEmpty(resource.StringId))
return Forbidden();

resource = await _resourceService.CreateAsync(resource);
resource = await _resourceService.CreateAsync(resource, cancellationToken);

return Created($"{HttpContext.Request.Path}/{resource.Id}", resource);
}

[HttpPatch("{id}")]
public async Task<IActionResult> PatchAsync(TId id, [FromBody] T resource)
public async Task<IActionResult> PatchAsync(TId id, [FromBody] T resource, CancellationToken cancellationToken)
{
if (resource == null)
return UnprocessableEntity();

try
{
var updated = await _resourceService.UpdateAsync(id, resource);
var updated = await _resourceService.UpdateAsync(id, resource, cancellationToken);
return Ok(updated);
}
catch (ResourceNotFoundException)
Expand All @@ -131,17 +132,17 @@ public async Task<IActionResult> PatchAsync(TId id, [FromBody] T resource)
}

[HttpPatch("{id}/relationships/{relationshipName}")]
public async Task<IActionResult> PatchRelationshipAsync(TId id, string relationshipName, [FromBody] object secondaryResourceIds)
public async Task<IActionResult> PatchRelationshipAsync(TId id, string relationshipName, [FromBody] object secondaryResourceIds, CancellationToken cancellationToken)
{
await _resourceService.SetRelationshipAsync(id, relationshipName, secondaryResourceIds);
await _resourceService.SetRelationshipAsync(id, relationshipName, secondaryResourceIds, cancellationToken);

return Ok();
}

[HttpDelete("{id}")]
public async Task<IActionResult> DeleteAsync(TId id)
public async Task<IActionResult> DeleteAsync(TId id, CancellationToken cancellationToken)
{
await _resourceService.DeleteAsync(id);
await _resourceService.DeleteAsync(id, cancellationToken);
return NoContent();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Controllers;
Expand Down Expand Up @@ -36,21 +37,31 @@ public TodoItemsTestController(
{ }

[HttpGet]
public override async Task<IActionResult> GetAsync() => await base.GetAsync();
public override async Task<IActionResult> GetAsync(CancellationToken cancellationToken)
{
return await base.GetAsync(cancellationToken);
}

[HttpGet("{id}")]
public override async Task<IActionResult> GetAsync(int id) => await base.GetAsync(id);
public override async Task<IActionResult> GetAsync(int id, CancellationToken cancellationToken)
{
return await base.GetAsync(id, cancellationToken);
}

[HttpGet("{id}/{relationshipName}")]
public override async Task<IActionResult> GetSecondaryAsync(int id, string relationshipName)
=> await base.GetSecondaryAsync(id, relationshipName);
public override async Task<IActionResult> GetSecondaryAsync(int id, string relationshipName, CancellationToken cancellationToken)
{
return await base.GetSecondaryAsync(id, relationshipName, cancellationToken);
}

[HttpGet("{id}/relationships/{relationshipName}")]
public override async Task<IActionResult> GetRelationshipAsync(int id, string relationshipName)
=> await base.GetRelationshipAsync(id, relationshipName);
public override async Task<IActionResult> GetRelationshipAsync(int id, string relationshipName, CancellationToken cancellationToken)
{
return await base.GetRelationshipAsync(id, relationshipName, cancellationToken);
}

[HttpPost]
public override async Task<IActionResult> PostAsync([FromBody] TodoItem resource)
public override async Task<IActionResult> PostAsync([FromBody] TodoItem resource, CancellationToken cancellationToken)
{
await Task.Yield();

Expand All @@ -62,11 +73,13 @@ public override async Task<IActionResult> PostAsync([FromBody] TodoItem resource

[HttpPost("{id}/relationships/{relationshipName}")]
public override async Task<IActionResult> PostRelationshipAsync(
int id, string relationshipName, [FromBody] ISet<IIdentifiable> secondaryResourceIds)
=> await base.PostRelationshipAsync(id, relationshipName, secondaryResourceIds);
int id, string relationshipName, [FromBody] ISet<IIdentifiable> secondaryResourceIds, CancellationToken cancellationToken)
{
return await base.PostRelationshipAsync(id, relationshipName, secondaryResourceIds, cancellationToken);
}

[HttpPatch("{id}")]
public override async Task<IActionResult> PatchAsync(int id, [FromBody] TodoItem resource)
public override async Task<IActionResult> PatchAsync(int id, [FromBody] TodoItem resource, CancellationToken cancellationToken)
{
await Task.Yield();

Expand All @@ -75,19 +88,23 @@ public override async Task<IActionResult> PatchAsync(int id, [FromBody] TodoItem

[HttpPatch("{id}/relationships/{relationshipName}")]
public override async Task<IActionResult> PatchRelationshipAsync(
int id, string relationshipName, [FromBody] object secondaryResourceIds)
=> await base.PatchRelationshipAsync(id, relationshipName, secondaryResourceIds);
int id, string relationshipName, [FromBody] object secondaryResourceIds, CancellationToken cancellationToken)
{
return await base.PatchRelationshipAsync(id, relationshipName, secondaryResourceIds, cancellationToken);
}

[HttpDelete("{id}")]
public override async Task<IActionResult> DeleteAsync(int id)
public override async Task<IActionResult> DeleteAsync(int id, CancellationToken cancellationToken)
{
await Task.Yield();

return NotFound();
}

[HttpDelete("{id}/relationships/{relationshipName}")]
public override async Task<IActionResult> DeleteRelationshipAsync(int id, string relationshipName, [FromBody] ISet<IIdentifiable> secondaryResourceIds)
=> await base.DeleteRelationshipAsync(id, relationshipName, secondaryResourceIds);
public override async Task<IActionResult> DeleteRelationshipAsync(int id, string relationshipName, [FromBody] ISet<IIdentifiable> secondaryResourceIds, CancellationToken cancellationToken)
{
return await base.DeleteRelationshipAsync(id, relationshipName, secondaryResourceIds, cancellationToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Threading;
using System.Threading.Tasks;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Hooks.Internal;
Expand Down Expand Up @@ -27,9 +28,9 @@ public CustomArticleService(
resourceChangeTracker, resourceFactory, hookExecutor)
{ }

public override async Task<Article> GetAsync(int id)
public override async Task<Article> GetAsync(int id, CancellationToken cancellationToken)
{
var resource = await base.GetAsync(id);
var resource = await base.GetAsync(id, cancellationToken);
resource.Caption = "None for you Glen Coco";
return resource;
}
Expand Down
31 changes: 16 additions & 15 deletions src/Examples/NoEntityFrameworkExample/Services/WorkItemService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Dapper;
using JsonApiDotNetCore.Resources;
Expand All @@ -22,67 +23,67 @@ public WorkItemService(IConfiguration configuration)
_connectionString = configuration["Data:DefaultConnection"].Replace("###", postgresPassword);
}

public async Task<IReadOnlyCollection<WorkItem>> GetAsync()
public async Task<IReadOnlyCollection<WorkItem>> GetAsync(CancellationToken cancellationToken)
{
return (await QueryAsync(async connection =>
await connection.QueryAsync<WorkItem>(@"select * from ""WorkItems"""))).ToList();
await connection.QueryAsync<WorkItem>(new CommandDefinition(@"select * from ""WorkItems""", cancellationToken: cancellationToken)))).ToList();
}

public async Task<WorkItem> GetAsync(int id)
public async Task<WorkItem> GetAsync(int id, CancellationToken cancellationToken)
{
var query = await QueryAsync(async connection =>
await connection.QueryAsync<WorkItem>(@"select * from ""WorkItems"" where ""Id""=@id", new {id}));
await connection.QueryAsync<WorkItem>(new CommandDefinition(@"select * from ""WorkItems"" where ""Id""=@id", new {id}, cancellationToken: cancellationToken)));

return query.Single();
}

public Task<object> GetSecondaryAsync(int id, string relationshipName)
public Task<object> GetSecondaryAsync(int id, string relationshipName, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

public Task<object> GetRelationshipAsync(int id, string relationshipName)
public Task<object> GetRelationshipAsync(int id, string relationshipName, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

public async Task<WorkItem> CreateAsync(WorkItem resource)
public async Task<WorkItem> CreateAsync(WorkItem resource, CancellationToken cancellationToken)
{
return (await QueryAsync(async connection =>
{
var query =
@"insert into ""WorkItems"" (""Title"", ""IsBlocked"", ""DurationInHours"", ""ProjectId"") values " +
@"(@description, @isLocked, @ordinal, @uniqueId) returning ""Id"", ""Title"", ""IsBlocked"", ""DurationInHours"", ""ProjectId""";

return await connection.QueryAsync<WorkItem>(query, new
return await connection.QueryAsync<WorkItem>(new CommandDefinition(query, new
{
description = resource.Title, ordinal = resource.DurationInHours, uniqueId = resource.ProjectId, isLocked = resource.IsBlocked
});
}, cancellationToken: cancellationToken));
})).SingleOrDefault();
}

public Task AddToToManyRelationshipAsync(int primaryId, string relationshipName, ISet<IIdentifiable> secondaryResourceIds)
public Task AddToToManyRelationshipAsync(int primaryId, string relationshipName, ISet<IIdentifiable> secondaryResourceIds, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

public Task<WorkItem> UpdateAsync(int id, WorkItem resource)
public Task<WorkItem> UpdateAsync(int id, WorkItem resource, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

public Task SetRelationshipAsync(int primaryId, string relationshipName, object secondaryResourceIds)
public Task SetRelationshipAsync(int primaryId, string relationshipName, object secondaryResourceIds, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

public async Task DeleteAsync(int id)
public async Task DeleteAsync(int id, CancellationToken cancellationToken)
{
await QueryAsync(async connection =>
await connection.QueryAsync<WorkItem>(@"delete from ""WorkItems"" where ""Id""=@id", new {id}));
await connection.QueryAsync<WorkItem>(new CommandDefinition(@"delete from ""WorkItems"" where ""Id""=@id", new {id}, cancellationToken: cancellationToken)));
}

public Task RemoveFromToManyRelationshipAsync(int primaryId, string relationshipName, ISet<IIdentifiable> secondaryResourceIds)
public Task RemoveFromToManyRelationshipAsync(int primaryId, string relationshipName, ISet<IIdentifiable> secondaryResourceIds, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
Expand Down
6 changes: 5 additions & 1 deletion src/Examples/ReportsExample/Controllers/ReportsController.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Threading;
using System.Threading.Tasks;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Controllers;
Expand All @@ -19,6 +20,9 @@ public ReportsController(
{ }

[HttpGet]
public override async Task<IActionResult> GetAsync() => await base.GetAsync();
public override async Task<IActionResult> GetAsync(CancellationToken cancellationToken)
{
return await base.GetAsync(cancellationToken);
}
}
}
3 changes: 2 additions & 1 deletion src/Examples/ReportsExample/Services/ReportService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JsonApiDotNetCore.Services;
using Microsoft.Extensions.Logging;
Expand All @@ -16,7 +17,7 @@ public ReportService(ILoggerFactory loggerFactory)
_logger = loggerFactory.CreateLogger<ReportService>();
}

public Task<IReadOnlyCollection<Report>> GetAsync()
public Task<IReadOnlyCollection<Report>> GetAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("GetAsync");

Expand Down
Loading