Final ValueTask conversion

This commit is contained in:
Jordan Dominion
2023-10-07 17:41:19 -04:00
parent faeb730ebe
commit 8b59884bf9
57 changed files with 286 additions and 287 deletions
@@ -31,7 +31,7 @@ namespace Tgstation.Server.Host.Console
}
/// <inheritdoc />
public async Task CheckSignals(Func<string, (int, Task)> startChild, CancellationToken cancellationToken)
public async ValueTask CheckSignals(Func<string, (int, Task)> startChild, CancellationToken cancellationToken)
{
var (childPid, _) = startChild?.Invoke(null) ?? throw new ArgumentNullException(nameof(startChild));
var signalTcs = new TaskCompletionSource<Signum>();
+2 -2
View File
@@ -116,7 +116,7 @@ namespace Tgstation.Server.Host.Service
}
if (Configure)
await RunConfigure(CancellationToken.None); // DCT: None available
await RunConfigure(CancellationToken.None); // DCT: None available
bool stopped = false;
if (Uninstall)
@@ -281,7 +281,7 @@ namespace Tgstation.Server.Host.Service
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task RunConfigure(CancellationToken cancellationToken)
async ValueTask RunConfigure(CancellationToken cancellationToken)
{
using var loggerFactory = LoggerFactory.Create(builder =>
{
@@ -90,7 +90,7 @@ namespace Tgstation.Server.Host.Service
}
/// <inheritdoc />
public async Task CheckSignals(Func<string, (int, Task)> startChildAndGetPid, CancellationToken cancellationToken)
public async ValueTask CheckSignals(Func<string, (int, Task)> startChildAndGetPid, CancellationToken cancellationToken)
{
await using (commandPipeServer = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
await using (readyPipeServer = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
@@ -14,7 +14,7 @@ namespace Tgstation.Server.Host.Watchdog
/// </summary>
/// <param name="startChild">An <see cref="Func{TResult}"/> to start the main process. It accepts an optional additional command line argument as a paramter and returns it's <see cref="System.Diagnostics.Process.Id"/> and lifetime <see cref="Task"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task CheckSignals(Func<string, (int, Task)> startChild, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask CheckSignals(Func<string, (int, Task)> startChild, CancellationToken cancellationToken);
}
}
@@ -20,7 +20,7 @@ namespace Tgstation.Server.Host.Watchdog
/// <param name="runConfigure">If the <see cref="IWatchdog"/> should just run the host configuration wizard and exit.</param>
/// <param name="args">The arguments for the <see cref="IWatchdog"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in <see langword="true"/> if there were no errors, <see langword="false"/> otherwise.</returns>
Task<bool> RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in <see langword="true"/> if there were no errors, <see langword="false"/> otherwise.</returns>
ValueTask<bool> RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken);
}
}
@@ -10,11 +10,11 @@ namespace Tgstation.Server.Host.Watchdog
public sealed class NoopSignalChecker : ISignalChecker
{
/// <inheritdoc />
public Task CheckSignals(Func<string, (int, Task)> startChild, CancellationToken cancellationToken)
public ValueTask CheckSignals(Func<string, (int, Task)> startChild, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(startChild);
startChild(null);
return Task.CompletedTask;
return ValueTask.CompletedTask;
}
}
}
@@ -46,7 +46,7 @@ namespace Tgstation.Server.Host.Watchdog
/// <inheritdoc />
#pragma warning disable CA1502 // TODO: Decomplexify
#pragma warning disable CA1506
public async Task<bool> RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
public async ValueTask<bool> RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
{
logger.LogInformation("Host watchdog starting...");
int currentProcessId;
@@ -66,7 +66,7 @@ namespace Tgstation.Server.Host.Components.Byond
public abstract string GetDreamDaemonName(Version version, out bool supportsCli, out bool supportsMapThreads);
/// <inheritdoc />
public async ValueTask CleanCache(CancellationToken cancellationToken)
public async Task CleanCache(CancellationToken cancellationToken)
{
try
{
@@ -59,7 +59,7 @@ namespace Tgstation.Server.Host.Components.Byond
/// Attempts to cleans the BYOND cache folder for the system.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask CleanCache(CancellationToken cancellationToken);
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task CleanCache(CancellationToken cancellationToken);
}
}
@@ -178,7 +178,7 @@ namespace Tgstation.Server.Host.Components.Chat
}
/// <inheritdoc />
public async Task ChangeChannels(long connectionId, IEnumerable<Models.ChatChannel> newChannels, CancellationToken cancellationToken)
public async ValueTask ChangeChannels(long connectionId, IEnumerable<Models.ChatChannel> newChannels, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(newChannels);
@@ -261,7 +261,7 @@ namespace Tgstation.Server.Host.Components.Chat
}
/// <inheritdoc />
public async Task ChangeSettings(Models.ChatBot newSettings, CancellationToken cancellationToken)
public async ValueTask ChangeSettings(Models.ChatBot newSettings, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(newSettings);
@@ -412,7 +412,7 @@ namespace Tgstation.Server.Host.Components.Chat
AddMessageTask(task);
Task callbackTask;
Func<bool, ValueTask> finalUpdateAction = null;
Func<bool, Task> finalUpdateAction = null;
async Task CallbackTask(string errorMessage, string dreamMakerOutput)
{
await task;
@@ -423,10 +423,10 @@ namespace Tgstation.Server.Host.Components.Chat
dreamMakerOutput)),
callbacks.Count);
finalUpdateAction = active => ValueTaskExtensions.WhenAll(callbackResults.Select(finalizerCallback => finalizerCallback(active)));
finalUpdateAction = active => ValueTaskExtensions.WhenAll(callbackResults.Select(finalizerCallback => finalizerCallback(active))).AsTask();
}
async ValueTask CompletionTask(bool active)
async Task CompletionTask(bool active)
{
try
{
@@ -438,14 +438,14 @@ namespace Tgstation.Server.Host.Components.Chat
return;
}
AddMessageTask(finalUpdateAction(active).AsTask());
AddMessageTask(finalUpdateAction(active));
}
return (errorMessage, dreamMakerOutput) =>
{
callbackTask = CallbackTask(errorMessage, dreamMakerOutput);
AddMessageTask(callbackTask);
return active => AddMessageTask(CompletionTask(active).AsTask());
return active => AddMessageTask(CompletionTask(active));
};
}
@@ -455,7 +455,7 @@ namespace Tgstation.Server.Host.Components.Chat
foreach (var tgsCommand in commandFactory.GenerateCommands())
builtinCommands.Add(tgsCommand.Name.ToUpperInvariant(), tgsCommand);
var initialChatBots = activeChatBots.ToList();
await Task.WhenAll(initialChatBots.Select(x => ChangeSettings(x, cancellationToken)));
await ValueTaskExtensions.WhenAll(initialChatBots.Select(x => ChangeSettings(x, cancellationToken)));
initialProviderConnectionsTask = InitialConnection();
chatHandler = MonitorMessages(handlerCts.Token);
}
@@ -495,7 +495,7 @@ namespace Tgstation.Server.Host.Components.Chat
}
/// <inheritdoc />
public async Task UpdateTrackingContexts(CancellationToken cancellationToken)
public async ValueTask UpdateTrackingContexts(CancellationToken cancellationToken)
{
var logMessageSent = 0;
async Task UpdateTrackingContext(IChatTrackingContext channelSink, IEnumerable<ChannelRepresentation> channels)
@@ -589,8 +589,8 @@ namespace Tgstation.Server.Host.Components.Chat
/// <param name="connectionId">The <see cref="Api.Models.EntityId.Id"/> of the <see cref="IProvider"/> to delete.</param>
/// <param name="removeProvider">If the provider should be removed from <see cref="providers"/> and <see cref="trackingContexts"/> should be update.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IProvider"/> being removed if it exists, <see langword="null"/> otherwise.</returns>
async Task<IProvider> RemoveProviderChannels(long connectionId, bool removeProvider, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="IProvider"/> being removed if it exists, <see langword="null"/> otherwise.</returns>
async ValueTask<IProvider> RemoveProviderChannels(long connectionId, bool removeProvider, CancellationToken cancellationToken)
{
logger.LogTrace("RemoveProviderChannels {connectionId}...", connectionId);
IProvider provider;
@@ -936,7 +936,7 @@ namespace Tgstation.Server.Host.Components.Chat
{
logger.LogTrace("Starting processing loop...");
var messageTasks = new Dictionary<IProvider, Task<Message>>();
Task activeProcessingTask = Task.CompletedTask;
ValueTask activeProcessingTask = ValueTask.CompletedTask;
try
{
Task updatedTask = null;
@@ -956,7 +956,7 @@ namespace Tgstation.Server.Host.Components.Chat
if (!messageTasks.ContainsKey(providerKvp.Value))
messageTasks.Add(
providerKvp.Value,
providerKvp.Value.NextMessage(cancellationToken).AsTask());
providerKvp.Value.NextMessage(cancellationToken));
if (messageTasks.Count == 0)
{
@@ -981,7 +981,7 @@ namespace Tgstation.Server.Host.Components.Chat
var message = await completedMessageTaskKvp.Value;
var messageNumber = Interlocked.Increment(ref messagesProcessed);
async Task WrapProcessMessage()
async ValueTask WrapProcessMessage()
{
var localActiveProcessingTask = activeProcessingTask;
using (LogContext.PushProperty(SerilogContextHelper.ChatMessageIterationContextProperty, messageNumber))
@@ -24,8 +24,8 @@ namespace Tgstation.Server.Host.Components.Chat
/// </summary>
/// <param name="newSettings">The new <see cref="Models.ChatBot"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation. Will complete immediately if the <see cref="ChatBotSettings.Enabled"/> property of <paramref name="newSettings"/> is <see langword="false"/>.</returns>
Task ChangeSettings(Models.ChatBot newSettings, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation. Will complete immediately if the <see cref="ChatBotSettings.Enabled"/> property of <paramref name="newSettings"/> is <see langword="false"/>.</returns>
ValueTask ChangeSettings(Models.ChatBot newSettings, CancellationToken cancellationToken);
/// <summary>
/// Disconnects and deletes a given connection.
@@ -41,8 +41,8 @@ namespace Tgstation.Server.Host.Components.Chat
/// <param name="connectionId">The <see cref="Api.Models.EntityId.Id"/> of the connection.</param>
/// <param name="newChannels">An <see cref="IEnumerable{T}"/> of the new list of <see cref="Models.ChatChannel"/>s.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task ChangeChannels(long connectionId, IEnumerable<Models.ChatChannel> newChannels, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask ChangeChannels(long connectionId, IEnumerable<Models.ChatChannel> newChannels, CancellationToken cancellationToken);
/// <summary>
/// Queue a chat <paramref name="message"/> to a given set of <paramref name="channelIds"/>.
@@ -85,7 +85,7 @@ namespace Tgstation.Server.Host.Components.Chat
/// Force an update with the active channels on all active <see cref="IChatTrackingContext"/>s.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task UpdateTrackingContexts(CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask UpdateTrackingContexts(CancellationToken cancellationToken);
}
}
@@ -260,7 +260,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
var embeds = ConvertEmbed(message.Embed);
var channelsClient = serviceProvider.GetRequiredService<IDiscordRestChannelAPI>();
async Task SendToChannel(Snowflake channelId)
async ValueTask SendToChannel(Snowflake channelId)
{
var result = await channelsClient.CreateMessageAsync(
channelId,
@@ -312,7 +312,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
if (unmappedTextChannels.Any())
{
Logger.LogDebug("Dispatching to {count} unmapped channels...", unmappedTextChannels.Count());
await Task.WhenAll(
await ValueTaskExtensions.WhenAll(
unmappedTextChannels.Select(
x => SendToChannel(x.ID)));
}
@@ -430,7 +430,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
var updatedMessageText = $"DM: Deployment {completionString}!";
IMessage updatedMessage = null;
async Task CreateUpdatedMessage()
async ValueTask CreateUpdatedMessage()
{
var createUpdatedMessageResponse = await channelsClient.CreateMessageAsync(
new Snowflake(channelId),
@@ -39,12 +39,12 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
void InitialMappingComplete();
/// <summary>
/// Get a <see cref="ValueTask{TResult}"/> resulting in the next <see cref="Message"/> the <see cref="IProvider"/> recieves or <see langword="null"/> on a disconnect.
/// Get a <see cref="Task{TResult}"/> resulting in the next <see cref="Message"/> the <see cref="IProvider"/> recieves or <see langword="null"/> on a disconnect.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the next available <see cref="Message"/> or <see langword="null"/> if the <see cref="IProvider"/> needed to reconnect.</returns>
/// <returns>A <see cref="Task{TResult}"/> resulting in the next available <see cref="Message"/> or <see langword="null"/> if the <see cref="IProvider"/> needed to reconnect.</returns>
/// <remarks>Note that private messages will come in the form of <see cref="ChannelRepresentation"/>s not returned in <see cref="MapChannels(IEnumerable{ChatChannel}, CancellationToken)"/>.</remarks>
ValueTask<Message> NextMessage(CancellationToken cancellationToken);
Task<Message> NextMessage(CancellationToken cancellationToken);
/// <summary>
/// Gracefully disconnects the provider. Permanently stops the reconnection timer.
@@ -595,8 +595,8 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// Run SASL authentication on <see cref="client"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task SaslAuthenticate(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask SaslAuthenticate(CancellationToken cancellationToken)
{
client.WriteLine("CAP REQ :sasl", Priority.Critical); // needs to be put in the buffer before anything else
cancellationToken.ThrowIfCancellationRequested();
@@ -665,8 +665,8 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// Attempt to disconnect from IRC immediately.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task HardDisconnect(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask HardDisconnect(CancellationToken cancellationToken)
{
if (!Connected)
{
@@ -144,7 +144,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
}
/// <inheritdoc />
public async ValueTask<Message> NextMessage(CancellationToken cancellationToken)
public async Task<Message> NextMessage(CancellationToken cancellationToken)
{
while (true)
{
@@ -171,7 +171,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
{
stopOldTimerTask = StopReconnectionTimer();
reconnectCts = new CancellationTokenSource();
reconnectTask = ReconnectionLoop(reconnectInterval, connectNow, reconnectCts.Token).AsTask();
reconnectTask = ReconnectionLoop(reconnectInterval, connectNow, reconnectCts.Token);
}
return stopOldTimerTask;
@@ -260,8 +260,8 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// <param name="reconnectInterval">The amount of minutes to wait between reconnection attempts.</param>
/// <param name="connectNow">If a connection attempt should be immediately made.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask ReconnectionLoop(uint reconnectInterval, bool connectNow, CancellationToken cancellationToken)
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task ReconnectionLoop(uint reconnectInterval, bool connectNow, CancellationToken cancellationToken)
{
do
{
@@ -422,8 +422,8 @@ namespace Tgstation.Server.Host.Components.Deployment
/// </summary>
/// <param name="databaseContext">The <see cref="IDatabaseContext"/> to retrieve previous deployment <see cref="Job"/>s from.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the average <see cref="TimeSpan"/> of the 10 previous deployments or <see langword="null"/> if there are none.</returns>
async Task<TimeSpan?> CalculateExpectedDeploymentTime(IDatabaseContext databaseContext, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the average <see cref="TimeSpan"/> of the 10 previous deployments or <see langword="null"/> if there are none.</returns>
async ValueTask<TimeSpan?> CalculateExpectedDeploymentTime(IDatabaseContext databaseContext, CancellationToken cancellationToken)
{
var previousCompileJobs = await databaseContext
.CompileJobs
@@ -462,8 +462,8 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <param name="estimatedDuration">The optional estimated <see cref="TimeSpan"/> of the compilation.</param>
/// <param name="localCommitExistsOnRemote">Whether or not the <paramref name="repository"/>'s current commit exists on the remote repository.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the completed <see cref="CompileJob"/>.</returns>
async Task<Models.CompileJob> Compile(
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the completed <see cref="CompileJob"/>.</returns>
async ValueTask<Models.CompileJob> Compile(
Models.RevisionInformation revisionInformation,
Api.Models.Internal.DreamMakerSettings dreamMakerSettings,
DreamDaemonLaunchParameters launchParameters,
@@ -557,8 +557,8 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <param name="repository">The <see cref="IRepository"/> to use.</param>
/// <param name="remoteDeploymentManager">The <see cref="IRemoteDeploymentManager"/> to use.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task RunCompileJob(
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask RunCompileJob(
JobProgressReporter progressReporter,
Models.CompileJob job,
Api.Models.Internal.DreamMakerSettings dreamMakerSettings,
@@ -711,8 +711,8 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <param name="progressReporter">The <see cref="JobProgressReporter"/> to report progress of the operation.</param>
/// <param name="estimatedDuration">A <see cref="TimeSpan"/> representing the duration to give progress over if any.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task ProgressTask(JobProgressReporter progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask ProgressTask(JobProgressReporter progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)
{
double? lastReport = estimatedDuration.HasValue ? 0 : null;
progressReporter.ReportProgress(lastReport);
@@ -774,8 +774,8 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <param name="requireValidate">If the API validation is required to complete the deployment.</param>
/// <param name="logOutput">If output should be logged to the DreamDaemon Diagnostics folder.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task VerifyApi(
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask VerifyApi(
uint timeout,
DreamDaemonSecurity securityLevel,
Models.CompileJob job,
@@ -856,8 +856,8 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <param name="dreamMakerPath">The path to the DreamMaker executable.</param>
/// <param name="job">The <see cref="CompileJob"/> for the operation.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task<int> RunDreamMaker(string dreamMakerPath, Models.CompileJob job, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask<int> RunDreamMaker(string dreamMakerPath, Models.CompileJob job, CancellationToken cancellationToken)
{
await using var dm = processExecutor.LaunchProcess(
dreamMakerPath,
@@ -887,8 +887,8 @@ namespace Tgstation.Server.Host.Components.Deployment
/// </summary>
/// <param name="job">The <see cref="CompileJob"/> for the operation.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task ModifyDme(Models.CompileJob job, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask ModifyDme(Models.CompileJob job, CancellationToken cancellationToken)
{
var dmeFileName = String.Join('.', job.DmeName, DmeExtension);
var dmePath = ioManager.ConcatPath(job.DirectoryName.ToString(), dmeFileName);
@@ -74,8 +74,8 @@ namespace Tgstation.Server.Host.Components.Deployment
/// Make the <see cref="SwappableDmbProvider"/> active by replacing the live link with our <see cref="CompileJob"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
public async Task MakeActive(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
public async ValueTask MakeActive(CancellationToken cancellationToken)
{
if (Interlocked.Exchange(ref swapped, 1) != 0)
throw new InvalidOperationException("Already swapped!");
@@ -317,7 +317,7 @@ namespace Tgstation.Server.Host.Components
var hasDbChanges = false;
RevisionInformation currentRevInfo = null;
Models.Instance attachedInstance = null;
async Task UpdateRevInfo(string currentHead, bool onOrigin, IEnumerable<TestMerge> updatedTestMerges)
async ValueTask UpdateRevInfo(string currentHead, bool onOrigin, IEnumerable<TestMerge> updatedTestMerges)
{
if (currentRevInfo == null)
{
@@ -419,7 +419,7 @@ namespace Tgstation.Server.Host.Components
public Task StartAsync(CancellationToken cancellationToken)
{
CheckSystemCompatibility();
return byondInstaller.CleanCache(cancellationToken).AsTask();
return byondInstaller.CleanCache(cancellationToken);
}
/// <inheritdoc />
@@ -460,7 +460,7 @@ namespace Tgstation.Server.Host.Components
var instanceFactoryStopTask = instanceFactory.StopAsync(cancellationToken);
await jobService.StopAsync(cancellationToken);
async Task OfflineInstanceImmediate(IInstance instance, CancellationToken cancellationToken)
async ValueTask OfflineInstanceImmediate(IInstance instance, CancellationToken cancellationToken)
{
try
{
@@ -472,7 +472,7 @@ namespace Tgstation.Server.Host.Components
}
}
await Task.WhenAll(instances.Select(x => OfflineInstanceImmediate(x.Value.Instance, cancellationToken)));
await ValueTaskExtensions.WhenAll(instances.Select(x => OfflineInstanceImmediate(x.Value.Instance, cancellationToken)));
await instanceFactoryStopTask;
await swarmServiceController.Shutdown(cancellationToken);
@@ -490,7 +490,7 @@ namespace Tgstation.Server.Host.Components
}
/// <inheritdoc />
public async Task<BridgeResponse> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken)
public async ValueTask<BridgeResponse> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(parameters);
@@ -650,8 +650,8 @@ namespace Tgstation.Server.Host.Components
/// Initializes the connection to the TGS swarm.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task InitializeSwarm(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask InitializeSwarm(CancellationToken cancellationToken)
{
SwarmRegistrationResult registrationResult;
do
@@ -13,7 +13,7 @@ namespace Tgstation.Server.Host.Components.Interop.Bridge
/// </summary>
/// <param name="parameters">The <see cref="BridgeParameters"/> to handle.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="BridgeResponse"/> for the request or <see langword="null"/> if the request could not be dispatched.</returns>
Task<BridgeResponse> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="BridgeResponse"/> for the request or <see langword="null"/> if the request could not be dispatched.</returns>
ValueTask<BridgeResponse> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken);
}
}
@@ -63,9 +63,9 @@ namespace Tgstation.Server.Host.Components.Interop
/// <param name="chunkErrorCallback">The callback that generates a <typeparamref name="TResponse"/> for a given error.</param>
/// <param name="chunk">The <see cref="ChunkData"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <typeparamref name="TResponse"/> for the chunked request.</returns>
protected async Task<TResponse> ProcessChunk<TCommnication, TResponse>(
Func<TCommnication, CancellationToken, Task<TResponse>> completionCallback,
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <typeparamref name="TResponse"/> for the chunked request.</returns>
protected async ValueTask<TResponse> ProcessChunk<TCommnication, TResponse>(
Func<TCommnication, CancellationToken, ValueTask<TResponse>> completionCallback,
Func<string, TResponse> chunkErrorCallback,
ChunkData chunk,
CancellationToken cancellationToken)
@@ -535,7 +535,7 @@ namespace Tgstation.Server.Host.Components.Repository
if (postWriteHandler.NeedsPostWrite(src))
postWriteHandler.HandleWrite(dest);
return Task.CompletedTask;
return ValueTask.CompletedTask;
},
ioMananger.ResolvePath(),
path,
@@ -992,8 +992,8 @@ namespace Tgstation.Server.Host.Components.Repository
/// <param name="password">The password for the <see cref="credentialsProvider"/>.</param>
/// <param name="deploymentPipeline">If any events created should be marked as part of the deployment pipeline.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task UpdateSubmodules(
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask UpdateSubmodules(
JobProgressReporter progressReporter,
string username,
string password,
@@ -362,7 +362,7 @@ namespace Tgstation.Server.Host.Components.Session
}
/// <inheritdoc />
public async Task<BridgeResponse> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken)
public async ValueTask<BridgeResponse> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(parameters);
@@ -439,7 +439,7 @@ namespace Tgstation.Server.Host.Components.Session
(completedResponse, cancellationToken) =>
{
fullResponse = completedResponse;
return Task.FromResult<ChunkedTopicParameters>(null);
return ValueTask.FromResult<ChunkedTopicParameters>(null);
},
error =>
{
@@ -574,7 +574,7 @@ namespace Tgstation.Server.Host.Components.Session
cancellationToken);
/// <inheritdoc />
public Task CreateDump(string outputFile, CancellationToken cancellationToken) => process.CreateDump(outputFile, cancellationToken);
public ValueTask CreateDump(string outputFile, CancellationToken cancellationToken) => process.CreateDump(outputFile, cancellationToken);
/// <summary>
/// The <see cref="Task{TResult}"/> for <see cref="LaunchResult"/>.
@@ -660,8 +660,8 @@ namespace Tgstation.Server.Host.Components.Session
/// </summary>
/// <param name="parameters">The <see cref="BridgeParameters"/> to handle.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="BridgeResponse"/> for the request or <see langword="null"/> if the request could not be dispatched.</returns>
async Task<BridgeResponse> ProcessBridgeCommand(BridgeParameters parameters, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="BridgeResponse"/> for the request or <see langword="null"/> if the request could not be dispatched.</returns>
async ValueTask<BridgeResponse> ProcessBridgeCommand(BridgeParameters parameters, CancellationToken cancellationToken)
{
var response = new BridgeResponse();
switch (parameters.CommandType)
@@ -828,8 +828,8 @@ namespace Tgstation.Server.Host.Components.Session
/// </summary>
/// <param name="parameters">The <see cref="TopicParameters"/> to send.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="CombinedTopicResponse"/> of the topic request.</returns>
async Task<CombinedTopicResponse> SendTopicRequest(TopicParameters parameters, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="CombinedTopicResponse"/> of the topic request.</returns>
async ValueTask<CombinedTopicResponse> SendTopicRequest(TopicParameters parameters, CancellationToken cancellationToken)
{
parameters.AccessIdentifier = ReattachInformation.AccessIdentifier;
@@ -971,8 +971,8 @@ namespace Tgstation.Server.Host.Components.Session
/// <param name="queryString">The sanitized topic query string to send.</param>
/// <param name="priority">If this is a priority message. If so, the topic will make 5 attempts to send unless BYOND reboots or exits.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="CombinedTopicResponse"/> of the topic request.</returns>
async Task<CombinedTopicResponse> SendRawTopic(string queryString, bool priority, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="CombinedTopicResponse"/> of the topic request.</returns>
async ValueTask<CombinedTopicResponse> SendRawTopic(string queryString, bool priority, CancellationToken cancellationToken)
{
if (disposed)
{
@@ -239,6 +239,7 @@ namespace Tgstation.Server.Host.Components.Session
}
/// <inheritdoc />
#pragma warning disable CA1506 // TODO: Decomplexify
public async ValueTask<ISessionController> LaunchNew(
IDmbProvider dmbProvider,
IByondExecutableLock currentByondLock,
@@ -283,7 +284,7 @@ namespace Tgstation.Server.Host.Components.Session
dmbProvider.CompileJob.Id);
PortBindTest(launchParameters.Port.Value);
await CheckPagerIsNotRunning(cancellationToken);
await CheckPagerIsNotRunning();
string outputFilePath = null;
var preserveLogFile = true;
@@ -393,6 +394,7 @@ namespace Tgstation.Server.Host.Components.Session
throw;
}
}
#pragma warning restore CA1506
/// <inheritdoc />
public async ValueTask<ISessionController> Reattach(
@@ -647,9 +649,8 @@ namespace Tgstation.Server.Host.Components.Session
/// <summary>
/// Make sure the BYOND pager is not running.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task CheckPagerIsNotRunning(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask CheckPagerIsNotRunning()
{
if (!platformIdentifier.IsWindows)
return;
@@ -658,12 +659,12 @@ namespace Tgstation.Server.Host.Components.Session
if (otherProcess == null)
return;
var otherUsernameTask = otherProcess.GetExecutingUsername(cancellationToken);
await using var ourProcess = processExecutor.GetCurrentProcess();
var ourUserName = await ourProcess.GetExecutingUsername(cancellationToken);
var otherUserName = await otherUsernameTask;
var otherUsername = otherProcess.GetExecutingUsername();
if (otherUserName.Equals(ourUserName, StringComparison.Ordinal))
await using var ourProcess = processExecutor.GetCurrentProcess();
var ourUsername = ourProcess.GetExecutingUsername();
if (otherUsername.Equals(ourUsername, StringComparison.Ordinal))
throw new JobException(ErrorCode.DeploymentPagerRunning);
}
}
@@ -95,7 +95,7 @@ namespace Tgstation.Server.Host.Components.Session
Models.ReattachInformation result = null;
TimeSpan? topicTimeout = null;
async Task KillProcess(Models.ReattachInformation reattachInfo)
async ValueTask KillProcess(Models.ReattachInformation reattachInfo)
{
try
{
@@ -219,7 +219,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles
generalConfiguration.GetCopyDirectoryTaskThrottle(),
cancellationToken);
await Task.WhenAll(dmeExistsTask, headFileExistsTask, tailFileExistsTask, copyTask);
await Task.WhenAll(dmeExistsTask, headFileExistsTask, tailFileExistsTask, copyTask.AsTask());
if (!dmeExistsTask.Result && !headFileExistsTask.Result && !tailFileExistsTask.Result)
return null;
@@ -396,26 +396,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles
/// <inheritdoc />
public async ValueTask SymlinkStaticFilesTo(string destination, CancellationToken cancellationToken)
{
async Task<IReadOnlyList<string>> GetIgnoreFiles()
{
var ignoreFileBytes = await ioManager.ReadAllBytes(StaticIgnorePath(), cancellationToken);
var ignoreFileText = Encoding.UTF8.GetString(ignoreFileBytes);
var results = new List<string> { StaticIgnoreFile };
// we don't want to lose trailing whitespace on linux
using (var reader = new StringReader(ignoreFileText))
{
cancellationToken.ThrowIfCancellationRequested();
var line = await reader.ReadLineAsync();
if (!String.IsNullOrEmpty(line))
results.Add(line);
}
return results;
}
IReadOnlyList<string> ignoreFiles;
List<string> ignoreFiles;
async ValueTask SymlinkBase(bool files)
{
@@ -458,7 +439,20 @@ namespace Tgstation.Server.Host.Components.StaticFiles
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken))
{
await EnsureDirectories(cancellationToken);
ignoreFiles = await GetIgnoreFiles();
var ignoreFileBytes = await ioManager.ReadAllBytes(StaticIgnorePath(), cancellationToken);
var ignoreFileText = Encoding.UTF8.GetString(ignoreFileBytes);
ignoreFiles = new List<string> { StaticIgnoreFile };
// we don't want to lose trailing whitespace on linux
using (var reader = new StringReader(ignoreFileText))
{
cancellationToken.ThrowIfCancellationRequested();
var line = await reader.ReadLineAsync();
if (!String.IsNullOrEmpty(line))
ignoreFiles.Add(line);
}
await ValueTaskExtensions.WhenAll(SymlinkBase(true), SymlinkBase(false));
}
}
@@ -705,7 +699,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task EnsureDirectories(CancellationToken cancellationToken)
Task EnsureDirectories(CancellationToken cancellationToken)
{
async Task ValidateStaticFolder()
{
@@ -721,7 +715,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles
return;
await ioManager.CreateDirectory(CodeModificationsSubdirectory, cancellationToken);
await Task.WhenAll(
await ValueTaskExtensions.WhenAll(
ioManager.WriteAllBytes(
ioManager.ConcatPath(
CodeModificationsSubdirectory,
@@ -736,7 +730,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles
cancellationToken));
}
await Task.WhenAll(
return Task.WhenAll(
ValidateCodeModsFolder(),
ioManager.CreateDirectory(EventScriptsSubdirectory, cancellationToken),
ValidateStaticFolder());
@@ -395,8 +395,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
}
/// <inheritdoc />
public Task StopAsync(CancellationToken cancellationToken) =>
TerminateNoLock(false, !releaseServers, cancellationToken);
public async Task StopAsync(CancellationToken cancellationToken) =>
await TerminateNoLock(false, !releaseServers, cancellationToken);
/// <inheritdoc />
public async ValueTask Terminate(bool graceful, CancellationToken cancellationToken)
@@ -1002,8 +1002,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="graceful">If <see langword="true"/> the termination will be delayed until a reboot is detected in the active server's DMAPI and this function will return immediately.</param>
/// <param name="announce">If <see langword="true"/> the termination will be announced using <see cref="Chat"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task TerminateNoLock(bool graceful, bool announce, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask TerminateNoLock(bool graceful, bool announce, CancellationToken cancellationToken)
{
if (Status == WatchdogStatus.Offline)
return;
@@ -331,8 +331,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// Create the initial link to the live game directory using <see cref="ActiveSwappable"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task InitialLink(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask InitialLink(CancellationToken cancellationToken)
{
Logger.LogTrace("Symlinking compile job...");
return ActiveSwappable.MakeActive(cancellationToken);
@@ -95,14 +95,14 @@ namespace Tgstation.Server.Host.IO
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
public Task EnsureBuffered(CancellationToken cancellationToken) => GetResultInternal(cancellationToken);
public Task EnsureBuffered(CancellationToken cancellationToken) => GetResultInternal(cancellationToken).AsTask();
/// <summary>
/// Gets the shared <see cref="MemoryStream"/> and its <see cref="Stream.Length"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in <see cref="buffer"/> and its <see cref="Stream.Length"/>.</returns>
async Task<(MemoryStream, long)> GetResultInternal(CancellationToken cancellationToken)
async ValueTask<(MemoryStream, long)> GetResultInternal(CancellationToken cancellationToken)
{
if (!buffered)
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken))
@@ -68,9 +68,9 @@ namespace Tgstation.Server.Host.IO
}
/// <inheritdoc />
public async Task CopyDirectory(
public async ValueTask CopyDirectory(
IEnumerable<string> ignore,
Func<string, string, Task> postCopyCallback,
Func<string, string, ValueTask> postCopyCallback,
string src,
string dest,
int? taskThrottle,
@@ -93,7 +93,7 @@ namespace Tgstation.Server.Host.IO
public string ConcatPath(params string[] paths) => Path.Combine(paths);
/// <inheritdoc />
public async Task CopyFile(string src, string dest, CancellationToken cancellationToken)
public async ValueTask CopyFile(string src, string dest, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(src);
ArgumentNullException.ThrowIfNull(dest);
@@ -197,7 +197,7 @@ namespace Tgstation.Server.Host.IO
TaskScheduler.Current);
/// <inheritdoc />
public async Task<byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
public async ValueTask<byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
{
path = ResolvePath(path);
await using var file = new FileStream(
@@ -220,7 +220,7 @@ namespace Tgstation.Server.Host.IO
public virtual string ResolvePath(string path) => Path.GetFullPath(path ?? throw new ArgumentNullException(nameof(path)));
/// <inheritdoc />
public async Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
public async ValueTask WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
{
await using var file = CreateAsyncSequentialWriteStream(path);
await file.WriteAsync(contents, cancellationToken);
@@ -345,7 +345,7 @@ namespace Tgstation.Server.Host.IO
string src,
string dest,
IEnumerable<string> ignore,
Func<string, string, Task> postCopyCallback,
Func<string, string, ValueTask> postCopyCallback,
SemaphoreSlim semaphore,
CancellationToken cancellationToken)
{
+9 -9
View File
@@ -54,10 +54,10 @@ namespace Tgstation.Server.Host.IO
/// <param name="dest">The destination directory path.</param>
/// <param name="taskThrottle">The optional maximum number of simultaneous tasks allowed to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task CopyDirectory(
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask CopyDirectory(
IEnumerable<string> ignore,
Func<string, string, Task> postCopyCallback,
Func<string, string, ValueTask> postCopyCallback,
string src,
string dest,
int? taskThrottle,
@@ -84,8 +84,8 @@ namespace Tgstation.Server.Host.IO
/// </summary>
/// <param name="path">The path of the file to read.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> that results in the contents of a file at <paramref name="path"/>.</returns>
Task<byte[]> ReadAllBytes(string path, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> that results in the contents of a file at <paramref name="path"/>.</returns>
ValueTask<byte[]> ReadAllBytes(string path, CancellationToken cancellationToken);
/// <summary>
/// Returns directory names in a given <paramref name="path"/>.
@@ -116,8 +116,8 @@ namespace Tgstation.Server.Host.IO
/// <param name="path">The path of the file to write.</param>
/// <param name="contents">The contents of the file.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken);
/// <summary>
/// Copy a file from <paramref name="src"/> to <paramref name="dest"/>.
@@ -125,8 +125,8 @@ namespace Tgstation.Server.Host.IO
/// <param name="src">The source file to copy.</param>
/// <param name="dest">The destination path.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task CopyFile(string src, string dest, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask CopyFile(string src, string dest, CancellationToken cancellationToken);
/// <summary>
/// Gets the directory portion of a given <paramref name="path"/>.
+30 -30
View File
@@ -137,8 +137,8 @@ namespace Tgstation.Server.Host.Setup
/// <param name="question">The question <see cref="string"/>.</param>
/// <param name="defaultResponse">The optional default response if the user doesn't enter anything.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> resulting in <see langword="true"/> if the user replied yes, <see langword="false"/> otherwise.</returns>
async Task<bool> PromptYesNo(string question, bool? defaultResponse, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> resulting in <see langword="true"/> if the user replied yes, <see langword="false"/> otherwise.</returns>
async ValueTask<bool> PromptYesNo(string question, bool? defaultResponse, CancellationToken cancellationToken)
{
do
{
@@ -167,8 +167,8 @@ namespace Tgstation.Server.Host.Setup
/// Prompts the user to enter the port to host TGS on.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> resulting in the hosting port, or <see langword="null"/> to use the default.</returns>
async Task<ushort?> PromptForHostingPort(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> resulting in the hosting port, or <see langword="null"/> to use the default.</returns>
async ValueTask<ushort?> PromptForHostingPort(CancellationToken cancellationToken)
{
await console.WriteAsync(null, true, cancellationToken);
await console.WriteAsync("What port would you like to connect to TGS on?", true, cancellationToken);
@@ -198,8 +198,8 @@ namespace Tgstation.Server.Host.Setup
/// <param name="databaseName">The database name (or path in the case of a <see cref="DatabaseType.Sqlite"/> database).</param>
/// <param name="dbExists">Whether or not the database exists.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task TestDatabaseConnection(
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask TestDatabaseConnection(
DbConnection testConnection,
DatabaseConfiguration databaseConfiguration,
string databaseName,
@@ -290,8 +290,8 @@ namespace Tgstation.Server.Host.Setup
/// </summary>
/// <param name="databaseName">The path to the potential SQLite database file.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the SQLite database path to store in the configuration.</returns>
async Task<string> ValidateNonExistantSqliteDBName(string databaseName, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the SQLite database path to store in the configuration.</returns>
async ValueTask<string> ValidateNonExistantSqliteDBName(string databaseName, CancellationToken cancellationToken)
{
var dbPathIsRooted = Path.IsPathRooted(databaseName);
var resolvedPath = ioManager.ResolvePath(
@@ -343,8 +343,8 @@ namespace Tgstation.Server.Host.Setup
/// </summary>
/// <param name="firstTime">If this is the user's first time here.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the input <see cref="DatabaseType"/>.</returns>
async Task<DatabaseType> PromptDatabaseType(bool firstTime, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the input <see cref="DatabaseType"/>.</returns>
async ValueTask<DatabaseType> PromptDatabaseType(bool firstTime, CancellationToken cancellationToken)
{
if (firstTime)
{
@@ -392,9 +392,9 @@ namespace Tgstation.Server.Host.Setup
/// Prompts the user to create a <see cref="DatabaseConfiguration"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the new <see cref="DatabaseConfiguration"/>.</returns>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the new <see cref="DatabaseConfiguration"/>.</returns>
#pragma warning disable CA1502 // TODO: Decomplexify
async Task<DatabaseConfiguration> ConfigureDatabase(CancellationToken cancellationToken)
async ValueTask<DatabaseConfiguration> ConfigureDatabase(CancellationToken cancellationToken)
{
bool firstTime = true;
do
@@ -656,8 +656,8 @@ namespace Tgstation.Server.Host.Setup
/// Prompts the user to create a <see cref="GeneralConfiguration"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the new <see cref="GeneralConfiguration"/>.</returns>
async Task<GeneralConfiguration> ConfigureGeneral(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the new <see cref="GeneralConfiguration"/>.</returns>
async ValueTask<GeneralConfiguration> ConfigureGeneral(CancellationToken cancellationToken)
{
var newGeneralConfiguration = new GeneralConfiguration
{
@@ -714,8 +714,8 @@ namespace Tgstation.Server.Host.Setup
/// Prompts the user to create a <see cref="FileLoggingConfiguration"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the new <see cref="FileLoggingConfiguration"/>.</returns>
async Task<FileLoggingConfiguration> ConfigureLogging(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the new <see cref="FileLoggingConfiguration"/>.</returns>
async ValueTask<FileLoggingConfiguration> ConfigureLogging(CancellationToken cancellationToken)
{
var fileLoggingConfiguration = new FileLoggingConfiguration();
await console.WriteAsync(null, true, cancellationToken);
@@ -771,7 +771,7 @@ namespace Tgstation.Server.Host.Setup
}
while (true);
async Task<LogLevel?> PromptLogLevel(string question)
async ValueTask<LogLevel?> PromptLogLevel(string question)
{
do
{
@@ -799,8 +799,8 @@ namespace Tgstation.Server.Host.Setup
/// Prompts the user to create a <see cref="ElasticsearchConfiguration"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the new <see cref="ElasticsearchConfiguration"/>.</returns>
async Task<ElasticsearchConfiguration> ConfigureElasticsearch(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the new <see cref="ElasticsearchConfiguration"/>.</returns>
async ValueTask<ElasticsearchConfiguration> ConfigureElasticsearch(CancellationToken cancellationToken)
{
var elasticsearchConfiguration = new ElasticsearchConfiguration();
await console.WriteAsync(null, true, cancellationToken);
@@ -851,8 +851,8 @@ namespace Tgstation.Server.Host.Setup
/// Prompts the user to create a <see cref="ControlPanelConfiguration"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the new <see cref="ControlPanelConfiguration"/>.</returns>
async Task<ControlPanelConfiguration> ConfigureControlPanel(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the new <see cref="ControlPanelConfiguration"/>.</returns>
async ValueTask<ControlPanelConfiguration> ConfigureControlPanel(CancellationToken cancellationToken)
{
var config = new ControlPanelConfiguration
{
@@ -881,8 +881,8 @@ namespace Tgstation.Server.Host.Setup
/// Prompts the user to create a <see cref="SwarmConfiguration"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the new <see cref="SwarmConfiguration"/>.</returns>
async Task<SwarmConfiguration> ConfigureSwarm(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the new <see cref="SwarmConfiguration"/>.</returns>
async ValueTask<SwarmConfiguration> ConfigureSwarm(CancellationToken cancellationToken)
{
var enable = await PromptYesNo("Enable swarm mode?", false, cancellationToken);
if (!enable)
@@ -896,7 +896,7 @@ namespace Tgstation.Server.Host.Setup
}
while (String.IsNullOrWhiteSpace(identifer));
async Task<Uri> ParseAddress(string question)
async ValueTask<Uri> ParseAddress(string question)
{
var first = true;
Uri address;
@@ -956,8 +956,8 @@ namespace Tgstation.Server.Host.Setup
/// <param name="controlPanelConfiguration">The <see cref="ControlPanelConfiguration"/> to save.</param>
/// <param name="swarmConfiguration">The <see cref="SwarmConfiguration"/> to save.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task SaveConfiguration(
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask SaveConfiguration(
string userConfigFileName,
ushort? hostingPort,
DatabaseConfiguration databaseConfiguration,
@@ -1027,8 +1027,8 @@ namespace Tgstation.Server.Host.Setup
/// </summary>
/// <param name="userConfigFileName">The path to the settings json to build.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task RunWizard(string userConfigFileName, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask RunWizard(string userConfigFileName, CancellationToken cancellationToken)
{
// welcome message
await console.WriteAsync($"Welcome to {Constants.CanonicalPackageName}!", true, cancellationToken);
@@ -1067,8 +1067,8 @@ namespace Tgstation.Server.Host.Setup
/// Check if it should and run the <see cref="SetupWizard"/> if necessary.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task CheckRunWizard(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask CheckRunWizard(CancellationToken cancellationToken)
{
var setupWizardMode = generalConfiguration.SetupWizardMode;
if (setupWizardMode == SetupWizardMode.Never)
@@ -23,8 +23,8 @@ namespace Tgstation.Server.Host.Swarm
/// </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 <see langword="true"/> if the node is able to update, <see langword="false"/> otherwise.</returns>
Task<bool> PrepareUpdateFromController(SwarmUpdateRequest updateRequest, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in <see langword="true"/> if the node is able to update, <see langword="false"/> otherwise.</returns>
ValueTask<bool> PrepareUpdateFromController(SwarmUpdateRequest updateRequest, CancellationToken cancellationToken);
/// <summary>
/// Validate a given <paramref name="registrationId"/>.
@@ -39,23 +39,23 @@ namespace Tgstation.Server.Host.Swarm
/// <param name="node">The <see cref="SwarmServerResponse"/> that is registering.</param>
/// <param name="registrationId">The registration <see cref="Guid"/>.</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 registration was successful, <see langword="false"/> otherwise.</returns>
Task<bool> RegisterNode(Api.Models.Internal.SwarmServer node, Guid registrationId, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in <see langword="true"/> if the registration was successful, <see langword="false"/> otherwise.</returns>
ValueTask<bool> RegisterNode(Api.Models.Internal.SwarmServer node, Guid registrationId, CancellationToken cancellationToken);
/// <summary>
/// Attempt to unregister a node with a given <paramref name="registrationId"/> with the controller.
/// </summary>
/// <param name="registrationId">The registration <see cref="Guid"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task UnregisterNode(Guid registrationId, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask UnregisterNode(Guid registrationId, CancellationToken cancellationToken);
/// <summary>
/// Notify the controller that the node with the given <paramref name="registrationId"/> is ready to commit or notify the node of the controller telling it to commit.
/// </summary>
/// <param name="registrationId">The registration <see cref="Guid"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task<bool> RemoteCommitRecieved(Guid registrationId, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask<bool> RemoteCommitRecieved(Guid registrationId, CancellationToken cancellationToken);
}
}
@@ -24,15 +24,15 @@ namespace Tgstation.Server.Host.Swarm
/// <param name="fileStreamProvider">The <see cref="ISeekableFileStreamProvider"/> to relay to other nodes.</param>
/// <param name="version">The <see cref="Version"/> to update to.</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 update should proceed, <see langword="false"/> otherwise.</returns>
Task<SwarmPrepareResult> PrepareUpdate(ISeekableFileStreamProvider fileStreamProvider, Version version, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in <see langword="true"/> if the update should proceed, <see langword="false"/> otherwise.</returns>
ValueTask<SwarmPrepareResult> PrepareUpdate(ISeekableFileStreamProvider fileStreamProvider, Version version, CancellationToken cancellationToken);
/// <summary>
/// Signal to the swarm that an update is ready to be applied.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="SwarmCommitResult"/>.</returns>
Task<SwarmCommitResult> CommitUpdate(CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="SwarmCommitResult"/>.</returns>
ValueTask<SwarmCommitResult> CommitUpdate(CancellationToken cancellationToken);
/// <summary>
/// Gets the list of <see cref="SwarmServerResponse"/>s in the swarm, including the current one.
@@ -12,14 +12,14 @@ namespace Tgstation.Server.Host.Swarm
/// Attempt to register with the swarm controller if not one, sets up the database otherwise.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="SwarmRegistrationResult"/>.</returns>
Task<SwarmRegistrationResult> Initialize(CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="SwarmRegistrationResult"/>.</returns>
ValueTask<SwarmRegistrationResult> Initialize(CancellationToken cancellationToken);
/// <summary>
/// Deregister with the swarm controller or put clients into querying state.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task Shutdown(CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask Shutdown(CancellationToken cancellationToken);
}
}
@@ -10,8 +10,8 @@ namespace Tgstation.Server.Host.Swarm
/// <summary>
/// Attempt to abort an uncommitted update.
/// </summary>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
/// <remarks>This method does not accept a <see cref="global::System.Threading.CancellationToken"/> because aborting an update should never be cancelled.</remarks>
Task AbortUpdate();
ValueTask AbortUpdate();
}
}
+46 -41
View File
@@ -16,6 +16,7 @@ using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Tgstation.Server.Api.Models.Response;
using Tgstation.Server.Common.Extensions;
using Tgstation.Server.Common.Http;
using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.Core;
@@ -211,7 +212,7 @@ namespace Tgstation.Server.Host.Swarm
public void Dispose() => serverHealthCheckCancellationTokenSource?.Dispose();
/// <inheritdoc />
public async Task AbortUpdate()
public async ValueTask AbortUpdate()
{
if (!SwarmMode)
return;
@@ -239,7 +240,7 @@ namespace Tgstation.Server.Host.Swarm
}
/// <inheritdoc />
public async Task<SwarmCommitResult> CommitUpdate(CancellationToken cancellationToken)
public async ValueTask<SwarmCommitResult> CommitUpdate(CancellationToken cancellationToken)
{
if (!SwarmMode)
return SwarmCommitResult.ContinueUpdateNonCommitted;
@@ -311,7 +312,7 @@ namespace Tgstation.Server.Host.Swarm
// on the controller, we first need to signal for nodes to go ahead
// if anything fails at this point, there's nothing we can do
logger.LogDebug("Sending remote commit message to nodes...");
async Task SendRemoteCommitUpdate(SwarmServerResponse swarmServer)
async ValueTask SendRemoteCommitUpdate(SwarmServerResponse swarmServer)
{
using var request = PrepareSwarmRequest(
swarmServer,
@@ -332,12 +333,13 @@ namespace Tgstation.Server.Host.Swarm
}
}
Task task;
ValueTask task;
lock (swarmServers)
task = Task.WhenAll(
task = ValueTaskExtensions.WhenAll(
swarmServers
.Where(x => !x.Controller)
.Select(SendRemoteCommitUpdate));
.Select(SendRemoteCommitUpdate)
.ToList());
await task;
return SwarmCommitResult.MustCommitUpdate;
@@ -354,7 +356,7 @@ namespace Tgstation.Server.Host.Swarm
}
/// <inheritdoc />
public Task<SwarmPrepareResult> PrepareUpdate(ISeekableFileStreamProvider fileStreamProvider, Version version, CancellationToken cancellationToken)
public ValueTask<SwarmPrepareResult> PrepareUpdate(ISeekableFileStreamProvider fileStreamProvider, Version version, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(fileStreamProvider);
@@ -371,7 +373,7 @@ namespace Tgstation.Server.Host.Swarm
}
/// <inheritdoc />
public async Task<bool> PrepareUpdateFromController(SwarmUpdateRequest updateRequest, CancellationToken cancellationToken)
public async ValueTask<bool> PrepareUpdateFromController(SwarmUpdateRequest updateRequest, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(updateRequest);
@@ -385,7 +387,7 @@ namespace Tgstation.Server.Host.Swarm
}
/// <inheritdoc />
public async Task<SwarmRegistrationResult> Initialize(CancellationToken cancellationToken)
public async ValueTask<SwarmRegistrationResult> Initialize(CancellationToken cancellationToken)
{
if (SwarmMode)
logger.LogInformation(
@@ -418,11 +420,11 @@ namespace Tgstation.Server.Host.Swarm
}
/// <inheritdoc />
public async Task Shutdown(CancellationToken cancellationToken)
public async ValueTask Shutdown(CancellationToken cancellationToken)
{
logger.LogTrace("Begin Shutdown");
async Task SendUnregistrationRequest(SwarmServerResponse swarmServer)
async ValueTask SendUnregistrationRequest(SwarmServerResponse swarmServer)
{
using var httpClient = httpClientFactory.CreateClient();
using var request = PrepareSwarmRequest(
@@ -478,13 +480,14 @@ namespace Tgstation.Server.Host.Swarm
if (updateOperation == null)
{
logger.LogInformation("Unregistering nodes...");
Task task;
ValueTask task;
lock (swarmServers)
{
task = Task.WhenAll(
task = ValueTaskExtensions.WhenAll(
swarmServers
.Where(x => !x.Controller)
.Select(SendUnregistrationRequest));
.Select(SendUnregistrationRequest)
.ToList());
swarmServers.RemoveRange(1, swarmServers.Count - 1);
registrationIdsAndTimes.Clear();
}
@@ -527,7 +530,7 @@ namespace Tgstation.Server.Host.Swarm
}
/// <inheritdoc />
public async Task<bool> RegisterNode(Api.Models.Internal.SwarmServer node, Guid registrationId, CancellationToken cancellationToken)
public async ValueTask<bool> RegisterNode(Api.Models.Internal.SwarmServer node, Guid registrationId, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(node);
@@ -586,7 +589,7 @@ namespace Tgstation.Server.Host.Swarm
}
/// <inheritdoc />
public async Task<bool> RemoteCommitRecieved(Guid registrationId, CancellationToken cancellationToken)
public async ValueTask<bool> RemoteCommitRecieved(Guid registrationId, CancellationToken cancellationToken)
{
var localUpdateOperation = updateOperation;
if (!swarmController)
@@ -635,7 +638,7 @@ namespace Tgstation.Server.Host.Swarm
}
/// <inheritdoc />
public async Task UnregisterNode(Guid registrationId, CancellationToken cancellationToken)
public async ValueTask UnregisterNode(Guid registrationId, CancellationToken cancellationToken)
{
logger.LogTrace("UnregisterNode {registrationId}", registrationId);
await AbortUpdate();
@@ -667,14 +670,14 @@ namespace Tgstation.Server.Host.Swarm
/// <summary>
/// Sends out remote abort update requests.
/// </summary>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
/// <remarks>The aborted <see cref="updateOperation"/> should be cleared out before calling this. This method does not accept a <see cref="CancellationToken"/> because aborting an update should never be cancelled.</remarks>
Task RemoteAbortUpdate()
ValueTask RemoteAbortUpdate()
{
logger.LogInformation("Aborting swarm update!");
using var httpClient = httpClientFactory.CreateClient();
async Task SendRemoteAbort(SwarmServerResponse swarmServer)
async ValueTask SendRemoteAbort(SwarmServerResponse swarmServer)
{
using var request = PrepareSwarmRequest(
swarmServer,
@@ -706,10 +709,11 @@ namespace Tgstation.Server.Host.Swarm
});
lock (swarmServers)
return Task.WhenAll(
return ValueTaskExtensions.WhenAll(
swarmServers
.Where(x => !x.Controller)
.Select(SendRemoteAbort));
.Select(SendRemoteAbort)
.ToList());
}
/// <summary>
@@ -753,8 +757,8 @@ namespace Tgstation.Server.Host.Swarm
/// <param name="initiatorProvider">The <see cref="ISeekableFileStreamProvider"/> containing the update package if this is the initiating server, <see langword="null"/> otherwise.</param>
/// <param name="updateRequest">The <see cref="SwarmUpdateRequest"/>. Must always have <see cref="SwarmUpdateRequest.UpdateVersion"/> populated. If <paramref name="initiatorProvider"/> is <see langword="null"/>, it must be fully populated.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="SwarmPrepareResult"/>.</returns>
async Task<SwarmPrepareResult> PrepareUpdateImpl(ISeekableFileStreamProvider initiatorProvider, SwarmUpdateRequest updateRequest, CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="SwarmPrepareResult"/>.</returns>
async ValueTask<SwarmPrepareResult> PrepareUpdateImpl(ISeekableFileStreamProvider initiatorProvider, SwarmUpdateRequest updateRequest, CancellationToken cancellationToken)
{
if (!SwarmMode)
{
@@ -916,8 +920,8 @@ namespace Tgstation.Server.Host.Swarm
/// <param name="updateRequest">The <see cref="SwarmUpdateRequest"/>. Must always have <see cref="SwarmUpdateRequest.UpdateVersion"/> populated. If <paramref name="initiatorProvider"/> is <see langword="null"/>, it must be fully populated.</param>
/// <param name="currentUpdateOperation">The current <see cref="SwarmUpdateOperation"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="SwarmPrepareResult"/>.</returns>
async Task<SwarmPrepareResult> ControllerDistributedPrepareUpdate(
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="SwarmPrepareResult"/>.</returns>
async ValueTask<SwarmPrepareResult> ControllerDistributedPrepareUpdate(
ISeekableFileStreamProvider initiatorProvider,
SwarmUpdateRequest updateRequest,
SwarmUpdateOperation currentUpdateOperation,
@@ -1056,8 +1060,8 @@ namespace Tgstation.Server.Host.Swarm
/// <param name="initiatorProvider">The <see cref="ISeekableFileStreamProvider"/> containing the server update package.</param>
/// <param name="involvedServers">An <see cref="IEnumerable{T}"/> of the involved <see cref="SwarmServerResponse"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in a new <see cref="Dictionary{TKey, TValue}"/> of unique <see cref="FileTicketResponse"/>s keyed by their <see cref="Api.Models.Internal.SwarmServer.Identifier"/>.</returns>
async Task<Dictionary<string, FileTicketResponse>> CreateDownloadTickets(
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in a new <see cref="Dictionary{TKey, TValue}"/> of unique <see cref="FileTicketResponse"/>s keyed by their <see cref="Api.Models.Internal.SwarmServer.Identifier"/>.</returns>
async ValueTask<Dictionary<string, FileTicketResponse>> CreateDownloadTickets(
ISeekableFileStreamProvider initiatorProvider,
IReadOnlyCollection<SwarmServerResponse> involvedServers,
CancellationToken cancellationToken)
@@ -1093,8 +1097,8 @@ namespace Tgstation.Server.Host.Swarm
/// Ping each node to see that they are still running.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task HealthCheckNodes(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask HealthCheckNodes(CancellationToken cancellationToken)
{
using var httpClient = httpClientFactory.CreateClient();
@@ -1102,7 +1106,7 @@ namespace Tgstation.Server.Host.Swarm
lock (swarmServers)
currentSwarmServers = swarmServers.ToList();
async Task HealthRequestForServer(SwarmServerResponse swarmServer)
async ValueTask HealthRequestForServer(SwarmServerResponse swarmServer)
{
using var request = PrepareSwarmRequest(
swarmServer,
@@ -1131,7 +1135,7 @@ namespace Tgstation.Server.Host.Swarm
}
}
await Task.WhenAll(
await ValueTaskExtensions.WhenAll(
currentSwarmServers
.Where(node => !node.Controller
&& registrationIdsAndTimes.TryGetValue(node.Identifier, out var registrationAndTime)
@@ -1170,8 +1174,8 @@ namespace Tgstation.Server.Host.Swarm
/// Ping the swarm controller to see that it is still running. If need be, reregister.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task HealthCheckController(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask HealthCheckController(CancellationToken cancellationToken)
{
using var httpClient = httpClientFactory.CreateClient();
@@ -1227,8 +1231,8 @@ namespace Tgstation.Server.Host.Swarm
/// Attempt to register the node with the controller.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="SwarmRegistrationResult"/>.</returns>
async Task<SwarmRegistrationResult> RegisterWithController(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="SwarmRegistrationResult"/>.</returns>
async ValueTask<SwarmRegistrationResult> RegisterWithController(CancellationToken cancellationToken)
{
logger.LogInformation("Attempting to register with swarm controller at {controllerAddress}...", swarmConfiguration.ControllerAddress);
var requestedRegistrationId = Guid.NewGuid();
@@ -1289,8 +1293,8 @@ namespace Tgstation.Server.Host.Swarm
/// Sends the controllers list of nodes to all nodes.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task SendUpdatedServerListToNodes(CancellationToken cancellationToken)
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
async ValueTask SendUpdatedServerListToNodes(CancellationToken cancellationToken)
{
List<SwarmServerResponse> currentSwarmServers;
lock (swarmServers)
@@ -1308,7 +1312,7 @@ namespace Tgstation.Server.Host.Swarm
logger.LogDebug("Sending updated server list to all {nodeCount} nodes...", currentSwarmServers.Count - 1);
using var httpClient = httpClientFactory.CreateClient();
async Task UpdateRequestForServer(SwarmServerResponse swarmServer)
async ValueTask UpdateRequestForServer(SwarmServerResponse swarmServer)
{
using var request = PrepareSwarmRequest(
swarmServer,
@@ -1336,10 +1340,11 @@ namespace Tgstation.Server.Host.Swarm
}
}
await Task.WhenAll(
await ValueTaskExtensions.WhenAll(
currentSwarmServers
.Where(x => !x.Controller)
.Select(UpdateRequestForServer));
.Select(UpdateRequestForServer)
.ToList());
}
/// <summary>
+2 -3
View File
@@ -39,8 +39,7 @@ namespace Tgstation.Server.Host.System
/// <summary>
/// Get the name of the account executing the <see cref="IProcess"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the name of the account executing the <see cref="IProcess"/>.</returns>
Task<string> GetExecutingUsername(CancellationToken cancellationToken);
/// <returns>The name of the account executing the <see cref="IProcess"/>.</returns>
string GetExecutingUsername();
}
}
@@ -34,7 +34,7 @@ namespace Tgstation.Server.Host.System
/// </summary>
/// <param name="outputFile">The full path to the output file.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task CreateDump(string outputFile, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask CreateDump(string outputFile, CancellationToken cancellationToken);
}
}
@@ -12,9 +12,8 @@ namespace Tgstation.Server.Host.System
/// Get the name of the user executing a given <paramref name="process"/>.
/// </summary>
/// <param name="process">The <see cref="global::System.Diagnostics.Process"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>The name of the user executing <paramref name="process"/>.</returns>
Task<string> GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken);
string GetExecutingUsername(global::System.Diagnostics.Process process);
/// <summary>
/// Suspend a given <paramref name="process"/>.
@@ -34,7 +33,7 @@ namespace Tgstation.Server.Host.System
/// <param name="process">The <see cref="Process"/> to dump.</param>
/// <param name="outputFile">The full path to the output file.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task CreateDump(global::System.Diagnostics.Process process, string outputFile, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask CreateDump(global::System.Diagnostics.Process process, string outputFile, CancellationToken cancellationToken);
}
}
@@ -60,11 +60,11 @@ namespace Tgstation.Server.Host.System
}
/// <inheritdoc />
public Task<string> GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
public string GetExecutingUsername(global::System.Diagnostics.Process process)
=> throw new NotSupportedException();
/// <inheritdoc />
public async Task CreateDump(global::System.Diagnostics.Process process, string outputFile, CancellationToken cancellationToken)
public async ValueTask CreateDump(global::System.Diagnostics.Process process, string outputFile, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(process);
ArgumentNullException.ThrowIfNull(outputFile);
+3 -3
View File
@@ -202,15 +202,15 @@ namespace Tgstation.Server.Host.System
}
/// <inheritdoc />
public async Task<string> GetExecutingUsername(CancellationToken cancellationToken)
public string GetExecutingUsername()
{
var result = await processFeatures.GetExecutingUsername(handle, cancellationToken);
var result = processFeatures.GetExecutingUsername(handle);
logger.LogTrace("PID {pid} Username: {username}", Id, result);
return result;
}
/// <inheritdoc />
public Task CreateDump(string outputFile, CancellationToken cancellationToken)
public ValueTask CreateDump(string outputFile, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(outputFile);
@@ -93,7 +93,7 @@ namespace Tgstation.Server.Host.System
}
/// <inheritdoc />
public Task<string> GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
public string GetExecutingUsername(global::System.Diagnostics.Process process)
{
string query = $"SELECT * FROM Win32_Process WHERE ProcessId = {process?.Id ?? throw new ArgumentNullException(nameof(process))}";
using var searcher = new ManagementObjectSearcher(query);
@@ -106,21 +106,21 @@ namespace Tgstation.Server.Host.System
?.ToString();
if (!Int32.TryParse(returnString, out var returnVal))
return Task.FromResult($"BAD RETURN PARSE: {returnString}");
return $"BAD RETURN PARSE: {returnString}";
if (returnVal == 0)
{
// return DOMAIN\user
string owner = argList.Last() + "\\" + argList.First();
return Task.FromResult(owner);
return owner;
}
}
return Task.FromResult("NO OWNER");
return "NO OWNER";
}
/// <inheritdoc />
public async Task CreateDump(global::System.Diagnostics.Process process, string outputFile, CancellationToken cancellationToken)
public async ValueTask CreateDump(global::System.Diagnostics.Process process, string outputFile, CancellationToken cancellationToken)
{
try
{
@@ -163,7 +163,7 @@ namespace Tgstation.Server.Host.Transfer
}
/// <inheritdoc />
public async Task<Tuple<Stream, ErrorMessageResponse>> RetrieveDownloadStream(FileTicketResponse ticket, CancellationToken cancellationToken)
public async ValueTask<Tuple<Stream, ErrorMessageResponse>> RetrieveDownloadStream(FileTicketResponse ticket, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(ticket);
@@ -217,7 +217,7 @@ namespace Tgstation.Server.Host.Transfer
}
/// <inheritdoc />
public async Task<ErrorMessageResponse> SetUploadStream(FileTicketResponse ticket, Stream stream, CancellationToken cancellationToken)
public async ValueTask<ErrorMessageResponse> SetUploadStream(FileTicketResponse ticket, Stream stream, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(ticket);
@@ -18,15 +18,15 @@ namespace Tgstation.Server.Host.Transfer
/// <param name="ticket">The <see cref="FileTicketResponse"/>.</param>
/// <param name="stream">The <see cref="Stream"/> with uploaded data.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns><see langword="null"/> if the upload completed successfully, <see cref="ErrorMessageResponse"/> otherwise.</returns>
Task<ErrorMessageResponse> SetUploadStream(FileTicketResponse ticket, Stream stream, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in <see langword="null"/> if the upload completed successfully, <see cref="ErrorMessageResponse"/> otherwise.</returns>
ValueTask<ErrorMessageResponse> SetUploadStream(FileTicketResponse ticket, Stream stream, CancellationToken cancellationToken);
/// <summary>
/// Gets the the <see cref="Stream"/> for a given <paramref name="ticket"/> associated with a pending download.
/// </summary>
/// <param name="ticket">The <see cref="FileTicketResponse"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Tuple{T1, T2}"/> containing either a <see cref="Stream"/> containing the data to download or an <see cref="ErrorMessageResponse"/> to return.</returns>
Task<Tuple<Stream, ErrorMessageResponse>> RetrieveDownloadStream(FileTicketResponse ticket, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in a <see cref="Tuple{T1, T2}"/> containing either a <see cref="Stream"/> containing the data to download or an <see cref="ErrorMessageResponse"/> to return.</returns>
ValueTask<Tuple<Stream, ErrorMessageResponse>> RetrieveDownloadStream(FileTicketResponse ticket, CancellationToken cancellationToken);
}
}
@@ -14,7 +14,7 @@ namespace Tgstation.Server.Host.Utils
/// <param name="basePort">The port to check first. Will not allocate a port lower than this.</param>
/// <param name="checkOne">If only <paramref name="basePort"/> should be checked and no others.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the first available port on success, <see langword="null"/> on failure.</returns>
Task<ushort?> GetAvailablePort(ushort basePort, bool checkOne, CancellationToken cancellationToken);
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the first available port on success, <see langword="null"/> on failure.</returns>
ValueTask<ushort?> GetAvailablePort(ushort basePort, bool checkOne, CancellationToken cancellationToken);
}
}
@@ -58,7 +58,7 @@ namespace Tgstation.Server.Host.Utils
}
/// <inheritdoc />
public async Task<ushort?> GetAvailablePort(ushort basePort, bool checkOne, CancellationToken cancellationToken)
public async ValueTask<ushort?> GetAvailablePort(ushort basePort, bool checkOne, CancellationToken cancellationToken)
{
logger.LogTrace("Port allocation >= {basePort} requested...", basePort);
@@ -17,7 +17,7 @@ namespace Tgstation.Server.Host.Console.Tests
{
var mockServer = new Mock<IWatchdog>();
var args = Array.Empty<string>();
mockServer.Setup(x => x.RunAsync(false, args, It.IsAny<CancellationToken>())).Returns(Task.FromResult(true)).Verifiable();
mockServer.Setup(x => x.RunAsync(false, args, It.IsAny<CancellationToken>())).Returns(ValueTask.FromResult(true)).Verifiable();
var mockServerFactory = new Mock<IWatchdogFactory>();
mockServerFactory.Setup(x => x.CreateWatchdog(It.IsNotNull<ISignalChecker>(), It.IsNotNull<ILoggerFactory>())).Returns(mockServer.Object).Verifiable();
Program.WatchdogFactory = mockServerFactory.Object;
@@ -35,7 +35,7 @@ namespace Tgstation.Server.Host.Service.Tests
var mockWatchdog = new Mock<IWatchdog>();
var args = Array.Empty<string>();
CancellationToken cancellationToken = default;
Task signalCheckerTask = null;
ValueTask? signalCheckerTask = null;
var childStarted = false;
ISignalChecker signalChecker = null;
@@ -47,7 +47,7 @@ namespace Tgstation.Server.Host.Service.Tests
childStarted = true;
return (123, Task.CompletedTask);
}, cancellationToken);
}).Returns(Task.FromResult(true)).Verifiable();
}).Returns(ValueTask.FromResult(true)).Verifiable();
var mockWatchdogFactory = new Mock<IWatchdogFactory>();
mockWatchdogFactory.Setup(x => x.CreateWatchdog(It.IsNotNull<ISignalChecker>(), It.IsNotNull<ILoggerFactory>()))
@@ -67,7 +67,7 @@ namespace Tgstation.Server.Host.Service.Tests
}
mockWatchdogFactory.VerifyAll();
Assert.IsTrue(signalCheckerTask.IsCompleted);
Assert.IsTrue(signalCheckerTask.Value.IsCompleted);
}
}
}
@@ -88,28 +88,28 @@ namespace Tgstation.Server.Host.IO.Tests
null,
tempPath2,
throttle,
default));
default).AsTask());
await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => ioManager.CopyDirectory(
null,
null,
tempPath1,
null,
throttle,
default));
default).AsTask());
await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => ioManager.CopyDirectory(
null,
null,
null,
null,
throttle,
default));
default).AsTask());
await Assert.ThrowsExceptionAsync<ArgumentOutOfRangeException>(() => ioManager.CopyDirectory(
null,
null,
tempPath1,
tempPath2,
-1,
default));
default).AsTask());
}
[TestMethod]
@@ -104,10 +104,10 @@ namespace Tgstation.Server.Host.Setup.Tests
return $"{paths[0]}/{paths[1]}";
}).Verifiable();
mockIOManager.Setup(x => x.FileExists(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(true)).Verifiable();
mockIOManager.Setup(x => x.ReadAllBytes(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(Encoding.UTF8.GetBytes("less profane"))).Verifiable();
mockIOManager.Setup(x => x.ReadAllBytes(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(ValueTask.FromResult(Encoding.UTF8.GetBytes("less profane"))).Verifiable();
mockIOManager
.Setup(x => x.WriteAllBytes(It.IsNotNull<string>(), It.IsNotNull<byte[]>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask)
.Returns(ValueTask.CompletedTask)
.Verifiable();
var mockSuccessCommand = new Mock<DbCommand>();
@@ -306,7 +306,7 @@ namespace Tgstation.Server.Host.Setup.Tests
await RunWizard();
//second run
mockIOManager.Setup(x => x.ReadAllBytes(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(Encoding.UTF8.GetBytes(String.Empty))).Verifiable();
mockIOManager.Setup(x => x.ReadAllBytes(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(ValueTask.FromResult(Encoding.UTF8.GetBytes(String.Empty))).Verifiable();
await RunWizard();
//third run
@@ -10,6 +10,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Tgstation.Server.Common.Extensions;
using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.IO;
@@ -206,7 +207,7 @@ namespace Tgstation.Server.Host.Swarm.Tests
await TestSimultaneousPrepareDifferentVersionsFails(false);
}
static async Task TestSimultaneousPrepareDifferentVersionsFails(bool prepControllerFirst)
static async ValueTask TestSimultaneousPrepareDifferentVersionsFails(bool prepControllerFirst)
{
await using var controller = GenNode();
await using var node1 = GenNode(controller);
@@ -219,7 +220,7 @@ namespace Tgstation.Server.Host.Swarm.Tests
Assert.AreEqual(SwarmRegistrationResult.Success, await controller.TryInit());
Assert.AreEqual(SwarmRegistrationResult.Success, await node1.TryInit());
Task<SwarmPrepareResult> controllerPrepareTask = null, nodePrepareTask;
ValueTask<SwarmPrepareResult> controllerPrepareTask = ValueTask.FromResult(SwarmPrepareResult.SuccessProviderNotRequired), nodePrepareTask;
if (prepControllerFirst)
controllerPrepareTask = controller.Service.PrepareUpdate(updateFileStreamProvider, new Version(4, 3, 2), default);
@@ -230,7 +231,7 @@ namespace Tgstation.Server.Host.Swarm.Tests
await Task.Yield();
await Task.WhenAll(controllerPrepareTask, nodePrepareTask);
await ValueTaskExtensions.WhenAll(controllerPrepareTask, nodePrepareTask);
Task<SwarmCommitResult> nodeCommitTask = null, controllerCommitTask = null;
@@ -248,13 +249,13 @@ namespace Tgstation.Server.Host.Swarm.Tests
if (controllerPrepped != SwarmPrepareResult.Failure)
{
Assert.AreEqual(SwarmPrepareResult.SuccessHoldProviderUntilCommit, controllerPrepped);
controllerCommitTask = controller.Service.CommitUpdate(default);
controllerCommitTask = controller.Service.CommitUpdate(default).AsTask();
}
if (nodePrepped != SwarmPrepareResult.Failure)
{
Assert.AreEqual(SwarmPrepareResult.SuccessHoldProviderUntilCommit, nodePrepped);
nodeCommitTask = node1.Service.CommitUpdate(default);
nodeCommitTask = node1.Service.CommitUpdate(default).AsTask();
}
await Task.Yield();
@@ -237,7 +237,7 @@ namespace Tgstation.Server.Host.Swarm.Tests
throw new TaskCanceledException();
}).Verifiable();
Task<SwarmRegistrationResult> Invoke() => Service.Initialize(default);
Task<SwarmRegistrationResult> Invoke() => Service.Initialize(default).AsTask();
SwarmRegistrationResult? result;
if (cancel)
@@ -3,7 +3,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Tgstation.Server.Host.IO;
@@ -26,12 +25,12 @@ namespace Tgstation.Server.Host.System.Tests
}
[TestMethod]
public async Task TestGetUsername()
public void TestGetUsername()
{
if (!new PlatformIdentifier().IsWindows)
Assert.Inconclusive("This test is buggy on linux and not required");
var username = await features.GetExecutingUsername(global::System.Diagnostics.Process.GetCurrentProcess(), default);
var username = features.GetExecutingUsername(global::System.Diagnostics.Process.GetCurrentProcess());
Assert.IsTrue(username.Contains(Environment.UserName), $"Exepcted a string containing \"{Environment.UserName}\", got \"{username}\"");
}
}
@@ -11,6 +11,7 @@ using Tgstation.Server.Api.Models;
using Tgstation.Server.Api.Models.Request;
using Tgstation.Server.Client;
using Tgstation.Server.Client.Components;
using Tgstation.Server.Common.Extensions;
using Tgstation.Server.Host.IO;
namespace Tgstation.Server.Tests.Live.Instance
@@ -92,11 +93,11 @@ namespace Tgstation.Server.Tests.Live.Instance
await configurationClient.CreateDirectory(staticDir, cancellationToken);
}
public Task SetupDMApiTests(CancellationToken cancellationToken)
public ValueTask SetupDMApiTests(CancellationToken cancellationToken)
{
// just use an I/O manager here
var ioManager = new DefaultIOManager();
return Task.WhenAll(
return ValueTaskExtensions.WhenAll(
ioManager.CopyDirectory(
Enumerable.Empty<string>(),
null,
@@ -176,7 +177,7 @@ namespace Tgstation.Server.Tests.Live.Instance
public Task RunPreWatchdog(CancellationToken cancellationToken) => Task.WhenAll(
SequencedApiTests(cancellationToken),
SetupDMApiTests(cancellationToken),
SetupDMApiTests(cancellationToken).AsTask(),
TestPregeneratedFilesExist(cancellationToken));
}
}
@@ -43,7 +43,7 @@ namespace Tgstation.Server.Tests.Live.Instance
this.accessIdentifier = accessIdentifier;
}
public async Task<BridgeResponse> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken)
public async ValueTask<BridgeResponse> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken)
{
try
{