ValueTask conversion for controllers

This commit is contained in:
Jordan Dominion
2023-10-07 15:53:35 -04:00
parent fc52eae7ca
commit 8166cd3629
21 changed files with 203 additions and 194 deletions
@@ -126,7 +126,7 @@ namespace Tgstation.Server.Host.Controllers
/// Get <see cref="AdministrationResponse"/> server information.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="200">Retrieved <see cref="AdministrationResponse"/> data successfully.</response>
/// <response code="424">The GitHub API rate limit was hit. See response header Retry-After.</response>
/// <response code="429">A GitHub API error occurred. See error message for details.</response>
@@ -135,7 +135,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(AdministrationResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 424)]
[ProducesResponseType(typeof(ErrorMessageResponse), 429)]
public async Task<IActionResult> Read(CancellationToken cancellationToken)
public async ValueTask<IActionResult> Read(CancellationToken cancellationToken)
{
try
{
@@ -188,7 +188,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="ServerUpdateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="202">Update has been started successfully.</response>
/// <response code="410">The requested release version could not be found in the target GitHub repository.</response>
/// <response code="422">Upgrade operations are unavailable due to the launch configuration of TGS.</response>
@@ -201,7 +201,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(ErrorMessageResponse), 422)]
[ProducesResponseType(typeof(ErrorMessageResponse), 424)]
[ProducesResponseType(typeof(ErrorMessageResponse), 429)]
public async Task<IActionResult> Update([FromBody] ServerUpdateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] ServerUpdateRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -232,14 +232,14 @@ namespace Tgstation.Server.Host.Controllers
/// <summary>
/// Attempts to restart the server.
/// </summary>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="204">Restart begun successfully.</response>
/// <response code="422">Restart operations are unavailable due to the launch configuration of TGS.</response>
[HttpDelete]
[TgsAuthorize(AdministrationRights.RestartHost)]
[ProducesResponseType(204)]
[ProducesResponseType(typeof(ErrorMessageResponse), 422)]
public async Task<IActionResult> Delete()
public async ValueTask<IActionResult> Delete()
{
try
{
@@ -264,14 +264,14 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Listed logs successfully.</response>
/// <response code="409">An IO error occurred while listing.</response>
[HttpGet(Routes.Logs)]
[TgsAuthorize(AdministrationRights.DownloadLogs)]
[ProducesResponseType(typeof(PaginatedResponse<LogFileResponse>), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 409)]
public Task<IActionResult> ListLogs([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
public ValueTask<IActionResult> ListLogs([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
=> Paginated(
async () =>
{
@@ -317,14 +317,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="path">The path to download.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Downloaded <see cref="LogFileResponse"/> successfully.</response>
/// <response code="409">An IO error occurred while downloading.</response>
[HttpGet(Routes.Logs + "/{*path}")]
[TgsAuthorize(AdministrationRights.DownloadLogs)]
[ProducesResponseType(typeof(LogFileResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 409)]
public async Task<IActionResult> GetLog(string path, CancellationToken cancellationToken)
public async ValueTask<IActionResult> GetLog(string path, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(path);
@@ -369,8 +369,8 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="newVersion">The <see cref="Version"/> being updated to.</param>
/// <param name="attemptingUpload">If an upload is being attempted.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
async Task<IActionResult> AttemptInitiateUpdate(Version newVersion, bool attemptingUpload, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
async ValueTask<IActionResult> AttemptInitiateUpdate(Version newVersion, bool attemptingUpload, CancellationToken cancellationToken)
{
IFileUploadTicket uploadTicket = attemptingUpload
? fileTransferService.CreateUpload(FileUploadStreamKind.None)
@@ -257,9 +257,9 @@ namespace Tgstation.Server.Host.Controllers
/// Performs validation a request.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in an appropriate <see cref="IActionResult"/> on validation failure, <see langword="null"/> otherwise.</returns>
protected virtual Task<IActionResult> ValidateRequest(CancellationToken cancellationToken)
=> Task.FromResult<IActionResult>(null);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in an appropriate <see cref="IActionResult"/> on validation failure, <see langword="null"/> otherwise.</returns>
protected virtual ValueTask<IActionResult> ValidateRequest(CancellationToken cancellationToken)
=> ValueTask.FromResult<IActionResult>(null);
/// <summary>
/// Response for missing/Invalid headers.
@@ -299,10 +299,10 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="pageQuery">The requested page from the query.</param>
/// <param name="pageSizeQuery">The requested page size from the query.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
protected Task<IActionResult> Paginated<TModel>(
Func<Task<PaginatableResult<TModel>>> queryGenerator,
Func<TModel, Task> resultTransformer,
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
protected ValueTask<IActionResult> Paginated<TModel>(
Func<ValueTask<PaginatableResult<TModel>>> queryGenerator,
Func<TModel, ValueTask> resultTransformer,
int? pageQuery,
int? pageSizeQuery,
CancellationToken cancellationToken) => PaginatedImpl(
@@ -317,15 +317,15 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <typeparam name="TModel">The <see cref="Type"/> of model being generated.</typeparam>
/// <typeparam name="TApiModel">The <see cref="Type"/> of model being returned.</typeparam>
/// <param name="queryGenerator">A <see cref="Func{TResult}"/> resulting in a <see cref="Task{TResult}"/> resulting in the generated <see cref="PaginatableResult{TModel}"/>.</param>
/// <param name="queryGenerator">A <see cref="Func{TResult}"/> resulting in a <see cref="ValueTask{TResult}"/> resulting in the generated <see cref="PaginatableResult{TModel}"/>.</param>
/// <param name="resultTransformer">A <see cref="Func{T, TResult}"/> to transform the <typeparamref name="TApiModel"/>s after being queried.</param>
/// <param name="pageQuery">The requested page from the query.</param>
/// <param name="pageSizeQuery">The requested page size from the query.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
protected Task<IActionResult> Paginated<TModel, TApiModel>(
Func<Task<PaginatableResult<TModel>>> queryGenerator,
Func<TApiModel, Task> resultTransformer,
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
protected ValueTask<IActionResult> Paginated<TModel, TApiModel>(
Func<ValueTask<PaginatableResult<TModel>>> queryGenerator,
Func<TApiModel, ValueTask> resultTransformer,
int? pageQuery,
int? pageSizeQuery,
CancellationToken cancellationToken)
@@ -342,15 +342,15 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <typeparam name="TModel">The <see cref="Type"/> of model being generated. If different from <typeparamref name="TResultModel"/>, must implement <see cref="IApiTransformable{TApiModel}"/> for <typeparamref name="TResultModel"/>.</typeparam>
/// <typeparam name="TResultModel">The <see cref="Type"/> of model being returned.</typeparam>
/// <param name="queryGenerator">A <see cref="Func{TResult}"/> resulting in a <see cref="Task{TResult}"/> resulting in the generated <see cref="PaginatableResult{TModel}"/>.</param>
/// <param name="queryGenerator">A <see cref="Func{TResult}"/> resulting in a <see cref="ValueTask{TResult}"/> resulting in the generated <see cref="PaginatableResult{TModel}"/>.</param>
/// <param name="resultTransformer">A <see cref="Func{T, TResult}"/> to transform the <typeparamref name="TResultModel"/>s after being queried.</param>
/// <param name="pageQuery">The requested page from the query.</param>
/// <param name="pageSizeQuery">The requested page size from the query.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
async Task<IActionResult> PaginatedImpl<TModel, TResultModel>(
Func<Task<PaginatableResult<TModel>>> queryGenerator,
Func<TResultModel, Task> resultTransformer,
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
async ValueTask<IActionResult> PaginatedImpl<TModel, TResultModel>(
Func<ValueTask<PaginatableResult<TModel>>> queryGenerator,
Func<TResultModel, ValueTask> resultTransformer,
int? pageQuery,
int? pageSizeQuery,
CancellationToken cancellationToken)
@@ -74,9 +74,9 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="data">JSON encoded <see cref="BridgeParameters"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
[HttpGet]
public async Task<IActionResult> Process([FromQuery] string data, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Process([FromQuery] string data, CancellationToken cancellationToken)
{
// Nothing to see here
var remoteIP = Request.HttpContext.Connection.RemoteIpAddress;
@@ -74,14 +74,14 @@ namespace Tgstation.Server.Host.Controllers
/// <summary>
/// Gets the active <see cref="ByondResponse.Version"/>.
/// </summary>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="200">Retrieved version information successfully.</response>
[HttpGet]
[TgsAuthorize(ByondRights.ReadActive)]
[ProducesResponseType(typeof(ByondResponse), 200)]
public Task<IActionResult> Read()
public ValueTask<IActionResult> Read()
=> WithComponentInstance(instance =>
Task.FromResult<IActionResult>(
ValueTask.FromResult<IActionResult>(
Json(new ByondResponse
{
Version = instance.ByondManager.ActiveVersion,
@@ -93,15 +93,15 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="200">Retrieved version information successfully.</response>
[HttpGet(Routes.List)]
[TgsAuthorize(ByondRights.ListInstalled)]
[ProducesResponseType(typeof(PaginatedResponse<ByondResponse>), 200)]
public Task<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
public ValueTask<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
=> WithComponentInstance(
instance => Paginated(
() => Task.FromResult(
() => ValueTask.FromResult(
new PaginatableResult<ByondResponse>(
instance
.ByondManager
@@ -122,7 +122,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="ByondVersionRequest"/> containing the <see cref="Version"/> to switch to.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="200">Switched active version successfully.</response>
/// <response code="202">Created <see cref="Job"/> to install and switch active version successfully.</response>
[HttpPost]
@@ -130,7 +130,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(ByondInstallResponse), 200)]
[ProducesResponseType(typeof(ByondInstallResponse), 202)]
#pragma warning disable CA1506 // TODO: Decomplexify
public async Task<IActionResult> Update([FromBody] ByondVersionRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] ByondVersionRequest model, CancellationToken cancellationToken)
#pragma warning restore CA1506
{
ArgumentNullException.ThrowIfNull(model);
@@ -257,7 +257,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="ByondVersionDeleteRequest"/> containing the <see cref="Version"/> to delete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="202">Created <see cref="Job"/> to delete target version successfully.</response>
/// <response code="409">Attempted to delete the active BYOND <see cref="Version"/>.</response>
/// <response code="410">The <see cref="ByondVersionDeleteRequest.Version"/> specified was not installed.</response>
@@ -266,7 +266,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(JobResponse), 202)]
[ProducesResponseType(typeof(ErrorMessageResponse), 409)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> Delete([FromBody] ByondVersionDeleteRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Delete([FromBody] ByondVersionDeleteRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -282,12 +282,12 @@ namespace Tgstation.Server.Host.Controllers
var byondManager = instance.ByondManager;
if (version == byondManager.ActiveVersion)
return Task.FromResult<IActionResult>(
return ValueTask.FromResult<IActionResult>(
Conflict(new ErrorMessageResponse(ErrorCode.ByondCannotDeleteActiveVersion)));
var versionNotInstalled = !byondManager.InstalledVersions.Any(x => x == version);
return Task.FromResult<IActionResult>(
return ValueTask.FromResult<IActionResult>(
versionNotInstalled
? this.Gone()
: null);
@@ -99,12 +99,12 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="ChatBotCreateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="201">Created <see cref="ChatBot"/> successfully.</response>
[HttpPut]
[TgsAuthorize(ChatBotRights.Create)]
[ProducesResponseType(typeof(ChatBotResponse), 201)]
public async Task<IActionResult> Create([FromBody] ChatBotCreateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Create([FromBody] ChatBotCreateRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -173,12 +173,12 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="EntityId.Id"/> to delete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="204">Chat bot deleted or does not exist.</response>
[HttpDelete("{id}")]
[TgsAuthorize(ChatBotRights.Delete)]
[ProducesResponseType(204)]
public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Delete(long id, CancellationToken cancellationToken)
=> await WithComponentInstance(
async instance =>
{
@@ -200,16 +200,16 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="200">Listed chat bots successfully.</response>
[HttpGet(Routes.List)]
[TgsAuthorize(ChatBotRights.Read)]
[ProducesResponseType(typeof(PaginatedResponse<ChatBotResponse>), 200)]
public Task<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
public ValueTask<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
{
var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
return Paginated<ChatBot, ChatBotResponse>(
() => Task.FromResult(
() => ValueTask.FromResult(
new PaginatableResult<ChatBot>(
DatabaseContext
.ChatBots
@@ -222,7 +222,7 @@ namespace Tgstation.Server.Host.Controllers
if (!connectionStrings)
chatBot.ConnectionString = null;
return Task.CompletedTask;
return ValueTask.CompletedTask;
},
page,
pageSize,
@@ -234,14 +234,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="EntityId.Id"/> to retrieve.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="200">Retrieved <see cref="ChatBot"/> successfully.</response>
/// <response code="410">The <see cref="ChatBot"/> with the given ID does not exist in this instance.</response>
[HttpGet("{id}")]
[TgsAuthorize(ChatBotRights.Read)]
[ProducesResponseType(typeof(ChatBotResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> GetId(long id, CancellationToken cancellationToken)
{
var query = DatabaseContext.ChatBots
.AsQueryable()
@@ -265,7 +265,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="ChatBotUpdateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="200">Update applied successfully.</response>
/// <response code="204">Update applied successfully. <see cref="ChatBot"/> not returned based on user permissions.</response>
/// <response code="410">The <see cref="ChatBot"/> with the given ID does not exist in this instance.</response>
@@ -275,7 +275,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(204)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
#pragma warning disable CA1502, CA1506 // TODO: Decomplexify
public async Task<IActionResult> Update([FromBody] ChatBotUpdateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] ChatBotUpdateRequest model, CancellationToken cancellationToken)
#pragma warning restore CA1502, CA1506
{
ArgumentNullException.ThrowIfNull(model);
@@ -60,7 +60,7 @@ namespace Tgstation.Server.Host.Controllers
}
/// <inheritdoc />
protected override async Task<IActionResult> ValidateRequest(CancellationToken cancellationToken)
protected override async ValueTask<IActionResult> ValidateRequest(CancellationToken cancellationToken)
{
if (!useInstanceRequestHeader)
return null;
@@ -113,11 +113,11 @@ namespace Tgstation.Server.Host.Controllers
/// <summary>
/// Run a given <paramref name="action"/> with the relevant <see cref="IInstance"/>.
/// </summary>
/// <param name="action">A <see cref="Func{T, TResult}"/> accepting the <see cref="IInstance"/> and returning a <see cref="Task{TResult}"/> with the <see cref="IActionResult"/>.</param>
/// <param name="action">A <see cref="Func{T, TResult}"/> accepting the <see cref="IInstance"/> and returning a <see cref="ValueTask{TResult}"/> with the <see cref="IActionResult"/>.</param>
/// <param name="instance">The <see cref="Models.Instance"/> to grab. If <see langword="null"/>, <see cref="ApiController.Instance"/> will be used.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> that should be returned.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> that should be returned.</returns>
/// <remarks>The context of <paramref name="action"/> should be as small as possible so as to avoid race conditions. This function can return a <see cref="ConflictResult"/> if the requested instance was offline.</remarks>
protected async Task<IActionResult> WithComponentInstance(Func<IInstanceCore, Task<IActionResult>> action, Models.Instance instance = null)
protected async ValueTask<IActionResult> WithComponentInstance(Func<IInstanceCore, ValueTask<IActionResult>> action, Models.Instance instance = null)
{
ArgumentNullException.ThrowIfNull(action);
@@ -58,14 +58,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="ConfigurationFileRequest"/> representing the file.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="200">File updated successfully.</response>
/// <response code="202">File upload ticket created successfully.</response>
[HttpPost]
[TgsAuthorize(ConfigurationRights.Write)]
[ProducesResponseType(typeof(ConfigurationFileResponse), 200)]
[ProducesResponseType(typeof(ConfigurationFileResponse), 202)]
public async Task<IActionResult> Update([FromBody] ConfigurationFileRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] ConfigurationFileRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
if (ForbidDueToModeConflicts(model.Path, out var systemIdentity))
@@ -109,7 +109,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="filePath">The path of the file to get.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>>
/// <response code="200">File read successfully.</response>>
/// <response code="410">File does not currently exist.</response>
[HttpGet(Routes.File + "/{*filePath}")]
@@ -117,7 +117,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(ConfigurationFileResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 409)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> File(string filePath, CancellationToken cancellationToken)
public async ValueTask<IActionResult> File(string filePath, CancellationToken cancellationToken)
{
if (ForbidDueToModeConflicts(filePath, out var systemIdentity))
return Forbid();
@@ -158,7 +158,7 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="200">Directory listed successfully.</response>>
/// <response code="410">Directory does not currently exist.</response>
[HttpGet(Routes.List + "/{*directoryPath}")]
@@ -166,7 +166,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(PaginatedResponse<ConfigurationFileResponse>), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 409)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public Task<IActionResult> Directory(
public ValueTask<IActionResult> Directory(
string directoryPath,
[FromQuery] int? page,
[FromQuery] int? pageSize,
@@ -222,11 +222,11 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
[HttpGet(Routes.List)]
[TgsAuthorize(ConfigurationRights.List)]
[ProducesResponseType(typeof(PaginatedResponse<ConfigurationFileResponse>), 200)]
public Task<IActionResult> List(
public ValueTask<IActionResult> List(
[FromQuery] int? page,
[FromQuery] int? pageSize,
CancellationToken cancellationToken) => Directory(null, page, pageSize, cancellationToken);
@@ -236,7 +236,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="ConfigurationFileRequest"/> representing the directory.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> for the operation.</returns>
/// <response code="200">Directory already exists.</response>
/// <response code="201">Directory created successfully.</response>
[HttpPut]
@@ -244,7 +244,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(ConfigurationFileResponse), 200)]
[ProducesResponseType(typeof(ConfigurationFileResponse), 201)]
[ProducesResponseType(typeof(ErrorMessageResponse), 409)]
public async Task<IActionResult> CreateDirectory([FromBody] ConfigurationFileRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> CreateDirectory([FromBody] ConfigurationFileRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -297,13 +297,13 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="directory">A <see cref="ConfigurationFileRequest"/> representing the path to the directory to delete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="204">Empty directory deleted successfully.</response>
[HttpDelete]
[TgsAuthorize(ConfigurationRights.Delete)]
[ProducesResponseType(204)]
[ProducesResponseType(typeof(ErrorMessageResponse), 409)]
public async Task<IActionResult> DeleteDirectory([FromBody] ConfigurationFileRequest directory, CancellationToken cancellationToken)
public async ValueTask<IActionResult> DeleteDirectory([FromBody] ConfigurationFileRequest directory, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(directory);
@@ -73,12 +73,12 @@ namespace Tgstation.Server.Host.Controllers
/// Launches the watchdog.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="202">Watchdog launch started successfully.</response>
[HttpPut]
[TgsAuthorize(DreamDaemonRights.Start)]
[ProducesResponseType(typeof(JobResponse), 202)]
public Task<IActionResult> Create(CancellationToken cancellationToken)
public ValueTask<IActionResult> Create(CancellationToken cancellationToken)
=> WithComponentInstance(async instance =>
{
if (instance.Watchdog.Status != WatchdogStatus.Offline)
@@ -103,25 +103,25 @@ namespace Tgstation.Server.Host.Controllers
/// Get the watchdog status.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="200">Read <see cref="DreamDaemonResponse"/> information successfully.</response>
/// <response code="410">The database entity for the requested instance could not be retrieved. The instance was likely detached.</response>
[HttpGet]
[TgsAuthorize(DreamDaemonRights.ReadMetadata | DreamDaemonRights.ReadRevision)]
[ProducesResponseType(typeof(DreamDaemonResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public Task<IActionResult> Read(CancellationToken cancellationToken) => ReadImpl(null, cancellationToken);
public ValueTask<IActionResult> Read(CancellationToken cancellationToken) => ReadImpl(null, cancellationToken);
/// <summary>
/// Stops the Watchdog if it's running.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="204">Watchdog terminated.</response>
[HttpDelete]
[TgsAuthorize(DreamDaemonRights.Shutdown)]
[ProducesResponseType(204)]
public Task<IActionResult> Delete(CancellationToken cancellationToken)
public ValueTask<IActionResult> Delete(CancellationToken cancellationToken)
=> WithComponentInstance(async instance =>
{
await instance.Watchdog.Terminate(false, cancellationToken);
@@ -133,7 +133,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="DreamDaemonRequest"/> with updated settings.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="200">Settings applied successfully.</response>
/// <response code="410">The database entity for the requested instance could not be retrieved. The instance was likely detached.</response>
[HttpPost]
@@ -157,7 +157,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
#pragma warning disable CA1502 // TODO: Decomplexify
#pragma warning disable CA1506
public async Task<IActionResult> Update([FromBody] DreamDaemonRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] DreamDaemonRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -259,12 +259,12 @@ namespace Tgstation.Server.Host.Controllers
/// Creates a <see cref="JobResponse"/> to restart the Watchdog. It will not start if it wasn't already running.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="202">Restart <see cref="JobResponse"/> started successfully.</response>
[HttpPatch]
[TgsAuthorize(DreamDaemonRights.Restart)]
[ProducesResponseType(typeof(JobResponse), 202)]
public Task<IActionResult> Restart(CancellationToken cancellationToken)
public ValueTask<IActionResult> Restart(CancellationToken cancellationToken)
=> WithComponentInstance(async instance =>
{
var job = new Job
@@ -292,12 +292,12 @@ namespace Tgstation.Server.Host.Controllers
/// Creates a <see cref="JobResponse"/> to generate a DreamDaemon process dump.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="202">Dump <see cref="JobResponse"/> started successfully.</response>
[HttpPatch(Routes.Diagnostics)]
[TgsAuthorize(DreamDaemonRights.CreateDump)]
[ProducesResponseType(typeof(JobResponse), 202)]
public Task<IActionResult> CreateDump(CancellationToken cancellationToken)
public ValueTask<IActionResult> CreateDump(CancellationToken cancellationToken)
=> WithComponentInstance(async instance =>
{
var job = new Job
@@ -326,8 +326,8 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="settings">The <see cref="DreamDaemonSettings"/> to operate on if any.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
Task<IActionResult> ReadImpl(DreamDaemonSettings settings, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
ValueTask<IActionResult> ReadImpl(DreamDaemonSettings settings, CancellationToken cancellationToken)
=> WithComponentInstance(async instance =>
{
var dd = instance.Watchdog;
@@ -69,12 +69,12 @@ namespace Tgstation.Server.Host.Controllers
/// Read current deployment settings.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Read deployment settings successfully.</response>
[HttpGet]
[TgsAuthorize(DreamMakerRights.Read)]
[ProducesResponseType(typeof(DreamMakerResponse), 200)]
public async Task<IActionResult> Read(CancellationToken cancellationToken)
public async ValueTask<IActionResult> Read(CancellationToken cancellationToken)
{
var dreamMakerSettings = await DatabaseContext
.DreamMakerSettings
@@ -89,14 +89,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="EntityId.Id"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200"><see cref="CompileJob"/> retrieved successfully.</response>
/// <response code="404">Specified <see cref="CompileJob"/> ID does not exist in this instance.</response>
[HttpGet("{id}")]
[TgsAuthorize(DreamMakerRights.CompileJobs)]
[ProducesResponseType(typeof(CompileJobResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 404)]
public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> GetId(long id, CancellationToken cancellationToken)
{
var compileJob = await BaseCompileJobsQuery()
.Where(x => x.Id == id)
@@ -112,14 +112,14 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Retrieved <see cref="EntityId"/>s successfully.</response>
[HttpGet(Routes.List)]
[TgsAuthorize(DreamMakerRights.CompileJobs)]
[ProducesResponseType(typeof(PaginatedResponse<CompileJobResponse>), 200)]
public Task<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
public ValueTask<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
=> Paginated<CompileJob, CompileJobResponse>(
() => Task.FromResult(
() => ValueTask.FromResult(
new PaginatableResult<CompileJob>(
BaseCompileJobsQuery()
.OrderByDescending(x => x.Job.StoppedAt))),
@@ -132,12 +132,12 @@ namespace Tgstation.Server.Host.Controllers
/// Begin deploying repository code.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="202">Created deployment <see cref="JobResponse"/> successfully.</response>
[HttpPut]
[TgsAuthorize(DreamMakerRights.Compile)]
[ProducesResponseType(typeof(JobResponse), 202)]
public async Task<IActionResult> Create(CancellationToken cancellationToken)
public async ValueTask<IActionResult> Create(CancellationToken cancellationToken)
{
var job = new Job
{
@@ -161,7 +161,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="DreamMakerRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Changes applied successfully. The updated <see cref="DreamMakerSettings"/> will be returned.</response>
/// <response code="204">Changes applied successfully. The updated <see cref="DreamMakerSettings"/> will be not be returned due to permissions.</response>
/// <response code="410">The database entity for the requested instance could not be retrieved. The instance was likely detached.</response>
@@ -175,7 +175,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(DreamMakerResponse), 200)]
[ProducesResponseType(204)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> Update([FromBody] DreamMakerRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] DreamMakerRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -147,14 +147,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> resuting in the <see cref="JsonResult"/> containing <see cref="ServerInformationResponse"/> of the <see cref="Application"/> if a properly authenticated API request, the web control panel if on a browser and enabled, <see cref="UnauthorizedResult"/> otherwise.
/// A <see cref="ValueTask{TResult}"/> resuting in the <see cref="JsonResult"/> containing <see cref="ServerInformationResponse"/> of the <see cref="Application"/> if a properly authenticated API request, the web control panel if on a browser and enabled, <see cref="UnauthorizedResult"/> otherwise.
/// </returns>
/// <response code="200"><see cref="ServerInformationResponse"/> retrieved successfully.</response>
[HttpGet]
[AllowAnonymous]
[ProducesResponseType(typeof(ServerInformationResponse), 200)]
#pragma warning disable CA1506
public async Task<IActionResult> Home(CancellationToken cancellationToken)
public async ValueTask<IActionResult> Home(CancellationToken cancellationToken)
{
if (controlPanelConfiguration.Enable)
Response.Headers.Add(
@@ -211,7 +211,7 @@ namespace Tgstation.Server.Host.Controllers
/// Attempt to authenticate a <see cref="User"/> using <see cref="ApiController.ApiHeaders"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="200">User logged in and <see cref="TokenResponse"/> generated successfully.</response>
/// <response code="401">User authentication failed.</response>
/// <response code="403">User authenticated but is disabled by an administrator.</response>
@@ -220,7 +220,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(TokenResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 429)]
#pragma warning disable CA1506 // TODO: Decomplexify
public async Task<IActionResult> CreateToken(CancellationToken cancellationToken)
public async ValueTask<IActionResult> CreateToken(CancellationToken cancellationToken)
{
if (ApiHeaders == null)
{
@@ -120,14 +120,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="InstanceCreateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Instance attached successfully.</response>
/// <response code="201">Instance created successfully.</response>
[HttpPut]
[TgsAuthorize(InstanceManagerRights.Create)]
[ProducesResponseType(typeof(InstanceResponse), 200)]
[ProducesResponseType(typeof(InstanceResponse), 201)]
public async Task<IActionResult> Create([FromBody] InstanceCreateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Create([FromBody] InstanceCreateRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -199,7 +199,7 @@ namespace Tgstation.Server.Host.Controllers
.Any(path => InstanceIsChildOf(path)) ?? true))
return BadRequest(new ErrorMessageResponse(ErrorCode.InstanceNotAtWhitelistedPath));
async Task<bool> DirExistsAndIsNotEmpty()
async ValueTask<bool> DirExistsAndIsNotEmpty()
{
if (!await ioManager.DirectoryExists(model.Path, cancellationToken))
return false;
@@ -272,14 +272,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="EntityId.Id"/> of the instance to detach.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="204">Instance detatched successfully.</response>
/// <response code="410">The database entity for the requested instance could not be retrieved. The instance was likely detached.</response>
[HttpDelete("{id}")]
[TgsAuthorize(InstanceManagerRights.Delete)]
[ProducesResponseType(204)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Delete(long id, CancellationToken cancellationToken)
{
var originalModel = await DatabaseContext
.Instances
@@ -315,7 +315,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The updated <see cref="Api.Models.Instance"/> settings.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Instance updated successfully.</response>
/// <response code="202">Instance updated successfully and relocation job created.</response>
/// <response code="410">The database entity for the requested instance could not be retrieved. The instance was likely detached.</response>
@@ -325,7 +325,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(InstanceResponse), 202)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
#pragma warning disable CA1502 // TODO: Decomplexify
public async Task<IActionResult> Update([FromBody] InstanceUpdateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] InstanceUpdateRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -512,12 +512,12 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Retrieved <see cref="Api.Models.Instance"/>s successfully.</response>
[HttpGet(Routes.List)]
[TgsAuthorize(InstanceManagerRights.List | InstanceManagerRights.Read)]
[ProducesResponseType(typeof(PaginatedResponse<InstanceResponse>), 200)]
public async Task<IActionResult> List(
public async ValueTask<IActionResult> List(
[FromQuery] int? page,
[FromQuery] int? pageSize,
CancellationToken cancellationToken)
@@ -552,7 +552,7 @@ namespace Tgstation.Server.Host.Controllers
var needsUpdate = false;
var result = await Paginated<Models.Instance, InstanceResponse>(
() => Task.FromResult(
() => ValueTask.FromResult(
new PaginatableResult<Models.Instance>(
GetBaseQuery()
.OrderBy(x => x.Id))),
@@ -577,14 +577,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The instance <see cref="EntityId.Id"/> to retrieve.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Retrieved <see cref="Api.Models.Instance"/> successfully.</response>
/// <response code="410">The database entity for the requested instance could not be retrieved. The instance was likely detached.</response>
[HttpGet("{id}")]
[TgsAuthorize(InstanceManagerRights.List | InstanceManagerRights.Read)]
[ProducesResponseType(typeof(InstanceResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> GetId(long id, CancellationToken cancellationToken)
{
var cantList = !AuthenticationContext.PermissionSet.InstanceManagerRights.Value.HasFlag(InstanceManagerRights.List);
IQueryable<Models.Instance> QueryForUser()
@@ -634,13 +634,13 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The instance <see cref="EntityId.Id"/> to give permissions on.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="204">Granted permissions successfully.</response>
[HttpPatch("{id}")]
[TgsAuthorize(InstanceManagerRights.GrantPermissions)]
[ProducesResponseType(204)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> GrantPermissions(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> GrantPermissions(long id, CancellationToken cancellationToken)
{
IQueryable<Models.Instance> BaseQuery() => DatabaseContext
.Instances
@@ -678,8 +678,8 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="initialSettings">The <see cref="InstanceCreateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the new <see cref="Models.Instance"/> or <see langword="null"/> if ports could not be allocated.</returns>
async Task<Models.Instance> CreateDefaultInstance(InstanceCreateRequest initialSettings, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the new <see cref="Models.Instance"/> or <see langword="null"/> if ports could not be allocated.</returns>
async ValueTask<Models.Instance> CreateDefaultInstance(InstanceCreateRequest initialSettings, CancellationToken cancellationToken)
{
var ddPort = await portAllocator.GetAvailablePort(1024, false, cancellationToken);
if (!ddPort.HasValue)
@@ -797,8 +797,8 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="instanceResponse">The <see cref="InstanceResponse"/> to populate.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task CheckAccessible(InstanceResponse instanceResponse, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask CheckAccessible(InstanceResponse instanceResponse, CancellationToken cancellationToken)
{
instanceResponse.Accessible = await DatabaseContext
.InstancePermissionSets
@@ -53,7 +53,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="InstancePermissionSetRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="201"><see cref="InstancePermissionSet"/> created successfully.</response>
/// <response code="410">The <see cref="Api.Models.PermissionSet"/> does not exist.</response>
[HttpPut]
@@ -61,7 +61,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(InstancePermissionSetResponse), 201)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
#pragma warning disable CA1506
public async Task<IActionResult> Create([FromBody] InstancePermissionSetRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Create([FromBody] InstancePermissionSetRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -116,7 +116,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="InstancePermissionSetRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200"><see cref="InstancePermissionSet"/> updated successfully.</response>
/// <response code="410">The requested <see cref="InstancePermissionSet"/> does not currently exist.</response>
[HttpPost]
@@ -124,7 +124,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(InstancePermissionSetResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
#pragma warning disable CA1506 // TODO: Decomplexify
public async Task<IActionResult> Update([FromBody] InstancePermissionSetRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] InstancePermissionSetRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -174,14 +174,14 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Retrieved <see cref="InstancePermissionSet"/>s successfully.</response>
[HttpGet(Routes.List)]
[TgsAuthorize(InstancePermissionSetRights.Read)]
[ProducesResponseType(typeof(PaginatedResponse<InstancePermissionSetResponse>), 200)]
public Task<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
public ValueTask<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
=> Paginated<InstancePermissionSet, InstancePermissionSetResponse>(
() => Task.FromResult(
() => ValueTask.FromResult(
new PaginatableResult<InstancePermissionSet>(
DatabaseContext
.Instances
@@ -199,14 +199,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="Api.Models.Internal.InstancePermissionSet.PermissionSetId"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Retrieve <see cref="Api.Models.Internal.InstancePermissionSet"/> successfully.</response>
/// <response code="410">The requested <see cref="Api.Models.Internal.InstancePermissionSet"/> does not currently exist.</response>
[HttpGet("{id}")]
[TgsAuthorize(InstancePermissionSetRights.Read)]
[ProducesResponseType(typeof(InstancePermissionSetResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> GetId(long id, CancellationToken cancellationToken)
{
// this functions as userId
var permissionSet = await DatabaseContext
@@ -226,14 +226,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="Api.Models.Internal.InstancePermissionSet.PermissionSetId"/> to delete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="204">Target <see cref="InstancePermissionSet"/> deleted.</response>
/// <response code="410">Target <see cref="InstancePermissionSet"/> or no longer exists.</response>
[HttpDelete("{id}")]
[TgsAuthorize(InstancePermissionSetRights.Write)]
[ProducesResponseType(204)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Delete(long id, CancellationToken cancellationToken)
{
var numDeleted = await DatabaseContext
.Instances
@@ -59,14 +59,14 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Retrieved active <see cref="Job"/>s successfully.</response>
[HttpGet]
[TgsAuthorize]
[ProducesResponseType(typeof(PaginatedResponse<JobResponse>), 200)]
public Task<IActionResult> Read([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
public ValueTask<IActionResult> Read([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
=> Paginated<Job, JobResponse>(
() => Task.FromResult(
() => ValueTask.FromResult(
new PaginatableResult<Job>(
DatabaseContext
.Jobs
@@ -86,14 +86,14 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Retrieved <see cref="Job"/> <see cref="EntityId"/>s successfully.</response>
[HttpGet(Routes.List)]
[TgsAuthorize]
[ProducesResponseType(typeof(PaginatedResponse<JobResponse>), 200)]
public Task<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
public ValueTask<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
=> Paginated<Job, JobResponse>(
() => Task.FromResult(
() => ValueTask.FromResult(
new PaginatableResult<Job>(
DatabaseContext
.Jobs
@@ -112,7 +112,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="EntityId.Id"/> of the <see cref="JobResponse"/> to cancel.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="202"><see cref="Job"/> cancellation requested successfully.</response>
/// <response code="404"><see cref="Job"/> does not exist in this instance.</response>
/// <response code="410"><see cref="Job"/> could not be found in the job manager. Has it already completed?.</response>
@@ -120,7 +120,7 @@ namespace Tgstation.Server.Host.Controllers
[TgsAuthorize]
[ProducesResponseType(typeof(JobResponse), 202)]
[ProducesResponseType(typeof(ErrorMessageResponse), 404)]
public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Delete(long id, CancellationToken cancellationToken)
{
// don't care if an instance post or not at this point
var job = await DatabaseContext
@@ -147,14 +147,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="EntityId.Id"/> of the <see cref="JobResponse"/> to retrieve.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Retrieved <see cref="Job"/> successfully.</response>
/// <response code="404"><see cref="Job"/> does not exist in this instance.</response>
[HttpGet("{id}")]
[TgsAuthorize]
[ProducesResponseType(typeof(JobResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 404)]
public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> GetId(long id, CancellationToken cancellationToken)
{
var job = await DatabaseContext
.Jobs
@@ -174,11 +174,11 @@ namespace Tgstation.Server.Host.Controllers
/// Supplements <see cref="JobResponse"/> <see cref="PaginatedResponse{TModel}"/>s with their <see cref="JobResponse.Progress"/>.
/// </summary>
/// <param name="jobResponse">The <see cref="JobResponse"/> to augment.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task AddJobProgressResponseTransformer(JobResponse jobResponse)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask AddJobProgressResponseTransformer(JobResponse jobResponse)
{
jobManager.SetJobProgress(jobResponse);
return Task.CompletedTask;
return ValueTask.CompletedTask;
}
}
}
@@ -73,14 +73,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="RepositoryCreateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="201">The repository was created successfully and the <see cref="JobResponse"/> to clone it has begun.</response>
/// <response code="410">The database entity for the requested instance could not be retrieved. The instance was likely detached.</response>
[HttpPut]
[TgsAuthorize(RepositoryRights.SetOrigin)]
[ProducesResponseType(typeof(RepositoryResponse), 201)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> Create([FromBody] RepositoryCreateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Create([FromBody] RepositoryCreateRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -193,14 +193,14 @@ namespace Tgstation.Server.Host.Controllers
/// Delete the repository.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="202">Job to delete the repository created successfully.</response>
/// <response code="410">The database entity for the requested instance could not be retrieved. The instance was likely detached.</response>
[HttpDelete]
[TgsAuthorize(RepositoryRights.Delete)]
[ProducesResponseType(typeof(RepositoryResponse), 202)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> Delete(CancellationToken cancellationToken)
public async ValueTask<IActionResult> Delete(CancellationToken cancellationToken)
{
var currentModel = await DatabaseContext
.RepositorySettings
@@ -237,7 +237,7 @@ namespace Tgstation.Server.Host.Controllers
/// Get the repository's status.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="200">Retrieved the repository settings successfully.</response>
/// <response code="201">Retrieved the repository settings successfully, though they did not previously exist.</response>
/// <response code="410">The database entity for the requested instance could not be retrieved. The instance was likely detached.</response>
@@ -246,7 +246,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(RepositoryResponse), 200)]
[ProducesResponseType(typeof(RepositoryResponse), 201)]
[ProducesResponseType(typeof(RepositoryResponse), 410)]
public async Task<IActionResult> Read(CancellationToken cancellationToken)
public async ValueTask<IActionResult> Read(CancellationToken cancellationToken)
{
var currentModel = await DatabaseContext
.RepositorySettings
@@ -287,7 +287,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="RepositoryUpdateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="200">Updated the repository settings successfully.</response>
/// <response code="202">Updated the repository settings successfully and a <see cref="JobResponse"/> was created to make the requested git changes.</response>
/// <response code="410">The database entity for the requested instance could not be retrieved. The instance was likely detached.</response>
@@ -306,7 +306,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(RepositoryResponse), 202)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
#pragma warning disable CA1502 // TODO: Decomplexify
public async Task<IActionResult> Update([FromBody] RepositoryUpdateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] RepositoryUpdateRequest model, CancellationToken cancellationToken)
#pragma warning restore CA1502
{
ArgumentNullException.ThrowIfNull(model);
@@ -484,8 +484,8 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="databaseContext">The active <see cref="IDatabaseContext"/>.</param>
/// <param name="instance">The active <see cref="Models.Instance"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in <see langword="true"/> if the <paramref name="databaseContext"/> was modified in a way that requires saving, <see langword="false"/> otherwise.</returns>
async Task<bool> PopulateApi(
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in <see langword="true"/> if the <paramref name="databaseContext"/> was modified in a way that requires saving, <see langword="false"/> otherwise.</returns>
async ValueTask<bool> PopulateApi(
RepositoryResponse apiResponse,
IRepository repository,
IDatabaseContext databaseContext,
@@ -89,7 +89,7 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>The <see cref="IActionResult"/> of the operation.</returns>
[HttpPost(SwarmConstants.RegisterRoute)]
public async Task<IActionResult> Register([FromBody] SwarmRegistrationRequest registrationRequest, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Register([FromBody] SwarmRegistrationRequest registrationRequest, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(registrationRequest);
@@ -108,7 +108,7 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
[HttpDelete(SwarmConstants.RegisterRoute)]
public async Task<IActionResult> UnregisterNode(CancellationToken cancellationToken)
public async ValueTask<IActionResult> UnregisterNode(CancellationToken cancellationToken)
{
if (!ValidateRegistration())
return Forbid();
@@ -138,7 +138,7 @@ namespace Tgstation.Server.Host.Controllers
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
[HttpGet(SwarmConstants.UpdateRoute)]
[Produces(MediaTypeNames.Application.Octet)]
public Task<IActionResult> GetUpdatePackage([FromQuery] string ticket, CancellationToken cancellationToken)
public ValueTask<IActionResult> GetUpdatePackage([FromQuery] string ticket, CancellationToken cancellationToken)
=> transferService.GenerateDownloadResponse(this, ticket, cancellationToken);
/// <summary>
@@ -163,9 +163,9 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="updateRequest">The <see cref="SwarmUpdateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
[HttpPut(SwarmConstants.UpdateRoute)]
public async Task<IActionResult> PrepareUpdate([FromBody] SwarmUpdateRequest updateRequest, CancellationToken cancellationToken)
public async ValueTask<IActionResult> PrepareUpdate([FromBody] SwarmUpdateRequest updateRequest, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(updateRequest);
@@ -183,9 +183,9 @@ namespace Tgstation.Server.Host.Controllers
/// Update commit endpoint.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
[HttpPost(SwarmConstants.UpdateRoute)]
public async Task<IActionResult> CommitUpdate(CancellationToken cancellationToken)
public async ValueTask<IActionResult> CommitUpdate(CancellationToken cancellationToken)
{
if (!ValidateRegistration())
return Forbid();
@@ -199,9 +199,9 @@ namespace Tgstation.Server.Host.Controllers
/// <summary>
/// Update abort endpoint.
/// </summary>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
[HttpDelete(SwarmConstants.UpdateRoute)]
public async Task<IActionResult> AbortUpdate()
public async ValueTask<IActionResult> AbortUpdate()
{
if (!ValidateRegistration())
return Forbid();
@@ -54,14 +54,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="ticket">The <see cref="FileTicketResponse.FileTicket"/> for the download.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the method.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the method.</returns>
/// <response code="200">Started streaming download successfully.</response>
/// <response code="410">The <paramref name="ticket"/> was no longer or was never valid.</response>
[TgsAuthorize]
[HttpGet]
[ProducesResponseType(200, Type = typeof(LimitedStreamResult))]
[ProducesResponseType(410, Type = typeof(ErrorMessageResponse))]
public Task<IActionResult> Download([Required, FromQuery] string ticket, CancellationToken cancellationToken)
public ValueTask<IActionResult> Download([Required, FromQuery] string ticket, CancellationToken cancellationToken)
=> fileTransferService.GenerateDownloadResponse(this, ticket, cancellationToken);
/// <summary>
@@ -69,7 +69,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="ticket">The <see cref="FileTicketResponse.FileTicket"/> for the upload.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the method.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the method.</returns>
/// <response code="204">Uploaded file successfully.</response>
/// <response code="409">An error occurred during the upload.</response>
/// <response code="410">The <paramref name="ticket"/> was no longer or was never valid.</response>
@@ -77,7 +77,7 @@ namespace Tgstation.Server.Host.Controllers
[HttpPut]
[ProducesResponseType(204)]
[ProducesResponseType(410, Type = typeof(ErrorMessageResponse))]
public async Task<IActionResult> Upload([Required, FromQuery] string ticket, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Upload([Required, FromQuery] string ticket, CancellationToken cancellationToken)
{
if (ticket == null)
return BadRequest(new ErrorMessageResponse(ErrorCode.ModelValidationFailure));
@@ -75,14 +75,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="UserCreateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="201"><see cref="User"/> created successfully.</response>
/// <response code="410">The requested system identifier could not be found.</response>
[HttpPut]
[TgsAuthorize(AdministrationRights.WriteUsers)]
[ProducesResponseType(typeof(UserResponse), 201)]
#pragma warning disable CA1502, CA1506
public async Task<IActionResult> Create([FromBody] UserCreateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Create([FromBody] UserCreateRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -155,7 +155,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="UserResponse"/> to update.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="200"><see cref="User"/> updated successfully.</response>
/// <response code="200"><see cref="User"/> updated successfully. Not returned due to lack of permissions.</response>
/// <response code="404">Requested <see cref="EntityId.Id"/> does not exist.</response>
@@ -168,7 +168,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
#pragma warning disable CA1502 // TODO: Decomplexify
#pragma warning disable CA1506
public async Task<IActionResult> Update([FromBody] UserUpdateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] UserUpdateRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -336,14 +336,14 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="200">Retrieved <see cref="User"/>s successfully.</response>
[HttpGet(Routes.List)]
[TgsAuthorize(AdministrationRights.ReadUsers)]
[ProducesResponseType(typeof(PaginatedResponse<UserResponse>), 200)]
public Task<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
public ValueTask<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
=> Paginated<User, UserResponse>(
() => Task.FromResult(
() => ValueTask.FromResult(
new PaginatableResult<User>(
DatabaseContext
.Users
@@ -365,14 +365,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="EntityId.Id"/> to retrieve.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="200">The <see cref="User"/> was retrieved successfully.</response>
/// <response code="404">The <see cref="User"/> does not exist.</response>
[HttpGet("{id}")]
[TgsAuthorize]
[ProducesResponseType(typeof(UserResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 404)]
public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> GetId(long id, CancellationToken cancellationToken)
{
if (id == AuthenticationContext.User.Id)
return Read();
@@ -403,8 +403,8 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="Api.Models.Internal.UserApiBase"/> to use as a template.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in a new <see cref="User"/> on success, <see langword="null"/> if the requested <see cref="UserGroup"/> did not exist.</returns>
async Task<User> CreateNewUserFromModel(Api.Models.Internal.UserApiBase model, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in a new <see cref="User"/> on success, <see langword="null"/> if the requested <see cref="UserGroup"/> did not exist.</returns>
async ValueTask<User> CreateNewUserFromModel(Api.Models.Internal.UserApiBase model, CancellationToken cancellationToken)
{
Models.PermissionSet permissionSet = null;
UserGroup group = null;
@@ -60,12 +60,12 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="UserGroupCreateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="201"><see cref="UserGroup"/> created successfully.</response>
[HttpPut]
[TgsAuthorize(AdministrationRights.WriteUsers)]
[ProducesResponseType(typeof(UserGroupResponse), 201)]
public async Task<IActionResult> Create([FromBody] UserGroupCreateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Create([FromBody] UserGroupCreateRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -103,13 +103,13 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="model">The <see cref="UserGroupUpdateRequest"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation.</returns>
/// <response code="200"><see cref="UserGroup"/> updated successfully.</response>
/// <response code="410">The requested <see cref="UserGroup"/> does not currently exist.</response>
[HttpPost]
[TgsAuthorize(AdministrationRights.WriteUsers)]
[ProducesResponseType(typeof(UserGroupResponse), 200)]
public async Task<IActionResult> Update([FromBody] UserGroupUpdateRequest model, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Update([FromBody] UserGroupUpdateRequest model, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(model);
@@ -148,14 +148,14 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="EntityId.Id"/> of the <see cref="UserGroupResponse"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Retrieve <see cref="UserGroup"/> successfully.</response>
/// <response code="410">The requested <see cref="UserGroup"/> does not currently exist.</response>
[HttpGet("{id}")]
[TgsAuthorize(AdministrationRights.ReadUsers)]
[ProducesResponseType(typeof(UserGroupResponse), 200)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> GetId(long id, CancellationToken cancellationToken)
{
// this functions as userId
var group = await DatabaseContext
@@ -176,14 +176,14 @@ namespace Tgstation.Server.Host.Controllers
/// <param name="page">The current page.</param>
/// <param name="pageSize">The page size.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="200">Retrieved <see cref="UserGroup"/>s successfully.</response>
[HttpGet(Routes.List)]
[TgsAuthorize(AdministrationRights.ReadUsers)]
[ProducesResponseType(typeof(PaginatedResponse<UserGroupResponse>), 200)]
public Task<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
public ValueTask<IActionResult> List([FromQuery] int? page, [FromQuery] int? pageSize, CancellationToken cancellationToken)
=> Paginated<UserGroup, UserGroupResponse>(
() => Task.FromResult(
() => ValueTask.FromResult(
new PaginatableResult<UserGroup>(
DatabaseContext
.Groups
@@ -201,7 +201,7 @@ namespace Tgstation.Server.Host.Controllers
/// </summary>
/// <param name="id">The <see cref="EntityId.Id"/> of the <see cref="UserGroup"/> to delete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the request.</returns>
/// <response code="204"><see cref="UserGroup"/> was deleted.</response>
/// <response code="409">The <see cref="UserGroup"/> is not empty.</response>
/// <response code="410">The <see cref="UserGroup"/> didn't exist.</response>
@@ -210,7 +210,7 @@ namespace Tgstation.Server.Host.Controllers
[ProducesResponseType(204)]
[ProducesResponseType(typeof(ErrorMessageResponse), 409)]
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
public async ValueTask<IActionResult> Delete(long id, CancellationToken cancellationToken)
{
var numDeleted = await DatabaseContext
.Groups
@@ -28,8 +28,8 @@ namespace Tgstation.Server.Host.Extensions
/// <param name="controller">The <see cref="ControllerBase"/> the request is coming from.</param>
/// <param name="ticket">The <see cref="FileTicketResponse.FileTicket"/> for the download.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the method.</returns>
public static async Task<IActionResult> GenerateDownloadResponse(
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IActionResult"/> of the method.</returns>
public static async ValueTask<IActionResult> GenerateDownloadResponse(
this IFileTransferStreamHandler fileTransferService,
ControllerBase controller,
string ticket,
@@ -184,12 +184,21 @@ namespace Tgstation.Server.Host.Swarm.Tests
if (controllerMethod.ReturnType != typeof(IActionResult))
{
Assert.AreEqual(typeof(Task<IActionResult>), controllerMethod.ReturnType);
var isValueTask = controllerMethod.ReturnType == typeof(ValueTask<IActionResult>);
if (!isValueTask)
Assert.AreEqual(typeof(Task<IActionResult>), controllerMethod.ReturnType);
var lastParam = controllerMethod.GetParameters().LastOrDefault();
if (lastParam?.ParameterType == typeof(CancellationToken))
args.Add(cancellationToken);
var invocationTask = (Task<IActionResult>)controllerMethod.Invoke(controller, args.ToArray());
var rawTask = controllerMethod.Invoke(controller, args.ToArray());
Task<IActionResult> invocationTask;
if (isValueTask)
invocationTask = ((ValueTask<IActionResult>)rawTask).AsTask();
else
invocationTask = (Task<IActionResult>)rawTask;
result = await invocationTask;
}
else
@@ -270,18 +270,18 @@ namespace Tgstation.Server.Host.Swarm.Tests
return result;
}
Task<ServerUpdateResult> BeginUpdate(ISwarmService swarmService, IFileStreamProvider fileStreamProvider, Version version, CancellationToken cancellationToken)
ValueTask<ServerUpdateResult> BeginUpdate(ISwarmService swarmService, IFileStreamProvider fileStreamProvider, Version version, CancellationToken cancellationToken)
{
logger.LogTrace("BeginUpdate...");
if (UpdateTask?.IsCompleted == false)
return Task.FromResult(ServerUpdateResult.UpdateInProgress);
return ValueTask.FromResult(ServerUpdateResult.UpdateInProgress);
if (UpdateResult == ServerUpdateResult.Started)
{
UpdateTask = ExecuteUpdate(fileStreamProvider, version, cancellationToken, CriticalCancellationTokenSource.Token);
}
return Task.FromResult(UpdateResult);
return ValueTask.FromResult(UpdateResult);
}
async Task<SwarmCommitResult?> ExecuteUpdate(IFileStreamProvider fileStreamProvider, Version version, CancellationToken cancellationToken, CancellationToken criticalCancellationToken)