@@ -308,6 +308,68 @@ await Assert.ThrowsAsync<OrleansCascadingAbortException>(
308308 Assert . Equal ( 0 , conflictingOperationCount ) ;
309309 }
310310
311+ [ Fact ]
312+ public async Task UnresolvableQueuedWriteUpgradeAbortsItsPendingOperations ( )
313+ {
314+ var queue = new GatedCancelTransactionQueue (
315+ CreateParticipant ( "resource" , ParticipantId . Role . Resource ) ,
316+ new TestActivationLifetime ( ) ) ;
317+ var currentTransactionId = Guid . NewGuid ( ) ;
318+ var upgradingTransactionId = Guid . NewGuid ( ) ;
319+ var conflictingTransactionId = Guid . NewGuid ( ) ;
320+ var higherPriority = new DateTime ( 2026 , 8 , 21 , 12 , 0 , 0 , DateTimeKind . Utc ) ;
321+ var lowerPriority = higherPriority . AddTicks ( 1 ) ;
322+ var transactionTimeout = TimeSpan . FromMinutes ( 1 ) ;
323+ var upgradingOperationCount = 0 ;
324+ var conflictingOperationCount = 0 ;
325+
326+ await queue . RWLock . EnterLock (
327+ currentTransactionId ,
328+ higherPriority ,
329+ transactionTimeout ,
330+ new AccessCounter ( ) ,
331+ isRead : false ,
332+ exclusiveLock : false ,
333+ static ( ) => 0 ) ;
334+ var queuedRead = queue . RWLock . EnterLock (
335+ upgradingTransactionId ,
336+ lowerPriority ,
337+ transactionTimeout ,
338+ new AccessCounter ( ) ,
339+ isRead : true ,
340+ exclusiveLock : false ,
341+ ( ) => ++ upgradingOperationCount ) ;
342+ var conflictingRead = queue . RWLock . EnterLock (
343+ conflictingTransactionId ,
344+ higherPriority ,
345+ transactionTimeout ,
346+ new AccessCounter ( ) ,
347+ isRead : true ,
348+ exclusiveLock : false ,
349+ ( ) => ++ conflictingOperationCount ) ;
350+
351+ await Assert . ThrowsAsync < OrleansTransactionLockUpgradeException > (
352+ ( ) => queue . RWLock . EnterLock (
353+ upgradingTransactionId ,
354+ lowerPriority ,
355+ transactionTimeout ,
356+ new AccessCounter { Reads = 1 } ,
357+ isRead : false ,
358+ exclusiveLock : false ,
359+ static ( ) => 0 ) ) ;
360+ await Assert . ThrowsAsync < OrleansCascadingAbortException > (
361+ ( ) => queuedRead . WaitAsync ( TestContext . Current . CancellationToken ) ) ;
362+ Assert . Equal ( 0 , upgradingOperationCount ) ;
363+ Assert . False ( conflictingRead . IsCompleted ) ;
364+
365+ queue . RWLock . Rollback ( currentTransactionId ) ;
366+ queue . RWLock . Notify ( ) ;
367+
368+ Assert . Equal ( 1 , await conflictingRead . WaitAsync ( TestContext . Current . CancellationToken ) ) ;
369+ Assert . Equal ( 0 , upgradingOperationCount ) ;
370+ Assert . Equal ( 1 , conflictingOperationCount ) ;
371+ }
372+
311373 [ Fact ]
312374 public async Task LocalAbortCompletesManagerDecisionAfterDispatchAndBeforeCleanupSettles ( )
313375 {
0 commit comments