public HttpApiHandler(DurableTaskExtension config, ILogger logger) { this.config = config; this.logger = logger; }
public override async Task <string> Execute(OrchestrationContext innerContext, string serializedInput) { // Supress "Variable is assigned but its value is never used" in Functions V1 #pragma warning disable CS0219 OrchestrationRuntimeStatus status; // for reporting the status of the orchestration on App Insights #pragma warning restore CS0219 if (this.FunctionInvocationCallback == null) { throw new InvalidOperationException($"The {nameof(this.FunctionInvocationCallback)} has not been assigned!"); } if (!this.config.MessageDataConverter.IsDefault) { innerContext.MessageDataConverter = this.config.MessageDataConverter; } if (!this.config.ErrorDataConverter.IsDefault) { innerContext.ErrorDataConverter = this.config.ErrorDataConverter; } this.context.InnerContext = innerContext; this.context.RawInput = serializedInput; this.Config.TraceHelper.FunctionStarting( this.context.HubName, this.context.Name, this.context.InstanceId, this.Config.GetIntputOutputTrace(serializedInput), FunctionType.Orchestrator, this.context.IsReplaying); status = OrchestrationRuntimeStatus.Running; #if !FUNCTIONS_V1 // On a replay, the orchestrator will either go into a 'Completed' // state or a 'Failed' state. We want to avoid tagging them as // 'Running' while replaying because this could result in // Application Insights reporting the wrong status. if (!innerContext.IsReplaying) { DurableTaskExtension.TagActivityWithOrchestrationStatus(status, this.context.InstanceId); } #endif var orchestratorInfo = this.Config.GetOrchestratorInfo(new FunctionName(this.context.Name)); if (!this.context.IsReplaying) { this.context.AddDeferredTask(() => this.Config.LifeCycleNotificationHelper.OrchestratorStartingAsync( this.context.HubName, this.context.Name, this.context.InstanceId, this.context.IsReplaying)); } await this.InvokeUserCodeAndHandleResults(orchestratorInfo, innerContext); // release any locks that were held by the orchestration // just in case the application code did not do so already this.context.ReleaseLocks(); string serializedOutput = this.context.GetSerializedOutput(); this.Config.TraceHelper.FunctionCompleted( this.context.HubName, this.context.Name, this.context.InstanceId, this.Config.GetIntputOutputTrace(serializedOutput), this.context.ContinuedAsNew, FunctionType.Orchestrator, this.context.IsReplaying); status = OrchestrationRuntimeStatus.Completed; if (!this.context.IsReplaying) { this.context.AddDeferredTask(() => this.Config.LifeCycleNotificationHelper.OrchestratorCompletedAsync( this.context.HubName, this.context.Name, this.context.InstanceId, this.context.ContinuedAsNew, this.context.IsReplaying)); } #if !FUNCTIONS_V1 DurableTaskExtension.TagActivityWithOrchestrationStatus(status, this.context.InstanceId); #endif return(serializedOutput); }
internal DurableActivityContext(DurableTaskExtension config, string instanceId, string serializedInput) { this.messageDataConverter = config.MessageDataConverter; this.instanceId = instanceId; this.serializedInput = serializedInput; }
public DurableEntityContext(DurableTaskExtension config, EntityId entity, TaskEntityShim shim) : base(config, entity.EntityName) { this.self = entity; this.shim = shim; }
// Responsible for invoking the function, handling the exception, set the output, and if // the function execution is out-of-process, handles the replay. private async Task InvokeUserCodeAndHandleResults( RegisteredFunctionInfo orchestratorInfo, OrchestrationContext innerContext) { try { Task invokeTask = this.FunctionInvocationCallback(); if (invokeTask is Task <object> resultTask) { // Orchestrator threads cannot perform async I/O, so block on such out-of-proc threads. // Possible performance implications; may need revisiting. object returnValue = orchestratorInfo.IsOutOfProc ? resultTask.Result : await resultTask; if (returnValue != null) { if (orchestratorInfo.IsOutOfProc) { await this.outOfProcShim.HandleDurableTaskReplay(new OrchestrationInvocationResult() { ReturnValue = returnValue, }); } else { this.context.SetOutput(returnValue); } } } else { throw new InvalidOperationException("The WebJobs runtime returned a invocation task that does not support return values!"); } } catch (Exception e) { if (orchestratorInfo.IsOutOfProc && OutOfProcExceptionHelpers.TryExtractOutOfProcStateJson(e.InnerException, out string returnValue) && !string.IsNullOrEmpty(returnValue)) { try { await this.outOfProcShim.HandleDurableTaskReplay(new OrchestrationInvocationResult() { ReturnValue = returnValue, Exception = e, }); } catch (OrchestrationFailureException ex) { this.TraceAndSendExceptionNotification(ex.Details); this.context.OrchestrationException = ExceptionDispatchInfo.Capture(ex); throw ex; } } else { this.TraceAndSendExceptionNotification(e.ToString()); var orchestrationException = new OrchestrationFailureException( $"Orchestrator function '{this.context.Name}' failed: {e.Message}", Utils.SerializeCause(e, innerContext.ErrorDataConverter)); this.context.OrchestrationException = ExceptionDispatchInfo.Capture(orchestrationException); #if !FUNCTIONS_V1 DurableTaskExtension.TagActivityWithOrchestrationStatus(OrchestrationRuntimeStatus.Failed, this.context.InstanceId); #endif throw orchestrationException; } } finally { this.context.IsCompleted = true; } }
public BindingHelper(DurableTaskExtension config, EndToEndTraceHelper traceHelper) { this.config = config; this.traceHelper = traceHelper; }
public HttpApiHandler(DurableTaskExtension config, ILogger logger) { this.config = config; this.dataConverter = this.config.DataConverter; this.logger = logger; }
internal DurableCommonContext(DurableTaskExtension config, string functionName) { this.Config = config ?? throw new ArgumentNullException(nameof(config)); this.FunctionName = functionName; }
internal DurableCommonContext(DurableTaskExtension config, string functionName) { this.Config = config ?? throw new ArgumentNullException(nameof(config)); this.FunctionName = functionName; this.EntityMessageReorderWindow = TimeSpan.FromMinutes(config.Options.EntityMessageReorderWindowInMinutes); }
public override async Task <string> Execute(OrchestrationContext innerContext, string serializedInput) { #if !FUNCTIONS_V1 // Adding "Tags" to activity allows using App Insights to query current state of entities var activity = Activity.Current; OrchestrationRuntimeStatus status = OrchestrationRuntimeStatus.Running; DurableTaskExtension.TagActivityWithOrchestrationStatus(status, this.context.InstanceId, true); #endif if (this.operationBatch.Count == 0 && this.lockRequest == null && (this.toBeRescheduled == null || this.toBeRescheduled.Count == 0)) { // we are idle after a ContinueAsNew - the batch is empty. // Wait for more messages to get here (via extended sessions) await this.doneProcessingMessages.Task; } if (!this.messageDataConverter.IsDefault) { innerContext.MessageDataConverter = this.messageDataConverter; } if (!this.errorDataConverter.IsDefault) { innerContext.ErrorDataConverter = this.errorDataConverter; } this.Config.TraceHelper.FunctionStarting( this.context.HubName, this.context.Name, this.context.InstanceId, this.Config.GetIntputOutputTrace(serializedInput), FunctionType.Entity, isReplay: false); if (this.NumberEventsToReceive > 0) { await this.doneProcessingMessages.Task; } // Commit the effects of this batch, if // we have not already run into an internal error // (in which case we will abort the batch instead of committing it) if (this.context.InternalError == null) { bool writeBackSuccessful = true; ResponseMessage serializationErrorMessage = null; if (this.RollbackFailedOperations) { // the state has already been written back, since it is // done right after each operation. } else { // we are writing back the state here, after executing // the entire batch of operations. writeBackSuccessful = this.context.TryWriteback(out serializationErrorMessage); } // Reschedule all signals that were received before their time this.context.RescheduleMessages(innerContext, this.toBeRescheduled); // Send all buffered outgoing messages this.context.SendOutbox(innerContext, writeBackSuccessful, serializationErrorMessage); var jstate = JToken.FromObject(this.context.State); // continue as new innerContext.ContinueAsNew(jstate); } if (this.context.ErrorsPresent(out var description)) { this.Config.TraceHelper.FunctionFailed( this.context.HubName, this.context.Name, this.context.InstanceId, description, functionType: FunctionType.Entity, isReplay: false); } else { this.Config.TraceHelper.FunctionCompleted( this.context.HubName, this.context.Name, this.context.InstanceId, this.Config.GetIntputOutputTrace(this.context.State.EntityState), continuedAsNew: true, functionType: FunctionType.Entity, isReplay: false); } // The return value is not used. return(string.Empty); }