Skip to content

Commit 9581f26

Browse files
committed
Release 5.22.0
1 parent aae77e4 commit 9581f26

File tree

5 files changed

+29
-18
lines changed

5 files changed

+29
-18
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Release Notes
22
====
33

4-
# 05-25-2025
4+
# 05-26-2025
55
<a href="https://www.nuget.org/packages/dotnext/5.22.0">DotNext 5.22.0</a>
66
* Added `!` operator overloading for the result and optional types: [261](https://github.com/dotnet/dotNext/pull/261)
77

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ All these things are implemented in 100% managed code on top of existing .NET AP
4444
* [NuGet Packages](https://www.nuget.org/profiles/rvsakno)
4545

4646
# What's new
47-
Release Date: 05-25-2025
47+
Release Date: 05-26-2025
4848

4949
<a href="https://www.nuget.org/packages/dotnext/5.22.0">DotNext 5.22.0</a>
5050
* Added `!` operator overloading for the result and optional types: [261](https://github.com/dotnet/dotNext/pull/261)

src/cluster/DotNext.Net.Cluster/Net/Cluster/Consensus/Raft/StateMachine/WriteAheadLog.Cleaner.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,18 @@ namespace DotNext.Net.Cluster.Consensus.Raft.StateMachine;
88
partial class WriteAheadLog
99
{
1010
[AsyncMethodBuilder(typeof(SpawningAsyncTaskMethodBuilder))]
11-
private async Task CleanUpAsync(CancellationToken token)
11+
private async Task CleanUpAsync(long upToIndex, CancellationToken token)
1212
{
13-
var nextIndex = stateMachine.Snapshot?.Index ?? 0L;
14-
1513
// After the barrier, we know that there is no competing reader that reads the old snapshot version
1614
lockManager.SetCallerInformation("Remove Pages");
1715
await lockManager.AcquireReadBarrierAsync(token).ConfigureAwait(false);
1816
try
1917
{
2018
// The barrier can suspend this async flow. However, the OS flushes the pages in the background
21-
RemoveSquashedPages(nextIndex);
19+
RemoveSquashedPages(upToIndex);
2220

2321
// ensure that garbage reclamation is not running concurrently with the snapshot installation process
24-
await stateMachine.ReclaimGarbageAsync(nextIndex, token).ConfigureAwait(false);
22+
await stateMachine.ReclaimGarbageAsync(upToIndex, token).ConfigureAwait(false);
2523
}
2624
catch (Exception e) when (e is not OperationCanceledException canceledEx || canceledEx.CancellationToken != token)
2725
{
@@ -45,6 +43,7 @@ private void RemoveSquashedPages(long toIndex)
4543
toPage = metadataPages.GetEndPageIndex(toIndex);
4644
removedBytes += metadataPages.Delete(toPage) * (long)MetadataPageManager.PageSize;
4745

48-
BytesDeletedMeter.Record(removedBytes, measurementTags);
46+
if (removedBytes > 0L)
47+
BytesDeletedMeter.Record(removedBytes, measurementTags);
4948
}
5049
}

src/cluster/DotNext.Net.Cluster/Net/Cluster/Consensus/Raft/StateMachine/WriteAheadLog.Flusher.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,21 @@ partial class WriteAheadLog
2828
[AsyncMethodBuilder(typeof(SpawningAsyncTaskMethodBuilder))]
2929
private async Task FlushAsync(long previousIndex, TimeSpan timeout, CancellationToken token)
3030
{
31-
var cleanupTask = Task.CompletedTask;
31+
// Weak ref tracks the task, but allows GC to collect associated state machine
32+
// as soon as possible. While the task is running, it cannot be collected, because it's referenced
33+
// by the async state machine.
34+
var cleanupTask = GCHandle.Alloc(Task.CompletedTask, GCHandleType.Weak);
3235
try
3336
{
34-
for (long newIndex; !token.IsCancellationRequested && backgroundTaskFailure is null; previousIndex = newIndex)
37+
for (long newIndex, oldSnapshot = SnapshotIndex, newSnapshot;
38+
!token.IsCancellationRequested && backgroundTaskFailure is null;
39+
previousIndex = long.Max(oldSnapshot = newSnapshot, newIndex) + 1L)
3540
{
36-
manualFlushQueue.SwitchValve();
41+
newSnapshot = SnapshotIndex;
3742
newIndex = LastCommittedEntryIndex;
43+
manualFlushQueue.SwitchValve();
3844

39-
if (newIndex > previousIndex)
45+
if (newIndex >= previousIndex)
4046
{
4147
// Ensure that the flusher is not running with the snapshot installation process concurrently
4248
lockManager.SetCallerInformation("Flush Pages");
@@ -55,18 +61,22 @@ private async Task FlushAsync(long previousIndex, TimeSpan timeout, Cancellation
5561
{
5662
lockManager.ReleaseReadLock();
5763
}
58-
59-
if (cleanupTask.IsCompleted)
60-
cleanupTask = CleanUpAsync(token);
6164
}
6265

66+
if (cleanupTask.Target is null or Task { IsCompletedSuccessfully: true } && oldSnapshot < newSnapshot)
67+
cleanupTask.Target = CleanUpAsync(newSnapshot, token);
68+
6369
manualFlushQueue.Drain();
6470
await flushTrigger.WaitAsync(timeout, token).ConfigureAwait(false);
6571
}
6672
}
67-
catch (OperationCanceledException e) when (e.CancellationToken == token)
73+
catch (OperationCanceledException e) when (e.CancellationToken == token && cleanupTask.Target is Task target)
74+
{
75+
await target.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
76+
}
77+
finally
6878
{
69-
await cleanupTask.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
79+
cleanupTask.Free();
7080
}
7181
}
7282

src/cluster/DotNext.Net.Cluster/Net/Cluster/Consensus/Raft/StateMachine/WriteAheadLog.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public WriteAheadLog(Options configuration, IStateMachine stateMachine)
9292
flushOnCommit = false;
9393
}
9494

95-
flusherTask = FlushAsync(commitIndex, interval, lifetimeTokenSource.Token);
95+
flusherTask = FlushAsync(commitIndex + 1L, interval, lifetimeTokenSource.Token);
9696
}
9797

9898
// applier
@@ -110,6 +110,8 @@ static void CreateIfNeeded(DirectoryInfo directory)
110110
}
111111
}
112112

113+
private long SnapshotIndex => stateMachine.Snapshot?.Index ?? 0L;
114+
113115
/// <summary>
114116
/// Initializes the log asynchronously.
115117
/// </summary>

0 commit comments

Comments
 (0)