internal void RegisterActivity(FunctionName activityFunction, ITriggeredFunctionExecutor executor) { if (this.knownActivities.TryGetValue(activityFunction, out RegisteredFunctionInfo existing)) { existing.Executor = executor; } else { this.TraceHelper.ExtensionInformationalEvent( this.Options.HubName, instanceId: string.Empty, functionName: activityFunction.Name, message: $"Registering activity function named {activityFunction}.", writeToUserLogs: false); var info = new RegisteredFunctionInfo(executor, isOutOfProc: false); this.knownActivities[activityFunction] = info; } }
internal void RegisterEntity(FunctionName entityFunction, RegisteredFunctionInfo entityInfo) { if (entityInfo != null) { entityInfo.IsDeregistered = false; } if (this.knownEntities.TryAdd(entityFunction, entityInfo)) { this.TraceHelper.ExtensionInformationalEvent( this.Options.HubName, instanceId: string.Empty, functionName: entityFunction.Name, message: $"Registered entity function named {entityFunction}.", writeToUserLogs: false); } else { this.knownEntities[entityFunction] = entityInfo; } }
internal void RegisterOrchestrator(FunctionName orchestratorFunction, RegisteredFunctionInfo orchestratorInfo) { if (orchestratorInfo != null) { orchestratorInfo.IsDeregistered = false; } if (this.knownOrchestrators.TryAdd(orchestratorFunction, orchestratorInfo)) { this.TraceHelper.ExtensionInformationalEvent( this.Options.HubName, instanceId: string.Empty, functionName: orchestratorFunction.Name, message: $"Registered orchestrator function named {orchestratorFunction}.", writeToUserLogs: false); } else { this.knownOrchestrators[orchestratorFunction] = orchestratorInfo; } }
// 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.TraceAndReplay(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 != null && orchestratorInfo.IsOutOfProc && OutOfProcExceptionHelpers.TryExtractOutOfProcStateJson(e.InnerException, out string returnValue) && !string.IsNullOrEmpty(returnValue)) { try { await this.TraceAndReplay(returnValue, 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; } }