diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs
index 0eedc7c949..2aa9916bf7 100644
--- a/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs
@@ -710,7 +710,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
Task.WhenAll(
disconnectTask,
listenTask ?? Task.CompletedTask),
- AsyncDelayer.Delay(TimeSpan.FromSeconds(5), cancellationToken));
+ AsyncDelayer.Delay(TimeSpan.FromSeconds(5), cancellationToken).AsTask());
}
///
diff --git a/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstallation.cs b/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstallation.cs
index ed5ee75a56..e7fbd9baa6 100644
--- a/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstallation.cs
+++ b/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstallation.cs
@@ -135,7 +135,7 @@ namespace Tgstation.Server.Host.Components.Engine
const int MaximumTerminationSeconds = 5;
logger.LogTrace("Attempting Robust.Server graceful exit (Timeout: {seconds}s)...", MaximumTerminationSeconds);
- var timeout = asyncDelayer.Delay(TimeSpan.FromSeconds(MaximumTerminationSeconds), cancellationToken);
+ var timeout = asyncDelayer.Delay(TimeSpan.FromSeconds(MaximumTerminationSeconds), cancellationToken).AsTask();
var lifetime = process.Lifetime;
if (lifetime.IsCompleted)
logger.LogTrace("Robust.Server already exited");
diff --git a/src/Tgstation.Server.Host/Components/Instance.cs b/src/Tgstation.Server.Host/Components/Instance.cs
index d178eb94e0..b45b33a6cf 100644
--- a/src/Tgstation.Server.Host/Components/Instance.cs
+++ b/src/Tgstation.Server.Host/Components/Instance.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -522,30 +521,6 @@ namespace Tgstation.Server.Host.Components
logger.LogInformation("Next auto-update will occur at {time}", DateTimeOffset.UtcNow + delay);
- // https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.delay?view=net-8.0#system-threading-tasks-task-delay(system-timespan)
- const uint DelayMinutesLimit = UInt32.MaxValue - 1;
- Debug.Assert(DelayMinutesLimit == 4294967294, "Delay limit assertion failure!");
-
- var maxDelayIterations = 0UL;
- if (delay.TotalMilliseconds >= UInt32.MaxValue)
- {
- maxDelayIterations = (ulong)Math.Floor(delay.TotalMilliseconds / DelayMinutesLimit);
- logger.LogDebug("Breaking interval into {iterationCount} iterations", maxDelayIterations + 1);
- delay = TimeSpan.FromMilliseconds(delay.TotalMilliseconds - (maxDelayIterations * DelayMinutesLimit));
- }
-
- if (maxDelayIterations > 0)
- {
- var longDelayTimeSpan = TimeSpan.FromMilliseconds(DelayMinutesLimit);
- for (var i = 0UL; i < maxDelayIterations; ++i)
- {
- logger.LogTrace("Long delay #{iteration}...", i + 1);
- await asyncDelayer.Delay(longDelayTimeSpan, cancellationToken);
- }
-
- logger.LogTrace("Final delay iteration #{iteration}...", maxDelayIterations + 1);
- }
-
await asyncDelayer.Delay(delay, cancellationToken);
logger.LogInformation("Beginning auto update...");
await eventConsumer.HandleEvent(EventType.InstanceAutoUpdateStart, Enumerable.Empty(), true, cancellationToken);
diff --git a/src/Tgstation.Server.Host/Components/InstanceManager.cs b/src/Tgstation.Server.Host/Components/InstanceManager.cs
index 5f6a101260..12ebb1300e 100644
--- a/src/Tgstation.Server.Host/Components/InstanceManager.cs
+++ b/src/Tgstation.Server.Host/Components/InstanceManager.cs
@@ -541,7 +541,7 @@ namespace Tgstation.Server.Host.Components
loggedDelay = true;
}
- delayTask = asyncDelayer.Delay(TimeSpan.FromMilliseconds(100), cancellationToken);
+ delayTask = asyncDelayer.Delay(TimeSpan.FromMilliseconds(100), cancellationToken).AsTask();
}
await delayTask;
diff --git a/src/Tgstation.Server.Host/Components/Session/SessionController.cs b/src/Tgstation.Server.Host/Components/Session/SessionController.cs
index 77a25fd979..53f8086f07 100644
--- a/src/Tgstation.Server.Host/Components/Session/SessionController.cs
+++ b/src/Tgstation.Server.Host/Components/Session/SessionController.cs
@@ -547,7 +547,8 @@ namespace Tgstation.Server.Host.Components.Session
toAwait,
asyncDelayer.Delay(
TimeSpan.FromSeconds(startupTimeout.Value),
- CancellationToken.None)); // DCT: None available, task will clean up after delay
+ CancellationToken.None)
+ .AsTask()); // DCT: None available, task will clean up after delay
Logger.LogTrace(
"Waiting for LaunchResult based on {launchResultCompletionCause}{possibleTimeout}...",
@@ -611,7 +612,7 @@ namespace Tgstation.Server.Host.Components.Session
const int GracePeriodSeconds = 30;
Logger.LogDebug("Server will terminated in {gracePeriodSeconds}s if it does not exit...", GracePeriodSeconds);
- var delayTask = asyncDelayer.Delay(TimeSpan.FromSeconds(GracePeriodSeconds), CancellationToken.None); // DCT: None available
+ var delayTask = asyncDelayer.Delay(TimeSpan.FromSeconds(GracePeriodSeconds), CancellationToken.None).AsTask(); // DCT: None available
await Task.WhenAny(process.Lifetime, delayTask);
if (!process.Lifetime.IsCompleted)
diff --git a/src/Tgstation.Server.Host/Components/Watchdog/AdvancedWatchdog.cs b/src/Tgstation.Server.Host/Components/Watchdog/AdvancedWatchdog.cs
index b58db53601..68e44eee5d 100644
--- a/src/Tgstation.Server.Host/Components/Watchdog/AdvancedWatchdog.cs
+++ b/src/Tgstation.Server.Host/Components/Watchdog/AdvancedWatchdog.cs
@@ -185,7 +185,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
lingeringDeploymentExpirySeconds);
// DCT: A cancel firing here can result in us leaving a dmbprovider undisposed, localDeploymentCleanupGate will always fire in that case
- var timeout = AsyncDelayer.Delay(TimeSpan.FromSeconds(lingeringDeploymentExpirySeconds), CancellationToken.None);
+ var timeout = AsyncDelayer.Delay(TimeSpan.FromSeconds(lingeringDeploymentExpirySeconds), CancellationToken.None).AsTask();
var completedTask = await Task.WhenAny(
localDeploymentCleanupGate.Task,
diff --git a/src/Tgstation.Server.Host/Security/SessionInvalidationTracker.cs b/src/Tgstation.Server.Host/Security/SessionInvalidationTracker.cs
index 6f302a3532..00880fc1b3 100644
--- a/src/Tgstation.Server.Host/Security/SessionInvalidationTracker.cs
+++ b/src/Tgstation.Server.Host/Security/SessionInvalidationTracker.cs
@@ -86,7 +86,7 @@ namespace Tgstation.Server.Host.Security
var timeTillSessionExpiry = authenticationContext.SessionExpiry - DateTimeOffset.UtcNow;
if (timeTillSessionExpiry > TimeSpan.Zero)
{
- var delayTask = asyncDelayer.Delay(timeTillSessionExpiry, applicationLifetime.ApplicationStopping);
+ var delayTask = asyncDelayer.Delay(timeTillSessionExpiry, applicationLifetime.ApplicationStopping).AsTask();
await Task.WhenAny(delayTask, otherCancellationReason);
diff --git a/src/Tgstation.Server.Host/Swarm/SwarmService.cs b/src/Tgstation.Server.Host/Swarm/SwarmService.cs
index b6a0e51df6..dcb3737ff9 100644
--- a/src/Tgstation.Server.Host/Swarm/SwarmService.cs
+++ b/src/Tgstation.Server.Host/Swarm/SwarmService.cs
@@ -298,7 +298,7 @@ namespace Tgstation.Server.Host.Swarm
var timeoutTask = swarmController
? asyncDelayer.Delay(
TimeSpan.FromMinutes(SwarmConstants.UpdateCommitTimeoutMinutes),
- cancellationToken)
+ cancellationToken).AsTask()
: Extensions.TaskExtensions.InfiniteTask.WaitAsync(cancellationToken);
var commitTask = Task.WhenAny(localUpdateOperation.CommitGate, timeoutTask);
@@ -1512,7 +1512,8 @@ namespace Tgstation.Server.Host.Swarm
var delayTask = asyncDelayer.Delay(
delay,
- cancellationToken);
+ cancellationToken)
+ .AsTask();
var awakeningTask = Task.WhenAny(
delayTask,
diff --git a/src/Tgstation.Server.Host/Utils/AsyncDelayer.cs b/src/Tgstation.Server.Host/Utils/AsyncDelayer.cs
index 79ffce1838..c8adc33436 100644
--- a/src/Tgstation.Server.Host/Utils/AsyncDelayer.cs
+++ b/src/Tgstation.Server.Host/Utils/AsyncDelayer.cs
@@ -1,13 +1,57 @@
using System;
+using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+
namespace Tgstation.Server.Host.Utils
{
///
sealed class AsyncDelayer : IAsyncDelayer
{
+ ///
+ /// The for the .
+ ///
+ readonly ILogger logger;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value of .
+ public AsyncDelayer(ILogger logger)
+ {
+ this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ }
+
///
- public Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken) => Task.Delay(timeSpan, cancellationToken);
+ public async ValueTask Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
+ {
+ // https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.delay?view=net-8.0#system-threading-tasks-task-delay(system-timespan)
+ const uint DelayMinutesLimit = UInt32.MaxValue - 1;
+ Debug.Assert(DelayMinutesLimit == 4294967294, "Delay limit assertion failure!");
+
+ var maxDelayIterations = 0UL;
+ if (timeSpan.TotalMilliseconds >= UInt32.MaxValue)
+ {
+ maxDelayIterations = (ulong)Math.Floor(timeSpan.TotalMilliseconds / DelayMinutesLimit);
+ logger.LogDebug("Breaking interval into {iterationCount} iterations", maxDelayIterations + 1);
+ timeSpan = TimeSpan.FromMilliseconds(timeSpan.TotalMilliseconds - (maxDelayIterations * DelayMinutesLimit));
+ }
+
+ if (maxDelayIterations > 0)
+ {
+ var longDelayTimeSpan = TimeSpan.FromMilliseconds(DelayMinutesLimit);
+ for (var i = 0UL; i < maxDelayIterations; ++i)
+ {
+ logger.LogTrace("Long delay #{iteration}...", i + 1);
+ await Task.Delay(longDelayTimeSpan, cancellationToken);
+ }
+
+ logger.LogTrace("Final delay iteration #{iteration}...", maxDelayIterations + 1);
+ }
+
+ await Task.Delay(timeSpan, cancellationToken);
+ }
}
}
diff --git a/src/Tgstation.Server.Host/Utils/IAsyncDelayer.cs b/src/Tgstation.Server.Host/Utils/IAsyncDelayer.cs
index d47c5cbc62..e60799fc29 100644
--- a/src/Tgstation.Server.Host/Utils/IAsyncDelayer.cs
+++ b/src/Tgstation.Server.Host/Utils/IAsyncDelayer.cs
@@ -14,7 +14,7 @@ namespace Tgstation.Server.Host.Utils
///
/// The that must elapse.
/// The for the operation.
- /// A representing the running operation.
- Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken);
+ /// A representing the running operation.
+ ValueTask Delay(TimeSpan timeSpan, CancellationToken cancellationToken);
}
}
diff --git a/tests/Tgstation.Server.Host.Tests.Signals/Program.cs b/tests/Tgstation.Server.Host.Tests.Signals/Program.cs
index 92a733e59d..bcb5aa6699 100644
--- a/tests/Tgstation.Server.Host.Tests.Signals/Program.cs
+++ b/tests/Tgstation.Server.Host.Tests.Signals/Program.cs
@@ -25,7 +25,7 @@ namespace Tgstation.Server.Host.Tests.Signals
.Returns(ValueTask.CompletedTask);
var mockAsyncDelayer = new Mock();
- mockAsyncDelayer.Setup(x => x.Delay(It.IsAny(), It.IsAny())).Returns(Task.CompletedTask);
+ mockAsyncDelayer.Setup(x => x.Delay(It.IsAny(), It.IsAny())).Returns(ValueTask.CompletedTask);
using var signalHandler = new PosixSignalHandler(mockServerControl.Object, mockAsyncDelayer.Object, Mock.Of>());
Assert.IsFalse(tcs.Task.IsCompleted);
diff --git a/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestIrcProvider.cs b/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestIrcProvider.cs
index bc1ecbf0a4..834be3bcad 100644
--- a/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestIrcProvider.cs
+++ b/tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestIrcProvider.cs
@@ -89,7 +89,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers.Tests
Instance = new Models.Instance(),
};
- await using var provider = new IrcProvider(mockJobManager, new AsyncDelayer(), loggerFactory.CreateLogger(), Mock.Of(), chatBot, new FileLoggingConfiguration());
+ await using var provider = new IrcProvider(mockJobManager, new AsyncDelayer(loggerFactory.CreateLogger()), loggerFactory.CreateLogger(), Mock.Of(), chatBot, new FileLoggingConfiguration());
Assert.IsFalse(provider.Connected);
await InvokeConnect(provider);
Assert.IsTrue(provider.Connected);
diff --git a/tests/Tgstation.Server.Host.Tests/Setup/TestSetupWizard.cs b/tests/Tgstation.Server.Host.Tests/Setup/TestSetupWizard.cs
index 5598673dc2..fba28a4d6e 100644
--- a/tests/Tgstation.Server.Host.Tests/Setup/TestSetupWizard.cs
+++ b/tests/Tgstation.Server.Host.Tests/Setup/TestSetupWizard.cs
@@ -91,7 +91,7 @@ namespace Tgstation.Server.Host.Setup.Tests
mockInternalConfigurationOptions.Object);
mockPlatformIdentifier.SetupGet(x => x.IsWindows).Returns(true).Verifiable();
- mockAsyncDelayer.Setup(x => x.Delay(It.IsAny(), It.IsAny())).Returns(Task.CompletedTask).Verifiable();
+ mockAsyncDelayer.Setup(x => x.Delay(It.IsAny(), It.IsAny())).Returns(ValueTask.CompletedTask).Verifiable();
await RunWizard();
diff --git a/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs b/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs
index c5f22614b8..9c130af80e 100644
--- a/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs
+++ b/tests/Tgstation.Server.Host.Tests/Swarm/TestableSwarmNode.cs
@@ -129,7 +129,7 @@ namespace Tgstation.Server.Host.Swarm.Tests
mockAsyncDelayer.Setup(
x => x.Delay(It.IsAny(), It.IsAny()))
.Returns(
- (delay, ct) => Task.Delay(TimeSpan.FromMilliseconds(100), ct));
+ async (delay, ct) => await Task.Delay(TimeSpan.FromMilliseconds(100), ct));
var mockServerUpdater = new Mock();
@@ -152,7 +152,7 @@ namespace Tgstation.Server.Host.Swarm.Tests
new CryptographySuite(
Mock.Of>()),
Mock.Of(),
- new AsyncDelayer(), // use a real one here because otherwise tickets expire too fast
+ new AsyncDelayer(Mock.Of>()), // use a real one here because otherwise tickets expire too fast
CreateLoggerFactoryForLogger(loggerFactory.CreateLogger($"FileTransferService-{swarmConfiguration.Identifier}"), out var mockLoggerFactory).CreateLogger());
RpcMapper = new SwarmRpcMapper(
diff --git a/tests/Tgstation.Server.Host.Tests/Utils/TestAsyncDelayer.cs b/tests/Tgstation.Server.Host.Tests/Utils/TestAsyncDelayer.cs
index fcad8785c5..991a03ceb3 100644
--- a/tests/Tgstation.Server.Host.Tests/Utils/TestAsyncDelayer.cs
+++ b/tests/Tgstation.Server.Host.Tests/Utils/TestAsyncDelayer.cs
@@ -2,8 +2,11 @@
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+
namespace Tgstation.Server.Host.Utils.Tests
{
[TestClass]
@@ -12,7 +15,7 @@ namespace Tgstation.Server.Host.Utils.Tests
[TestMethod]
public async Task TestDelay()
{
- var delayer = new AsyncDelayer();
+ var delayer = new AsyncDelayer(Mock.Of>());
var startDelay = delayer.Delay(TimeSpan.FromSeconds(1), CancellationToken.None);
var checkDelay = Task.Delay(TimeSpan.FromSeconds(1) - TimeSpan.FromMilliseconds(100), CancellationToken.None);
await startDelay;
@@ -22,10 +25,10 @@ namespace Tgstation.Server.Host.Utils.Tests
[TestMethod]
public async Task TestCancel()
{
- var delayer = new AsyncDelayer();
+ var delayer = new AsyncDelayer(Mock.Of>());
using var cts = new CancellationTokenSource();
cts.Cancel();
- await Assert.ThrowsExceptionAsync(() => delayer.Delay(TimeSpan.FromSeconds(1), cts.Token));
+ await Assert.ThrowsExceptionAsync(() => delayer.Delay(TimeSpan.FromSeconds(1), cts.Token).AsTask());
}
}
}
diff --git a/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs b/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs
index 872e59e6e6..b82cf58226 100644
--- a/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs
+++ b/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs
@@ -51,7 +51,7 @@ namespace Tgstation.Server.Tests.Live
// at time of writing, this is used exclusively for the reconnection interval which works in minutes
// shorten it to 3s
var mock = new Mock();
- mock.Setup(x => x.Delay(It.IsAny(), It.IsAny())).Returns((delay, cancellationToken) => Task.Delay(TimeSpan.FromSeconds(3), cancellationToken));
+ mock.Setup(x => x.Delay(It.IsAny(), It.IsAny())).Returns(async (delay, cancellationToken) => await Task.Delay(TimeSpan.FromSeconds(3), cancellationToken));
return mock.Object;
}
diff --git a/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs b/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs
index 16d3ac63fa..aff9e45867 100644
--- a/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs
+++ b/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs
@@ -309,7 +309,7 @@ namespace Tgstation.Server.Tests.Live.Instance
? await session.TopicSendSemaphore.Lock(cancellationToken)
: null)
return await topicClient.SendWithOptionalPriority(
- new AsyncDelayer(),
+ new AsyncDelayer(loggerFactory.CreateLogger()),
loggerFactory.CreateLogger(),
queryString,
topicPort,