Skip to content

Commit 62dd00a

Browse files
committed
fix: Refactor LongDelaySafe method to use Task directly and update tests
1 parent a816efb commit 62dd00a

5 files changed

Lines changed: 26 additions & 20 deletions

File tree

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<EnableNETAnalyzers>true</EnableNETAnalyzers>
66
<AnalysisLevel>latest</AnalysisLevel>
77
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
8+
<LangVersion>14.0</LangVersion>
89

910
<NoWarn>$(NoWarn);NCRONJOB_OBSERVER</NoWarn>
1011
</PropertyGroup>

src/NCronJob/NCronJob.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77
<RootNamespace>NCronJob</RootNamespace>
8-
<LangVersion>preview</LangVersion>
98
</PropertyGroup>
109

1110
<PropertyGroup Label="NuGet">

src/NCronJob/Scheduler/JobWorker.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ private async Task WaitForNextExecution(DateTimeOffset nextRunTime, Cancellation
167167
var delay = nextRunTime - utcNow;
168168
if (delay > TimeSpan.Zero)
169169
{
170-
await TaskExtensions.LongDelaySafe(delay, timeProvider, stopToken).ConfigureAwait(false);
170+
await Task.LongDelaySafe(delay, timeProvider, stopToken).ConfigureAwait(false);
171171
}
172172
}
173173

src/NCronJob/Scheduler/TaskExtensions.cs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,28 @@ namespace NCronJob;
55
/// </summary>
66
internal static class TaskExtensions
77
{
8-
/// <summary>
9-
/// Has the same semantics as <see cref="Task.Delay(TimeSpan, TimeProvider, CancellationToken)"/> but is safe to use for long delays.
10-
/// </summary>
11-
/// <param name="targetTimeSpan">The <see cref="TimeSpan" /> to wait before completing the returned task, or <see cref="Timeout.InfiniteTimeSpan" /> to wait indefinitely.</param>
12-
/// <param name="timeProvider">The <see cref="TimeProvider" /> with which to interpret <paramref name="targetTimeSpan" />.</param>
13-
/// <param name="token">A cancellation token to observe while waiting for the task to complete.</param>
14-
public static async Task LongDelaySafe(TimeSpan targetTimeSpan, TimeProvider timeProvider, CancellationToken token)
8+
extension(Task)
159
{
16-
ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(targetTimeSpan, TimeSpan.Zero);
17-
18-
var remainingTime = targetTimeSpan;
19-
while (remainingTime > TimeSpan.Zero)
10+
/// <summary>
11+
/// Has the same semantics as <see cref="Task.Delay(TimeSpan, TimeProvider, CancellationToken)"/> but is safe to use for long delays.
12+
/// </summary>
13+
/// <param name="targetTimeSpan">The <see cref="TimeSpan" /> to wait before completing the returned task, or <see cref="Timeout.InfiniteTimeSpan" /> to wait indefinitely.</param>
14+
/// <param name="timeProvider">The <see cref="TimeProvider" /> with which to interpret <paramref name="targetTimeSpan" />.</param>
15+
/// <param name="token">A cancellation token to observe while waiting for the task to complete.</param>
16+
public static async Task LongDelaySafe(
17+
TimeSpan targetTimeSpan,
18+
TimeProvider timeProvider,
19+
CancellationToken token)
2020
{
21-
var delay = TimeSpan.FromMilliseconds(Math.Min(remainingTime.TotalMilliseconds, uint.MaxValue - 1));
22-
await Task.Delay(delay, timeProvider, token).ConfigureAwait(ConfigureAwaitOptions.ForceYielding);
23-
remainingTime -= delay;
21+
ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(targetTimeSpan, TimeSpan.Zero);
22+
23+
var remainingTime = targetTimeSpan;
24+
while (remainingTime > TimeSpan.Zero)
25+
{
26+
var delay = TimeSpan.FromMilliseconds(Math.Min(remainingTime.TotalMilliseconds, uint.MaxValue - 1));
27+
await Task.Delay(delay, timeProvider, token).ConfigureAwait(ConfigureAwaitOptions.ForceYielding);
28+
remainingTime -= delay;
29+
}
2430
}
2531
}
2632
}

tests/NCronJob.Tests/TaskExtensionsTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ public async Task LongDelaySafe_WhenCalledWith100Days_ShouldDelay()
1313
var maxDelayTimeSpan = TimeSpan.FromMilliseconds(uint.MaxValue - 1);
1414
var timeProvider = new FakeTimeProvider();
1515
var targetTimeSpan = TimeSpan.FromDays(100);
16-
var token = new CancellationToken();
16+
var token = CancellationToken.None;
1717

1818
// Act
1919
var act = () =>
2020
{
21-
var delayTask = TaskExtensions.LongDelaySafe(targetTimeSpan, timeProvider, token);
21+
var delayTask = Task.LongDelaySafe(targetTimeSpan, timeProvider, token);
2222
timeProvider.Advance(maxDelayTimeSpan);
2323
timeProvider.Advance(maxDelayTimeSpan);
2424
timeProvider.Advance(targetTimeSpan - (maxDelayTimeSpan + maxDelayTimeSpan));
@@ -36,10 +36,10 @@ public void LongDelaySafeThrowsWhenTimeSpanZeroIsPassedIn()
3636
// Arrange
3737
var timeProvider = new FakeTimeProvider();
3838
var targetTimeSpan = TimeSpan.Zero;
39-
var token = new CancellationToken();
39+
var token = CancellationToken.None;
4040

4141
// Act
42-
var act = () => TaskExtensions.LongDelaySafe(targetTimeSpan, timeProvider, token);
42+
var act = () => Task.LongDelaySafe(targetTimeSpan, timeProvider, token);
4343

4444
// Assert
4545
act.ShouldThrow<ArgumentOutOfRangeException>();

0 commit comments

Comments
 (0)