protected override void Execute(NativeActivityContext context) { ReceiveRequestSendResponseScopeExecutionProperty executionProperty = context.GetReceiveRequestSendResponseScopeExecutionProperty(); if (!executionProperty.Faulted && !executionProperty.IsInitializedAndCompleted) { // The taskCompletionSource from an incoming request is not completed (we don't have it or we have but not completed). if (!executionProperty.IsInitializedButNotCompleted) { // We don't have taskCompletionSource from an incoming request. if (executionProperty.Idempotent && context.GetPreviousResponseParameterExtension().TrySetResponseCanceled(executionProperty.OperationName)) { context.ScheduleActivity(persist); } } else { // We have taskCompletionSource from an incoming request, after setting the response in the extension we cancel the taskCompletionSource also. if (executionProperty.Idempotent && context.GetPreviousResponseParameterExtension().TrySetResponseCanceled(executionProperty.OperationName)) { context.ScheduleActivity(persist, PersistCompletionCallback); } else { executionProperty.TrySetTaskCompletionSourceCanceled(); } } } }
protected override void PostExecute(NativeActivityContext context, UnhandledExceptionAction unhandledExceptionAction) { Exception propagatedException = PropagatedException.Get(context); ReceiveRequestSendResponseScopeExecutionProperty executionProperty = context.GetReceiveRequestSendResponseScopeExecutionProperty(); // Due to this activity will handle the fault, the Finally activity in the TryCatch will be executed also, // we have to prevent canceling the operation and the stored previous response in the extension. executionProperty.Faulted = true; switch (unhandledExceptionAction) { default: case UnhandledExceptionAction.Abort: // This will implicitly also call OnUnhandledException. context.Abort(propagatedException); break; case UnhandledExceptionAction.Cancel: // Don't wait for completion, that is critical only for the persistence to happen before the taskCompletionSource of the request is completed. context.ScheduleActivity(cancelWorkflow); break; case UnhandledExceptionAction.Terminate: // Don't wait for completion, that is critical only for the persistence to happen before the taskCompletionSource of the request is completed. context.ScheduleAction(terminateWorkflow, propagatedException); break; } }
private void SetTaskCompletionSourceResult(ReceiveRequestSendResponseScopeExecutionProperty <object> executionProperty, NativeActivityContext context) { executionProperty.SetTaskCompletionSourceResult(null, ThrowIfReloaded); if (context.GetActivityContext().TrackingEnabled) { context.Track(new SendResponseRecord()); } }
protected override void Execute(NativeActivityContext context) { if (Body != null) { ReceiveRequestSendResponseScopeExecutionProperty executionProperty = receiveRequestSendResponseScopeExecutionPropertyFactory(); context.Properties.Add(ExecutionPropertyName, executionProperty); context.ScheduleActivity(tryCatch); } }
// We must persist before sending the response if we are idempotent, but this will cause double persist if the workflow goes idle after the response is sent. // TODO: can we do anything against this??? protected override void Execute(NativeActivityContext context) { ReceiveRequestSendResponseScopeExecutionProperty <object> executionProperty = context.GetReceiveRequestSendResponseScopeExecutionProperty <object>(); executionProperty.AssertIsInitialized(); if (Idempotent) { context.GetPreviousResponseParameterExtension().SetResponseParameter( executionProperty.OperationName, typeof(void), null); context.ScheduleActivity(persist, PersistCompletionCallback); } else { SetTaskCompletionSourceResult(executionProperty, context); } }