private async Task CallAsyncCore(MethodInfo method, IDictionary <string, object> arguments, CancellationToken cancellationToken) { await EnsureHostStartedAsync(cancellationToken); IFunctionDefinition function = ResolveFunctionDefinition(method, _context.FunctionLookup); IFunctionInstance instance = CreateFunctionInstance(function, arguments); IDelayedException exception = await _context.Executor.TryExecuteAsync(instance, cancellationToken); if (exception != null) { exception.Throw(); } }
private async Task CallAsyncCore(IFunctionDefinition function, object functionKey, IDictionary <string, object> arguments, CancellationToken cancellationToken) { Validate(function, functionKey); IFunctionInstance instance = CreateFunctionInstance(function, arguments); IDelayedException exception = null; exception = await _context.Executor.TryExecuteAsync(instance, cancellationToken); if (exception != null) { exception.Throw(); } }
/// <summary>Calls a job method.</summary> /// <param name="name">The name of the function to call.</param> /// <param name="arguments">The argument names and values to bind to parameters in the job method. In addition to parameter values, these may also include binding data values. </param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>A <see cref="Task"/> that will call the job method.</returns> public async Task CallAsync(string name, IDictionary <string, object> arguments = null, CancellationToken cancellationToken = default(CancellationToken)) { if (name == null) { throw new ArgumentNullException(nameof(name)); } ThrowIfDisposed(); await EnsureHostInitializedAsync(cancellationToken); IFunctionDefinition function = _context.FunctionLookup.LookupByName(name); Validate(function, name); IFunctionInstance instance = CreateFunctionInstance(function, arguments); IDelayedException exception = await _context.Executor.TryExecuteAsync(instance, cancellationToken); if (exception != null) { exception.Throw(); } }
internal static async Task ExecuteWithWatchersAsync(IFunctionInstance instance, IReadOnlyDictionary <string, IValueProvider> parameters, TraceWriter traceWriter, CancellationTokenSource functionCancellationTokenSource) { IFunctionInvoker invoker = instance.Invoker; IReadOnlyList <string> parameterNames = invoker.ParameterNames; Tuple <object[], IDelayedException> preparedParameters = await PrepareParametersAsync(parameterNames, parameters); object[] invokeParameters = preparedParameters.Item1; IDelayedException delayedBindingException = preparedParameters.Item2; if (delayedBindingException != null) { // This is done inside a watcher context so that each binding error is publish next to the binding in // the parameter status log. delayedBindingException.Throw(); } // if the function is a Singleton, aquire the lock SingletonLock singleton = await GetSingletonLockAsync(parameters); if (singleton != null) { await singleton.AcquireAsync(functionCancellationTokenSource.Token); } // Create a source specifically for timeouts using (CancellationTokenSource timeoutTokenSource = new CancellationTokenSource()) { MethodInfo method = instance.FunctionDescriptor.Method; TimeoutAttribute timeoutAttribute = TypeUtility.GetHierarchicalAttributeOrNull <TimeoutAttribute>(method); bool throwOnTimeout = timeoutAttribute == null ? false : timeoutAttribute.ThrowOnTimeout; var timer = StartFunctionTimeout(instance, timeoutAttribute, timeoutTokenSource, traceWriter); TimeSpan timerInterval = timer == null ? TimeSpan.MinValue : TimeSpan.FromMilliseconds(timer.Interval); try { await InvokeAsync(invoker, invokeParameters, timeoutTokenSource, functionCancellationTokenSource, throwOnTimeout, timerInterval, instance); } finally { if (timer != null) { timer.Stop(); timer.Dispose(); } } } // Process any out parameters and persist any pending values. // Ensure IValueBinder.SetValue is called in BindStepOrder. This ordering is particularly important for // ensuring queue outputs occur last. That way, all other function side-effects are guaranteed to have // occurred by the time messages are enqueued. string[] parameterNamesInBindOrder = SortParameterNamesInStepOrder(parameters); foreach (string name in parameterNamesInBindOrder) { IValueProvider provider = parameters[name]; IValueBinder binder = provider as IValueBinder; if (binder != null) { object argument = invokeParameters[GetParameterIndex(parameterNames, name)]; try { // This could do complex things that may fail. Catch the exception. await binder.SetValueAsync(argument, functionCancellationTokenSource.Token); } catch (OperationCanceledException) { throw; } catch (Exception exception) { string message = String.Format(CultureInfo.InvariantCulture, "Error while handling parameter {0} after function returned:", name); throw new InvalidOperationException(message, exception); } } } if (singleton != null) { await singleton.ReleaseAsync(functionCancellationTokenSource.Token); } }