Skip to content

Commit

Permalink
Handle cancellation token if function is invoked before cancellation …
Browse files Browse the repository at this point in the history
…token (#2546)

* initial change

* add unit test

* updating unit test
  • Loading branch information
aishwaryabh authored Jul 2, 2024
1 parent 0152b65 commit d5b185e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ public async ValueTask<FunctionInputBindingResult> BindFunctionInputAsync(Functi
{
ObjectDisposedThrowHelper.ThrowIf(_disposed, this);

await _semaphoreSlim.WaitAsync(WaitTimeInMilliSeconds, context.CancellationToken);
// Setting second parameter to CancellationToken.None to prevent a TaskCancelledException if the
// pipeline cancels the code before the function is invoked. This way the customer code will be invoked
// and they can handle the cancellation token.
await _semaphoreSlim.WaitAsync(WaitTimeInMilliSeconds, CancellationToken.None);

try
{
Expand Down
44 changes: 44 additions & 0 deletions test/DotNetWorkerTests/DefaultModelBindingFeatureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,50 @@ public async void BindFunctionInputAsync_Populates_ParametersUsingConverters()
Assert.Equal("0ab4800e-1308-4e9f-be5f-4372717e68eb", guid.ToString());
}

[Fact]
public async void BindFunctionInputAsync_IgnoreCancellationToken()
{
// Arrange
var parameters = new List<FunctionParameter>()
{
new("myQueueItem",typeof(Book)),
new ("myGuid", typeof(Guid)),
new ("token", typeof(CancellationToken))
};
IInvocationFeatures features = new InvocationFeatures(Enumerable.Empty<IInvocationFeatureProvider>());
features.Set(_serviceProvider.GetService<IInputConversionFeature>());
features.Set<IFunctionBindingsFeature>(new TestFunctionBindingsFeature()
{
InputData = new Dictionary<string, object>
{
{ "myQueueItem","{\"id\":\"foo\", \"title\":\"bar\"}" },
{ "myGuid","0ab4800e-1308-4e9f-be5f-4372717e68eb" }
}
});

var definition = new TestFunctionDefinition(parameters: parameters, inputBindings: new Dictionary<string, BindingMetadata>
{
{ "myQueueItem", new TestBindingMetadata("myQueueItem","queueTrigger",BindingDirection.In) },
{ "myGuid", new TestBindingMetadata("myGuid","queueTrigger",BindingDirection.In) }
});

// Register a cancellation token
var cts = new CancellationTokenSource();
cts.Cancel();
var functionContext = new TestFunctionContext(definition, invocation: null, cts.Token, serviceProvider: _serviceProvider, features: features);

// Act
var bindingResult = await _functionInputBindingFeature.BindFunctionInputAsync(functionContext);
var parameterValuesArray = bindingResult.Values;
// Assert
var book = TestUtility.AssertIsTypeAndConvert<Book>(parameterValuesArray[0]);
Assert.Equal("foo", book.Id);
var guid = TestUtility.AssertIsTypeAndConvert<Guid>(parameterValuesArray[1]);
Assert.Equal("0ab4800e-1308-4e9f-be5f-4372717e68eb", guid.ToString());
var cancellationToken = TestUtility.AssertIsTypeAndConvert<CancellationToken>(parameterValuesArray[2]);
Assert.True(cancellationToken.IsCancellationRequested);
}

[Fact]
public async void BindFunctionInputAsync_Populates_Parameter_Using_DefaultValue_When_CouldNot_Populate_From_InputData()
{
Expand Down

0 comments on commit d5b185e

Please sign in to comment.