@@ -1284,6 +1284,97 @@ public async Task AvailabilityStrategyWithCancellationTokenThrowsExceptionTest()
12841284
12851285 }
12861286
1287+ [ TestMethod ]
1288+ [ TestCategory ( "MultiRegion" ) ]
1289+ public async Task HedgingCancellationTokenHandling ( )
1290+ {
1291+ List < FeedRange > feedRanges = ( List < FeedRange > ) await this . container . GetFeedRangesAsync ( ) ;
1292+ Assert . IsTrue ( feedRanges . Any ( ) ) ;
1293+
1294+ try
1295+ {
1296+ await this . container . DeleteItemAsync < CosmosIntegrationTestObject > ( "deleteMe" , new PartitionKey ( "MMWrite" ) ) ;
1297+ }
1298+ catch ( Exception ) { }
1299+
1300+
1301+ FaultInjectionRule sendDelay = new FaultInjectionRuleBuilder (
1302+ id : "sendDelay" ,
1303+ condition :
1304+ new FaultInjectionConditionBuilder ( )
1305+ . WithRegion ( region1 )
1306+ . WithConnectionType ( FaultInjectionConnectionType . Gateway )
1307+ . WithEndpoint (
1308+ new FaultInjectionEndpointBuilder (
1309+ MultiRegionSetupHelpers . dbName ,
1310+ MultiRegionSetupHelpers . containerName ,
1311+ feedRanges [ 0 ] )
1312+ . WithIncludePrimary ( true )
1313+ . WithReplicaCount ( 4 )
1314+ . Build ( ) )
1315+ . Build ( ) ,
1316+ result :
1317+ FaultInjectionResultBuilder . GetResultBuilder ( FaultInjectionServerErrorType . SendDelay )
1318+ . WithDelay ( TimeSpan . FromMilliseconds ( 68000 ) )
1319+ . Build ( ) )
1320+ . WithDuration ( TimeSpan . FromMinutes ( 90 ) )
1321+ . Build ( ) ;
1322+
1323+ List < FaultInjectionRule > rules = new List < FaultInjectionRule > ( ) { sendDelay } ;
1324+ FaultInjector faultInjector = new FaultInjector ( rules ) ;
1325+
1326+ sendDelay . Disable ( ) ;
1327+
1328+ CosmosClientOptions clientOptions = new CosmosClientOptions ( )
1329+ {
1330+ ConnectionMode = ConnectionMode . Direct ,
1331+ ApplicationPreferredRegions = new List < string > ( ) { region1 , region2 } ,
1332+ Serializer = this . cosmosSystemTextJsonSerializer ,
1333+ RequestTimeout = TimeSpan . FromMilliseconds ( 5000 )
1334+ } ;
1335+
1336+ using ( CosmosClient faultInjectionClient = new CosmosClient (
1337+ connectionString : this . connectionString ,
1338+ clientOptions : faultInjector . GetFaultInjectionClientOptions ( clientOptions ) ) )
1339+ {
1340+ Database database = faultInjectionClient . GetDatabase ( MultiRegionSetupHelpers . dbName ) ;
1341+ Container container = database . GetContainer ( MultiRegionSetupHelpers . containerName ) ;
1342+
1343+ sendDelay . Enable ( ) ;
1344+
1345+ CancellationTokenSource cts = new CancellationTokenSource ( ) ;
1346+ cts . CancelAfter ( TimeSpan . FromSeconds ( 5 ) ) ; // Cancellation token expiry time is 5 seconds.
1347+
1348+ ItemRequestOptions requestOptions = new ItemRequestOptions
1349+ {
1350+ AvailabilityStrategy = new CrossRegionHedgingAvailabilityStrategy (
1351+ threshold : TimeSpan . FromMilliseconds ( 100 ) ,
1352+ thresholdStep : TimeSpan . FromMilliseconds ( 50 ) ,
1353+ enableMultiWriteRegionHedge : true )
1354+ } ;
1355+
1356+ CosmosIntegrationTestObject CosmosIntegrationTestObject = new CosmosIntegrationTestObject
1357+ {
1358+ Id = "deleteMe" ,
1359+ Pk = "MMWrite" ,
1360+ Other = "test"
1361+ } ;
1362+
1363+ ItemResponse < CosmosIntegrationTestObject > ir = await container . CreateItemAsync < CosmosIntegrationTestObject > (
1364+ CosmosIntegrationTestObject ,
1365+ requestOptions : requestOptions ,
1366+ cancellationToken : cts . Token ) ;
1367+
1368+ sendDelay . Disable ( ) ;
1369+
1370+ CosmosTraceDiagnostics traceDiagnostic = ir . Diagnostics as CosmosTraceDiagnostics ;
1371+ Assert . IsNotNull ( traceDiagnostic ) ;
1372+ traceDiagnostic . Value . Data . TryGetValue ( "Response Region" , out object hedgeContext ) ;
1373+ Assert . IsNotNull ( hedgeContext ) ;
1374+ Assert . AreEqual ( region2 , ( string ) hedgeContext ) ;
1375+ }
1376+ }
1377+
12871378 private static async Task HandleChangesAsync (
12881379 ChangeFeedProcessorContext context ,
12891380 IReadOnlyCollection < CosmosIntegrationTestObject > changes ,
0 commit comments