@@ -1006,7 +1006,43 @@ public async Task FilterOrchestrationsByName()
10061006
10071007 // This should throw as the work is denied.
10081008 instanceId = await server . Client . ScheduleNewOrchestrationInstanceAsync ( orchestratorName ) ;
1009- await Assert . ThrowsAsync < OperationCanceledException > ( async ( ) => await server . Client . WaitForInstanceCompletionAsync ( instanceId , new CancellationTokenSource ( TimeSpan . FromSeconds ( 5 ) ) . Token ) ) ;
1009+ using CancellationTokenSource cts = new CancellationTokenSource ( TimeSpan . FromSeconds ( 5 ) ) ;
1010+ await Assert . ThrowsAsync < OperationCanceledException > ( async ( ) => await server . Client . WaitForInstanceCompletionAsync ( instanceId , cts . Token ) ) ;
1011+ }
1012+
1013+ [ Obsolete ( "Experimental" ) ]
1014+ [ Fact ]
1015+ public async Task FilterOrchestrationsByNamePassesWhenNotMatching ( )
1016+ {
1017+ // Setup a worker with an Orchestration Filter.
1018+ TaskName orchestratorName = nameof ( EmptyOrchestration ) ;
1019+ var orchestrationFilter = new OrchestrationFilter ( ) ;
1020+ await using HostTestLifetime server = await this . StartWorkerAsync ( b =>
1021+ {
1022+ b . AddTasks ( tasks => tasks . AddOrchestratorFunc ( orchestratorName , ctx => Task . FromResult < object ? > ( null ) ) ) ;
1023+ b . UseOrchestrationFilter ( orchestrationFilter ) ;
1024+ } ) ;
1025+
1026+ // Nothing in the filter set, the orchestration should complete.
1027+ string instanceId = await server . Client . ScheduleNewOrchestrationInstanceAsync ( orchestratorName ) ;
1028+ OrchestrationMetadata metadata = await server . Client . WaitForInstanceCompletionAsync (
1029+ instanceId , this . TimeoutToken ) ;
1030+
1031+ Assert . NotNull ( metadata ) ;
1032+ Assert . Equal ( instanceId , metadata . InstanceId ) ;
1033+ Assert . Equal ( OrchestrationRuntimeStatus . Completed , metadata . RuntimeStatus ) ;
1034+
1035+ // Update the filter and re-enqueue. The name doesn't match so the filter should be OK.
1036+ orchestrationFilter . NameDenySet . Add ( $ "not-{ orchestratorName } ") ;
1037+
1038+ // This should throw as the work is denied.
1039+ instanceId = await server . Client . ScheduleNewOrchestrationInstanceAsync ( orchestratorName ) ;
1040+ metadata = await server . Client . WaitForInstanceCompletionAsync (
1041+ instanceId , this . TimeoutToken ) ;
1042+
1043+ Assert . NotNull ( metadata ) ;
1044+ Assert . Equal ( instanceId , metadata . InstanceId ) ;
1045+ Assert . Equal ( OrchestrationRuntimeStatus . Completed , metadata . RuntimeStatus ) ;
10101046 }
10111047
10121048 [ Obsolete ( "Experimental" ) ]
@@ -1046,19 +1082,66 @@ public async Task FilterOrchestrationsByTag()
10461082 {
10471083 Tags = orchestratorTags ,
10481084 } ) ;
1049- await Assert . ThrowsAsync < OperationCanceledException > ( async ( ) => await server . Client . WaitForInstanceCompletionAsync ( instanceId , new CancellationTokenSource ( TimeSpan . FromSeconds ( 5 ) ) . Token ) ) ;
1085+ using CancellationTokenSource cts = new CancellationTokenSource ( TimeSpan . FromSeconds ( 5 ) ) ;
1086+ await Assert . ThrowsAsync < OperationCanceledException > ( async ( ) => await server . Client . WaitForInstanceCompletionAsync ( instanceId , cts . Token ) ) ;
10501087 }
10511088
1089+ [ Obsolete ( "Experimental" ) ]
1090+ [ Fact ]
1091+ public async Task FilterOrchestrationsByTagPassesWithNoMatch ( )
1092+ {
1093+ // Setup a worker with an Orchestration Filter.
1094+ TaskName orchestratorName = nameof ( EmptyOrchestration ) ;
1095+ IReadOnlyDictionary < string , string > orchestratorTags = new Dictionary < string , string >
1096+ {
1097+ { "test" , "true" }
1098+ } ;
1099+ var orchestrationFilter = new OrchestrationFilter ( ) ;
1100+ await using HostTestLifetime server = await this . StartWorkerAsync ( b =>
1101+ {
1102+ b . AddTasks ( tasks => tasks . AddOrchestratorFunc ( orchestratorName , ctx => Task . FromResult < object ? > ( null ) ) ) ;
1103+ b . UseOrchestrationFilter ( orchestrationFilter ) ;
1104+ } ) ;
1105+
1106+ // Nothing in the filter set, the orchestration should complete.
1107+ string instanceId = await server . Client . ScheduleNewOrchestrationInstanceAsync ( orchestratorName , new StartOrchestrationOptions
1108+ {
1109+ Tags = orchestratorTags ,
1110+ } ) ;
1111+ OrchestrationMetadata metadata = await server . Client . WaitForInstanceCompletionAsync (
1112+ instanceId , this . TimeoutToken ) ;
1113+
1114+ Assert . NotNull ( metadata ) ;
1115+ Assert . Equal ( instanceId , metadata . InstanceId ) ;
1116+ Assert . Equal ( OrchestrationRuntimeStatus . Completed , metadata . RuntimeStatus ) ;
1117+
1118+ // Update the filter and re-enqueue. The tags don't match so the orchestration should be OK.
1119+ orchestrationFilter . TagDenyDict . Add ( "test" , "false" ) ;
1120+
1121+ // This should throw as the work is denied.
1122+ instanceId = await server . Client . ScheduleNewOrchestrationInstanceAsync ( orchestratorName , new StartOrchestrationOptions
1123+ {
1124+ Tags = orchestratorTags ,
1125+ } ) ;
1126+ metadata = await server . Client . WaitForInstanceCompletionAsync (
1127+ instanceId , this . TimeoutToken ) ;
1128+
1129+ Assert . NotNull ( metadata ) ;
1130+ Assert . Equal ( instanceId , metadata . InstanceId ) ;
1131+ Assert . Equal ( OrchestrationRuntimeStatus . Completed , metadata . RuntimeStatus ) ;
1132+ }
1133+
1134+ [ Obsolete ( "Experimental" ) ]
10521135 class OrchestrationFilter : IOrchestrationFilter
10531136 {
10541137 public ISet < string > NameDenySet { get ; set ; } = new HashSet < string > ( ) ;
10551138 public IDictionary < string , string > TagDenyDict = new Dictionary < string , string > ( ) ;
10561139
1057- public Task < bool > IsOrchestrationValidAsync ( OrchestrationInfo info , CancellationToken cancellationToken = default )
1140+ public ValueTask < bool > IsOrchestrationValidAsync ( OrchestrationFilterParameters info , CancellationToken cancellationToken = default )
10581141 {
1059- return Task . FromResult (
1142+ return ValueTask . FromResult (
10601143 ! this . NameDenySet . Contains ( info . Name )
1061- && ! this . TagDenyDict . Any ( kvp => info . Tags . ContainsKey ( kvp . Key ) && info . Tags [ kvp . Key ] == kvp . Value ) ) ;
1144+ && ! this . TagDenyDict . Any ( kvp => info . Tags != null && info . Tags . ContainsKey ( kvp . Key ) && info . Tags [ kvp . Key ] == kvp . Value ) ) ;
10621145 }
10631146 }
10641147
0 commit comments