@@ -31,7 +31,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
3131 var idleTimeoutTicks = options . Value . IdleTimeout . Ticks ;
3232 var maxIdleSessionCount = options . Value . MaxIdleSessionCount ;
3333
34- var idleSessions = new SortedSet < ( string SessionId , long Timestamp ) > ( SessionTimestampComparer . Instance ) ;
34+ // The default ValueTuple Comparer will check the first item then the second which preserves both order and uniqueness.
35+ var idleSessions = new SortedSet < ( long Timestamp , string SessionId ) > ( ) ;
3536
3637 while ( ! stoppingToken . IsCancellationRequested && await timer . WaitForNextTickAsync ( stoppingToken ) )
3738 {
@@ -55,7 +56,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
5556 continue ;
5657 }
5758
58- idleSessions . Add ( ( session . Id , session . LastActivityTicks ) ) ;
59+ idleSessions . Add ( ( session . LastActivityTicks , session . Id ) ) ;
5960
6061 // Emit critical log at most once every 5 seconds the idle count it exceeded,
6162 // since the IdleTimeout will no longer be respected.
@@ -68,7 +69,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
6869 if ( idleSessions . Count > maxIdleSessionCount )
6970 {
7071 var sessionsToPrune = idleSessions . ToArray ( ) [ ..^ maxIdleSessionCount ] ;
71- foreach ( var ( id , _ ) in sessionsToPrune )
72+ foreach ( var ( _ , id ) in sessionsToPrune )
7273 {
7374 RemoveAndCloseSession ( id ) ;
7475 }
@@ -133,19 +134,6 @@ private async Task DisposeSessionAsync(HttpMcpSession<StreamableHttpServerTransp
133134 }
134135 }
135136
136- private sealed class SessionTimestampComparer : IComparer < ( string SessionId , long Timestamp ) >
137- {
138- public static SessionTimestampComparer Instance { get ; } = new ( ) ;
139-
140- public int Compare ( ( string SessionId , long Timestamp ) x , ( string SessionId , long Timestamp ) y ) =>
141- x . Timestamp . CompareTo ( y . Timestamp ) switch
142- {
143- // Use a SessionId comparison as tiebreaker to ensure uniqueness in the SortedSet.
144- 0 => string . CompareOrdinal ( x . SessionId , y . SessionId ) ,
145- var timestampComparison => timestampComparison ,
146- } ;
147- }
148-
149137 [ LoggerMessage ( Level = LogLevel . Information , Message = "Closing idle session {sessionId}." ) ]
150138 private partial void LogSessionIdle ( string sessionId ) ;
151139
0 commit comments