@@ -1061,6 +1061,68 @@ public async Task RequestToActiveConnectionIdKillsPreviousConnectionLongPolling(
1061
1061
}
1062
1062
}
1063
1063
1064
+ [ Fact ]
1065
+ public async Task MultipleRequestsToActiveConnectionId409ForLongPolling ( )
1066
+ {
1067
+ using ( StartVerifiableLog ( ) )
1068
+ {
1069
+ var manager = CreateConnectionManager ( LoggerFactory ) ;
1070
+ var connection = manager . CreateConnection ( ) ;
1071
+ connection . TransportType = HttpTransportType . LongPolling ;
1072
+
1073
+ var dispatcher = new HttpConnectionDispatcher ( manager , LoggerFactory ) ;
1074
+
1075
+ var context1 = MakeRequest ( "/foo" , connection ) ;
1076
+ var context2 = MakeRequest ( "/foo" , connection ) ;
1077
+
1078
+ var services = new ServiceCollection ( ) ;
1079
+ services . AddSingleton < TestConnectionHandler > ( ) ;
1080
+ var builder = new ConnectionBuilder ( services . BuildServiceProvider ( ) ) ;
1081
+ builder . UseConnectionHandler < TestConnectionHandler > ( ) ;
1082
+ var app = builder . Build ( ) ;
1083
+ var options = new HttpConnectionDispatcherOptions ( ) ;
1084
+
1085
+ // Prime the polling. Expect any empty response showing the transport is initialized.
1086
+ var request1 = dispatcher . ExecuteAsync ( context1 , options , app ) ;
1087
+ Assert . True ( request1 . IsCompleted ) ;
1088
+
1089
+ // Manually control PreviousPollTask instead of using a real PreviousPollTask, because a real
1090
+ // PreviousPollTask might complete too early when the second request cancels it.
1091
+ var lastPollTcs = new TaskCompletionSource < object > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
1092
+ connection . PreviousPollTask = lastPollTcs . Task ;
1093
+
1094
+ request1 = dispatcher . ExecuteAsync ( context1 , options , app ) ;
1095
+ var request2 = dispatcher . ExecuteAsync ( context2 , options , app ) ;
1096
+
1097
+ Assert . False ( request1 . IsCompleted ) ;
1098
+ Assert . False ( request2 . IsCompleted ) ;
1099
+
1100
+ lastPollTcs . SetResult ( null ) ;
1101
+
1102
+ var completedTask = await Task . WhenAny ( request1 , request2 ) . OrTimeout ( ) ;
1103
+
1104
+ if ( completedTask == request1 )
1105
+ {
1106
+ Assert . Equal ( StatusCodes . Status409Conflict , context1 . Response . StatusCode ) ;
1107
+ //Assert.Equal(StatusCodes.Status200OK, context2.Response.StatusCode);
1108
+ Assert . False ( request2 . IsCompleted ) ;
1109
+ }
1110
+ else
1111
+ {
1112
+ Assert . Equal ( StatusCodes . Status409Conflict , context2 . Response . StatusCode ) ;
1113
+ //Assert.Equal(StatusCodes.Status200OK, context1.Response.StatusCode);
1114
+ Assert . False ( request1 . IsCompleted ) ;
1115
+ }
1116
+
1117
+ Assert . Equal ( HttpConnectionStatus . Active , connection . Status ) ;
1118
+
1119
+ manager . CloseConnections ( ) ;
1120
+
1121
+ await request1 . OrTimeout ( ) ;
1122
+ await request2 . OrTimeout ( ) ;
1123
+ }
1124
+ }
1125
+
1064
1126
[ Theory ]
1065
1127
[ InlineData ( HttpTransportType . ServerSentEvents ) ]
1066
1128
[ InlineData ( HttpTransportType . LongPolling ) ]
0 commit comments