@@ -37,6 +37,76 @@ public CloseInactiveSessionsJobTests(ITestOutputHelper output) : base(output) {
3737 CreateDataAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
3838 }
3939
40+ [ Fact ]
41+ public async Task CloseDuplicateIdentitySessions ( ) {
42+ const string userId = "blake@exceptionless.io" ;
43+ var event1 = GenerateEvent ( SystemClock . OffsetNow . SubtractMinutes ( 5 ) , userId ) ;
44+ var event2 = GenerateEvent ( SystemClock . OffsetNow . SubtractMinutes ( 5 ) , userId , sessionId : "123456789" ) ;
45+
46+ var contexts = await _pipeline . RunAsync ( new [ ] { event1 , event2 } ) ;
47+ Assert . True ( contexts . All ( c => ! c . HasError ) ) ;
48+ Assert . True ( contexts . All ( c => ! c . IsCancelled ) ) ;
49+ Assert . True ( contexts . All ( c => c . IsProcessed ) ) ;
50+
51+ await _configuration . Client . RefreshAsync ( ) ;
52+ var events = await _eventRepository . GetAllAsync ( ) ;
53+ Assert . Equal ( 4 , events . Total ) ;
54+ Assert . Equal ( 2 , events . Documents . Where ( e => ! String . IsNullOrEmpty ( e . GetSessionId ( ) ) ) . Select ( e => e . GetSessionId ( ) ) . Distinct ( ) . Count ( ) ) ;
55+ var sessionStarts = events . Documents . Where ( e => e . IsSessionStart ( ) ) . ToList ( ) ;
56+ Assert . Equal ( 0 , sessionStarts . Sum ( e => e . Value ) ) ;
57+ Assert . False ( sessionStarts . Any ( e => e . HasSessionEndTime ( ) ) ) ;
58+
59+ var utcNow = SystemClock . UtcNow ;
60+ await _cache . SetAsync ( $ "Project:{ sessionStarts . First ( ) . ProjectId } :heartbeat:{ userId . ToSHA1 ( ) } ", utcNow . SubtractMinutes ( 1 ) ) ;
61+
62+ _job . DefaultInactivePeriod = TimeSpan . FromMinutes ( 3 ) ;
63+ Assert . Equal ( JobResult . Success , await _job . RunAsync ( ) ) ;
64+ await _configuration . Client . RefreshAsync ( ) ;
65+ events = await _eventRepository . GetAllAsync ( ) ;
66+ Assert . Equal ( 4 , events . Total ) ;
67+
68+ sessionStarts = events . Documents . Where ( e => e . IsSessionStart ( ) ) . ToList ( ) ;
69+ Assert . Equal ( 2 , sessionStarts . Count ) ;
70+ Assert . Equal ( 1 , sessionStarts . Count ( e => ! e . HasSessionEndTime ( ) ) ) ;
71+ Assert . Equal ( 1 , sessionStarts . Count ( e => e . HasSessionEndTime ( ) ) ) ;
72+ }
73+
74+ [ Fact ]
75+ public async Task WillNotCloseDuplicateIdentitySessionsWithSessionIdHeartbeat ( ) {
76+ const string userId = "blake@exceptionless.io" ;
77+ const string sessionId = "123456789" ;
78+ var event1 = GenerateEvent ( SystemClock . OffsetNow . SubtractMinutes ( 5 ) , userId ) ;
79+ var event2 = GenerateEvent ( SystemClock . OffsetNow . SubtractMinutes ( 5 ) , userId , sessionId : sessionId ) ;
80+
81+ var contexts = await _pipeline . RunAsync ( new [ ] { event1 , event2 } ) ;
82+ Assert . True ( contexts . All ( c => ! c . HasError ) ) ;
83+ Assert . True ( contexts . All ( c => ! c . IsCancelled ) ) ;
84+ Assert . True ( contexts . All ( c => c . IsProcessed ) ) ;
85+
86+ await _configuration . Client . RefreshAsync ( ) ;
87+ var events = await _eventRepository . GetAllAsync ( ) ;
88+ Assert . Equal ( 4 , events . Total ) ;
89+ Assert . Equal ( 2 , events . Documents . Where ( e => ! String . IsNullOrEmpty ( e . GetSessionId ( ) ) ) . Select ( e => e . GetSessionId ( ) ) . Distinct ( ) . Count ( ) ) ;
90+ var sessionStarts = events . Documents . Where ( e => e . IsSessionStart ( ) ) . ToList ( ) ;
91+ Assert . Equal ( 0 , sessionStarts . Sum ( e => e . Value ) ) ;
92+ Assert . False ( sessionStarts . Any ( e => e . HasSessionEndTime ( ) ) ) ;
93+
94+ var utcNow = SystemClock . UtcNow ;
95+ await _cache . SetAsync ( $ "Project:{ sessionStarts . First ( ) . ProjectId } :heartbeat:{ userId . ToSHA1 ( ) } ", utcNow . SubtractMinutes ( 1 ) ) ;
96+ await _cache . SetAsync ( $ "Project:{ sessionStarts . First ( ) . ProjectId } :heartbeat:{ sessionId . ToSHA1 ( ) } ", utcNow . SubtractMinutes ( 1 ) ) ;
97+
98+ _job . DefaultInactivePeriod = TimeSpan . FromMinutes ( 3 ) ;
99+ Assert . Equal ( JobResult . Success , await _job . RunAsync ( ) ) ;
100+ await _configuration . Client . RefreshAsync ( ) ;
101+ events = await _eventRepository . GetAllAsync ( ) ;
102+ Assert . Equal ( 4 , events . Total ) ;
103+
104+ sessionStarts = events . Documents . Where ( e => e . IsSessionStart ( ) ) . ToList ( ) ;
105+ Assert . Equal ( 2 , sessionStarts . Count ) ;
106+ Assert . Equal ( 2 , sessionStarts . Count ( e => ! e . HasSessionEndTime ( ) ) ) ;
107+ Assert . Equal ( 0 , sessionStarts . Count ( e => e . HasSessionEndTime ( ) ) ) ;
108+ }
109+
40110 [ Theory ]
41111 [ InlineData ( 1 , true , null , false ) ]
42112 [ InlineData ( 1 , true , 70 , false ) ]
0 commit comments