11using System ;
2+ using System . Diagnostics ;
23using System . Threading . Tasks ;
34using Xunit ;
45
@@ -7,6 +8,17 @@ namespace StackExchange.Redis.Tests;
78[ RunPerProtocol ]
89public class KeyIdleTests ( ITestOutputHelper output , SharedConnectionFixture fixture ) : TestBase ( output , fixture )
910{
11+ // Target the standalone secure server (6381) rather than the default primary (6379).
12+ // OBJECT IDLETIME is reset via the value's LRU access clock, but Redis deliberately
13+ // suppresses that update while a save/AOF/replication-sync child is active (copy-on-write
14+ // avoidance). The default primary has a replica attached, and every replica full-sync forks
15+ // such a child; if one overlaps a touch/read in these tests, the idle time isn't reset and the
16+ // test flakes (observed on Windows CI). 6381 has no replica and no persistence, so no fork ever
17+ // suppresses the reset and the behaviour is deterministic. Overriding GetConfiguration here also
18+ // opts these tests out of the shared connection fixture, giving each a dedicated 6381 connection.
19+ protected override string GetConfiguration ( )
20+ => TestConfig . Current . SecureServerAndPort + ",password=" + TestConfig . Current . SecurePassword ;
21+
1022 [ Fact ]
1123 public async Task IdleTime ( )
1224 {
@@ -16,13 +28,14 @@ public async Task IdleTime()
1628 var db = conn . GetDatabase ( ) ;
1729 db . KeyDelete ( key , CommandFlags . FireAndForget ) ;
1830 db . StringSet ( key , "new value" , flags : CommandFlags . FireAndForget ) ;
31+ var timer = Stopwatch . StartNew ( ) ;
1932 await Task . Delay ( 2000 ) . ForAwait ( ) ;
2033 var idleTime = db . KeyIdleTime ( key ) ;
21- Assert . True ( idleTime > TimeSpan . Zero ) ;
34+ Assert . True ( idleTime > TimeSpan . Zero , $ "First check: { idleTime } should be > 0; elapsed: { timer . ElapsedMilliseconds } ms" ) ;
2235
2336 db . StringSet ( key , "new value2" , flags : CommandFlags . FireAndForget ) ;
2437 var idleTime2 = db . KeyIdleTime ( key ) ;
25- Assert . True ( idleTime2 < idleTime ) ;
38+ Assert . True ( idleTime2 < idleTime , $ "Second check: { idleTime2 } should be < { idleTime } ; elapsed: { timer . ElapsedMilliseconds } ms" ) ;
2639
2740 db . KeyDelete ( key ) ;
2841 var idleTime3 = db . KeyIdleTime ( key ) ;
@@ -38,12 +51,13 @@ public async Task TouchIdleTime()
3851 var db = conn . GetDatabase ( ) ;
3952 db . KeyDelete ( key , CommandFlags . FireAndForget ) ;
4053 db . StringSet ( key , "new value" , flags : CommandFlags . FireAndForget ) ;
54+ var timer = Stopwatch . StartNew ( ) ;
4155 await Task . Delay ( 2000 ) . ForAwait ( ) ;
4256 var idleTime = db . KeyIdleTime ( key ) ;
43- Assert . True ( idleTime > TimeSpan . Zero , "First check" ) ;
57+ Assert . True ( idleTime > TimeSpan . Zero , $ "First check: { idleTime } should be > 0; elapsed: { timer . ElapsedMilliseconds } ms ") ;
4458
45- Assert . True ( db . KeyTouch ( key ) , "Second check" ) ;
59+ Assert . True ( db . KeyTouch ( key ) , $ "Second check: should be True; elapsed: { timer . ElapsedMilliseconds } ms ") ;
4660 var idleTime1 = db . KeyIdleTime ( key ) ;
47- Assert . True ( idleTime1 < idleTime , "Third check" ) ;
61+ Assert . True ( idleTime1 < idleTime , $ "Third check: { idleTime1 } should be < { idleTime } ; elapsed: { timer . ElapsedMilliseconds } ms ") ;
4862 }
4963}
0 commit comments