-
Notifications
You must be signed in to change notification settings - Fork 287
Add another platform exception type to OutOfProcMiddleware #3383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
7587cd9
b744c64
1f061fb
22477b7
fbd9c76
0aaa225
d40c7fa
f4fb4ce
0b4e009
758b712
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,13 +7,12 @@ | |
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using DurableTask.Core; | ||
| using DurableTask.Core.Entities; | ||
| using DurableTask.Core.Entities.OperationFormat; | ||
| using DurableTask.Core.Exceptions; | ||
| using DurableTask.Core.History; | ||
| using DurableTask.Core.Middleware; | ||
| using Microsoft.Azure.WebJobs.Host; | ||
| using Microsoft.Azure.WebJobs.Host.Executors; | ||
| using Microsoft.Extensions.Logging; | ||
| using Microsoft.Extensions.Logging.Abstractions; | ||
| using Microsoft.Extensions.Options; | ||
| using Moq; | ||
|
|
@@ -31,13 +30,13 @@ | |
| var innerException = new InvalidOperationException("The internal function invoker returned a task that does not support return values!"); | ||
| var outerException = new Exception("Function invocation failed.", innerException); | ||
|
|
||
| var (middleware, dispatchContext) = this.SetupOrchestratorTest(outerException); | ||
| (OutOfProcMiddleware middleware, DispatchMiddlewareContext dispatchContext) = this.SetupOrchestratorTest(outerException); | ||
|
|
||
| // Act: should NOT throw SessionAbortedException — instead the orchestration should be marked as failed | ||
| await middleware.CallOrchestratorAsync(dispatchContext, () => Task.CompletedTask); | ||
|
|
||
| // Assert: the middleware should have set a failure result on the dispatch context | ||
| var result = dispatchContext.GetProperty<OrchestratorExecutionResult>(); | ||
| OrchestratorExecutionResult result = dispatchContext.GetProperty<OrchestratorExecutionResult>(); | ||
| Assert.NotNull(result); | ||
| } | ||
|
|
||
|
|
@@ -46,16 +45,43 @@ | |
| [MemberData(nameof(PlatformLevelExceptions))] | ||
| public async Task CallOrchestratorAsync_PlatformLevelException_ThrowsSessionAbortedException(Exception exception) | ||
| { | ||
| var (middleware, dispatchContext) = this.SetupOrchestratorTest(exception); | ||
| (OutOfProcMiddleware middleware, DispatchMiddlewareContext dispatchContext) = this.SetupOrchestratorTest(exception); | ||
|
|
||
| await Assert.ThrowsAsync<SessionAbortedException>( | ||
| () => middleware.CallOrchestratorAsync(dispatchContext, () => Task.CompletedTask)); | ||
| } | ||
|
|
||
| [Fact] | ||
| [Trait("Category", PlatformSpecificHelpers.TestCategory)] | ||
| public async Task CallEntityAsync_FunctionTimeoutAbortException_ThrowsSessionAbortedException() | ||
| { | ||
| var exception = new FunctionTimeoutAbortException("Activity A timed out! Worker channel closing"); | ||
|
|
||
| (OutOfProcMiddleware middleware, DispatchMiddlewareContext dispatchContext) = this.SetupEntityTest(exception); | ||
|
|
||
| await Assert.ThrowsAsync<SessionAbortedException>( | ||
| () => middleware.CallEntityAsync(dispatchContext, () => Task.CompletedTask)); | ||
| } | ||
|
|
||
| [Fact] | ||
| [Trait("Category", PlatformSpecificHelpers.TestCategory)] | ||
| public async Task CallActivityAsync_FunctionTimeoutAbortException_ThrowsSessionAbortedException() | ||
| { | ||
| var exception = new FunctionTimeoutAbortException("Activity A timed out! Worker channel closing"); | ||
|
|
||
| (OutOfProcMiddleware middleware, DispatchMiddlewareContext dispatchContext) = this.SetupActivityTest(exception); | ||
|
|
||
| await Assert.ThrowsAsync<SessionAbortedException>( | ||
| () => middleware.CallActivityAsync(dispatchContext, () => Task.CompletedTask)); | ||
| } | ||
|
|
||
| public static IEnumerable<object[]> PlatformLevelExceptions() | ||
| { | ||
| // FunctionTimeoutException (top-level) | ||
| yield return new object[] { new Host.FunctionTimeoutException("Function timed out.") }; | ||
| yield return new object[] { new Host.FunctionTimeoutException("Function timed out.") }; | ||
|
|
||
| // FunctionTimeoutAbortException (top-level) | ||
| yield return new object[] { new Host.FunctionTimeoutAbortException("Function timed out.") }; | ||
|
|
||
| // SessionAbortedException as InnerException (e.g. out-of-memory handling) | ||
| yield return new object[] { new Exception("Function invocation failed.", new SessionAbortedException("Out of memory")) }; | ||
|
|
@@ -69,24 +95,50 @@ | |
|
|
||
| private (OutOfProcMiddleware middleware, DispatchMiddlewareContext context) SetupOrchestratorTest(Exception executorException) | ||
| { | ||
| var (middleware, dispatchContext) = this.CreateMiddleware(executorException, "TestOrchestrator", FunctionType.Orchestrator); | ||
| (OutOfProcMiddleware middleware, DispatchMiddlewareContext dispatchContext) | ||
| = this.CreateMiddleware(executorException, "TestOrchestrator", FunctionType.Orchestrator); | ||
|
|
||
| var orchestrationState = new OrchestrationRuntimeState( | ||
| new List<HistoryEvent> | ||
| { | ||
| [ | ||
| new ExecutionStartedEvent(-1, null) { Name = "TestOrchestrator" }, | ||
| }); | ||
| ]); | ||
|
|
||
| dispatchContext.SetProperty(orchestrationState); | ||
| dispatchContext.SetProperty(new OrchestrationInstance { InstanceId = "test-instance-id" }); | ||
|
|
||
| return (middleware, dispatchContext); | ||
| } | ||
|
|
||
| private (OutOfProcMiddleware middleware, DispatchMiddlewareContext context) SetupEntityTest(Exception executorException) | ||
| { | ||
| (OutOfProcMiddleware middleware, DispatchMiddlewareContext dispatchContext) | ||
| = this.CreateMiddleware(executorException, "TestEntity", FunctionType.Entity); | ||
|
|
||
| dispatchContext.SetProperty(new EntityBatchRequest | ||
| { | ||
| InstanceId = "@TestEntity@test-key", | ||
| EntityState = null, | ||
| Operations = new List<OperationRequest>(), | ||
| }); | ||
|
|
||
| return (middleware, dispatchContext); | ||
| } | ||
|
|
||
| private (OutOfProcMiddleware middleware, DispatchMiddlewareContext context) SetupActivityTest(Exception executorException) | ||
| { | ||
| (OutOfProcMiddleware middleware, DispatchMiddlewareContext dispatchContext) | ||
| = this.CreateMiddleware(executorException, "TestActivity", FunctionType.Activity); | ||
|
|
||
| dispatchContext.SetProperty(new TaskScheduledEvent(-1) { Name = "TestActivity" }); | ||
| dispatchContext.SetProperty(new OrchestrationInstance { InstanceId = "test-instance-id" }); | ||
|
|
||
| return (middleware, dispatchContext); | ||
| } | ||
|
|
||
| private (OutOfProcMiddleware middleware, DispatchMiddlewareContext context) CreateMiddleware( | ||
| Exception executorException, string functionName, FunctionType functionType) | ||
| { | ||
| var extension = CreateDurableTaskExtension(); | ||
| DurableTaskExtension extension = CreateDurableTaskExtension(); | ||
|
|
||
| var mockExecutor = new Mock<ITriggeredFunctionExecutor>(); | ||
| mockExecutor | ||
|
|
@@ -131,15 +183,14 @@ | |
| new OptionsWrapper<DurableTaskOptions>(options), | ||
| NullLoggerFactory.Instance, | ||
| TestHelpers.GetTestNameResolver(), | ||
| new[] | ||
| { | ||
| [ | ||
| new AzureStorageDurabilityProviderFactory( | ||
| new OptionsWrapper<DurableTaskOptions>(options), | ||
| new TestStorageServiceClientProviderFactory(), | ||
| TestHelpers.GetTestNameResolver(), | ||
| NullLoggerFactory.Instance, | ||
| TestHelpers.GetMockPlatformInformationService()), | ||
| }, | ||
| ], | ||
| new TestHostShutdownNotificationService(), | ||
| new DurableHttpMessageHandlerFactory(), | ||
| platformInformationService: TestHelpers.GetMockPlatformInformationService()); | ||
|
|
@@ -148,13 +199,13 @@ | |
| private static WorkItemMetadata CreateWorkItemMetadata(bool isExtendedSession, bool includeState) | ||
| { | ||
| // WorkItemMetadata has an internal constructor, so we use reflection to create it. | ||
| var ctor = typeof(WorkItemMetadata).GetConstructor( | ||
| ConstructorInfo ctor = typeof(WorkItemMetadata).GetConstructor( | ||
| BindingFlags.Instance | BindingFlags.NonPublic, | ||
| binder: null, | ||
| new[] { typeof(bool), typeof(bool) }, | ||
| [typeof(bool), typeof(bool)], | ||
| modifiers: null); | ||
| Assert.NotNull(ctor); | ||
| return (WorkItemMetadata)ctor.Invoke(new object[] { isExtendedSession, includeState }); | ||
| return (WorkItemMetadata)ctor.Invoke([isExtendedSession, includeState]); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -163,12 +214,8 @@ | |
| /// <c>WorkerProcessExitException</c> lives in <c>Microsoft.Azure.WebJobs.Script</c> | ||
| /// (the Functions host runtime), which is too heavy to reference as a test dependency. | ||
| /// </summary> | ||
| private class WorkerProcessExitExceptionStub : Exception | ||
| private class WorkerProcessExitExceptionStub(string message) : Exception(message) | ||
|
Check warning on line 217 in test/FunctionsV2/OutOfProcMiddlewareTests.cs
|
||
| { | ||
| public WorkerProcessExitExceptionStub(string message) | ||
| : base(message) | ||
| { | ||
| } | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.