コード例 #1
0
        private async Task ExecuteWithOutputLogsAsync(IFunctionInstance instance,
                                                      IReadOnlyDictionary <string, IValueProvider> parameters,
                                                      TextWriter consoleOutput,
                                                      IFunctionOutputDefinition outputDefinition,
                                                      IDictionary <string, ParameterLog> parameterLogCollector,
                                                      CancellationToken cancellationToken)
        {
            IFunctionInvoker invoker = instance.Invoker;
            IReadOnlyDictionary <string, IWatcher> watches = CreateWatches(parameters);
            IRecurrentCommand updateParameterLogCommand    =
                outputDefinition.CreateParameterLogUpdateCommand(watches, consoleOutput);

            using (ITaskSeriesTimer updateParameterLogTimer = StartParameterLogTimer(updateParameterLogCommand,
                                                                                     _backgroundExceptionDispatcher))
            {
                try
                {
                    await ExecuteWithWatchersAsync(invoker, parameters, cancellationToken);

                    if (updateParameterLogTimer != null)
                    {
                        // Stop the watches after calling IValueBinder.SetValue (it may do things that should show up in
                        // the watches).
                        // Also, IValueBinder.SetValue could also take a long time (flushing large caches), and so it's
                        // useful to have watches still running.
                        await updateParameterLogTimer.StopAsync(cancellationToken);
                    }
                }
                finally
                {
                    ValueWatcher.AddLogs(watches, parameterLogCollector);
                }
            }
        }
コード例 #2
0
 public TriggeredFunctionInstanceFactory(ITriggeredFunctionBinding <TTriggerValue> binding,
                                         IFunctionInvoker invoker, FunctionDescriptor descriptor)
 {
     _binding    = binding;
     _invoker    = invoker;
     _descriptor = descriptor;
 }
コード例 #3
0
        public void InvokeAsync_DelegatesToInstanceFactoryAndMethodInvoker()
        {
            // Arrange
            object expectedInstance = new object();

            object[] expectedArguments = new object[0];

            Mock <IFactory <object> > instanceFactoryMock = new Mock <IFactory <object> >(MockBehavior.Strict);

            instanceFactoryMock.Setup(f => f.Create())
            .Returns(expectedInstance)
            .Verifiable();
            IFactory <object> instanceFactory = instanceFactoryMock.Object;

            Mock <IMethodInvoker <object> > methodInvokerMock = new Mock <IMethodInvoker <object> >(MockBehavior.Strict);

            methodInvokerMock.Setup(i => i.InvokeAsync(expectedInstance, expectedArguments))
            .Returns(Task.FromResult(0))
            .Verifiable();
            IMethodInvoker <object> methodInvoker = methodInvokerMock.Object;

            IFunctionInvoker product = CreateProductUnderTest(instanceFactory, methodInvoker);

            // Act
            product.InvokeAsync(expectedArguments).GetAwaiter().GetResult();

            // Assert
            instanceFactoryMock.VerifyAll();
            methodInvokerMock.VerifyAll();
        }
コード例 #4
0
 public FunctionInstanceFactory(IFunctionBinding binding, IFunctionInvoker invoker,
                                FunctionDescriptor descriptor)
 {
     _binding    = binding;
     _invoker    = invoker;
     _descriptor = descriptor;
 }
コード例 #5
0
        public virtual bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            if (functionMetadata == null)
            {
                throw new InvalidOperationException("functionMetadata");
            }

            functionDescriptor = null;

            // Default the trigger binding name if a name hasn't
            // been specified
            // TODO: Remove this logic and always require it to be explicitly
            // specified?
            foreach (var binding in functionMetadata.Bindings.Where(p => p.IsTrigger))
            {
                if (string.IsNullOrEmpty(binding.Name))
                {
                    if (binding.Type == BindingType.HttpTrigger)
                    {
                        binding.Name = DefaultHttpInputParameterName;
                    }
                    else
                    {
                        binding.Name = DefaultInputParameterName;
                    }
                }
            }

            // parse the bindings
            Collection <FunctionBinding> inputBindings  = FunctionBinding.GetBindings(Config, functionMetadata.InputBindings, FileAccess.Read);
            Collection <FunctionBinding> outputBindings = FunctionBinding.GetBindings(Config, functionMetadata.OutputBindings, FileAccess.Write);

            BindingMetadata triggerMetadata = functionMetadata.InputBindings.FirstOrDefault(p => p.IsTrigger);

            string scriptFilePath = Path.Combine(Config.RootScriptPath, functionMetadata.ScriptFile);

            IFunctionInvoker invoker = null;

            try
            {
                invoker = CreateFunctionInvoker(scriptFilePath, triggerMetadata, functionMetadata, inputBindings, outputBindings);

                Collection <CustomAttributeBuilder> methodAttributes = new Collection <CustomAttributeBuilder>();
                Collection <ParameterDescriptor>    parameters       = GetFunctionParameters(invoker, functionMetadata, triggerMetadata, methodAttributes, inputBindings, outputBindings);

                functionDescriptor = new FunctionDescriptor(functionMetadata.Name, invoker, functionMetadata, parameters, methodAttributes);

                return(true);
            }
            catch (Exception)
            {
                IDisposable disposableInvoker = invoker as IDisposable;
                if (disposableInvoker != null)
                {
                    disposableInvoker.Dispose();
                }

                throw;
            }
        }
コード例 #6
0
        internal static async Task InvokeAsync(IFunctionInvoker invoker, object[] invokeParameters, CancellationTokenSource timeoutTokenSource,
                                               CancellationTokenSource functionCancellationTokenSource, bool throwOnTimeout, TimeSpan timerInterval, IFunctionInstance instance)
        {
            // There are three ways the function can complete:
            //   1. The invokeTask itself completes first.
            //   2. A cancellation is requested (by host.Stop(), for example).
            //      a. Continue waiting for the invokeTask to complete. Either #1 or #3 will occur.
            //   3. A timeout fires.
            //      a. If throwOnTimeout, we throw the FunctionTimeoutException.
            //      b. If !throwOnTimeout, wait for the task to complete.

            // Start the invokeTask.
            Task invokeTask = invoker.InvokeAsync(invokeParameters);

            // A task that will throw a TaskCanceledException if #2 occurs.
            Task shutdownTask = Task.Delay(-1, functionCancellationTokenSource.Token);

            // A task that will throw when either #1 or #2 occurs.
            Task <Task> invokeOrShutdownTask = Task.WhenAny(invokeTask, shutdownTask);

            // Combine #1 and #2 with a timeout task (handled by this method).
            bool isTimeout = await TryHandleTimeoutAsync(invokeOrShutdownTask, throwOnTimeout, timeoutTokenSource.Token,
                                                         timerInterval, instance, () => functionCancellationTokenSource.Cancel());

            // #2 occurred. If we're going to throwOnTimeout, watch for a timeout while we wait for invokeTask to complete.
            if (throwOnTimeout && !isTimeout && invokeOrShutdownTask.Result == shutdownTask)
            {
                await TryHandleTimeoutAsync(invokeTask, throwOnTimeout, timeoutTokenSource.Token, timerInterval, instance, null);
            }

            await invokeTask;
        }
コード例 #7
0
        internal static async Task InvokeAsync(IFunctionInvoker invoker, object[] invokeParameters, CancellationTokenSource timeoutTokenSource,
                                               CancellationTokenSource functionCancellationTokenSource, bool throwOnTimeout, TimeSpan timerInterval, IFunctionInstance instance)
        {
            // There are three ways the function can complete:
            //   1. The invokeTask itself completes first.
            //   2. A cancellation is requested (by host.Stop(), for example).
            //      a. Continue waiting for the invokeTask to complete. Either #1 or #3 will occur.
            //   3. A timeout fires.
            //      a. If throwOnTimeout, we throw the FunctionTimeoutException.
            //      b. If !throwOnTimeout, wait for the task to complete.

            // Start the invokeTask.
            Task invokeTask = invoker.InvokeAsync(invokeParameters);

            // Combine #1 and #2 with a timeout task (handled by this method).
            // functionCancellationTokenSource.Token is passed to each function that requests it, so we need to call Cancel() on it
            // if there is a timeout.
            bool isTimeout = await TryHandleTimeoutAsync(invokeTask, functionCancellationTokenSource.Token, throwOnTimeout, timeoutTokenSource.Token,
                                                         timerInterval, instance, () => functionCancellationTokenSource.Cancel());

            // #2 occurred. If we're going to throwOnTimeout, watch for a timeout while we wait for invokeTask to complete.
            if (throwOnTimeout && !isTimeout && functionCancellationTokenSource.IsCancellationRequested)
            {
                await TryHandleTimeoutAsync(invokeTask, CancellationToken.None, throwOnTimeout, timeoutTokenSource.Token, timerInterval, instance, null);
            }

            await invokeTask;
        }
コード例 #8
0
        public void InvokeAsync_IfInstanceIsDisposable_DoesNotDisposeWhileTaskIsRunning()
        {
            // Arrange
            bool disposed = false;

            Mock <IDisposable> disposableMock = new Mock <IDisposable>(MockBehavior.Strict);

            disposableMock.Setup(d => d.Dispose()).Callback(() => { disposed = true; });
            IDisposable disposable = disposableMock.Object;

            IFactory <object>             instanceFactory = CreateStubFactory(disposable);
            TaskCompletionSource <object> taskSource      = new TaskCompletionSource <object>();
            IMethodInvoker <object>       methodInvoker   = CreateStubMethodInvoker(taskSource.Task);

            IFunctionInvoker product = CreateProductUnderTest(instanceFactory, methodInvoker);

            object[] arguments = new object[0];

            // Act
            Task task = product.InvokeAsync(arguments);

            // Assert
            Assert.NotNull(task);
            Assert.False(disposed);
            taskSource.SetResult(null);
            task.GetAwaiter().GetResult();
        }
コード例 #9
0
 public FunctionInstance(Guid id, Guid? parentId, ExecutionReason reason, IBindingSource bindingSource,
     IFunctionInvoker invoker, FunctionDescriptor functionDescriptor)
 {
     _id = id;
     _parentId = parentId;
     _reason = reason;
     _bindingSource = bindingSource;
     _invoker = invoker;
     _functionDescriptor = functionDescriptor;
 }
コード例 #10
0
 public FunctionInstance(Guid id, Guid?parentId, ExecutionReason reason, IBindingSource bindingSource,
                         IFunctionInvoker invoker, FunctionDescriptor functionDescriptor)
 {
     _id                 = id;
     _parentId           = parentId;
     _reason             = reason;
     _bindingSource      = bindingSource;
     _invoker            = invoker;
     _functionDescriptor = functionDescriptor;
 }
コード例 #11
0
        private static FunctionDefinition CreateTriggeredFunctionDefinitionImpl <TTriggerValue>(
            ITriggerBinding triggerBinding, string parameterName, IFunctionExecutor executor, FunctionDescriptor descriptor,
            IReadOnlyDictionary <string, IBinding> nonTriggerBindings, IFunctionInvoker invoker, SingletonManager singletonManager)
        {
            ITriggeredFunctionBinding <TTriggerValue>         functionBinding = new TriggeredFunctionBinding <TTriggerValue>(descriptor, parameterName, triggerBinding, nonTriggerBindings, singletonManager);
            ITriggeredFunctionInstanceFactory <TTriggerValue> instanceFactory = new TriggeredFunctionInstanceFactory <TTriggerValue>(functionBinding, invoker, descriptor);
            ITriggeredFunctionExecutor triggerExecutor = new TriggeredFunctionExecutor <TTriggerValue>(descriptor, executor, instanceFactory);
            IListenerFactory           listenerFactory = new ListenerFactory(descriptor, triggerExecutor, triggerBinding);

            return(new FunctionDefinition(descriptor, instanceFactory, listenerFactory));
        }
コード例 #12
0
        public void Create_ReturnsFunctionInvoker()
        {
            // Arrange
            _functionMethod = GetMethodInfo(nameof(DefaultFunctionInvokerFactoryTests.StaticReturnVoid));

            // Act
            IFunctionInvoker invoker = _invokerFactory.Create(new TestFunctionDefinition());

            // Assert
            Assert.IsType <DefaultFunctionInvoker <DefaultFunctionInvokerFactoryTests, object> >(invoker);
        }
コード例 #13
0
 public FunctionDescriptor(
     string name, 
     IFunctionInvoker invoker, 
     Collection<ParameterDescriptor> parameters, 
     Collection<CustomAttributeBuilder> attributes)
 {
     Name = name;
     Invoker = invoker;
     Parameters = parameters;
     CustomAttributes = attributes;
 }
コード例 #14
0
 public FunctionInstance(Guid id, IDictionary <string, string> triggerDetails, Guid?parentId, ExecutionReason reason, IBindingSource bindingSource,
                         IFunctionInvoker invoker, FunctionDescriptor functionDescriptor)
 {
     _id                 = id;
     _triggerDetails     = triggerDetails;
     _parentId           = parentId;
     _reason             = reason;
     _bindingSource      = bindingSource;
     _invoker            = invoker;
     _functionDescriptor = functionDescriptor;
 }
コード例 #15
0
        internal static async Task ExecuteWithWatchersAsync(IFunctionInvoker invoker,
                                                            IReadOnlyDictionary <string, IValueProvider> parameters,
                                                            TextWriter consoleOutput,
                                                            CancellationToken cancellationToken)
        {
            IReadOnlyList <string> parameterNames = invoker.ParameterNames;
            IDelayedException      delayedBindingException;

            object[] invokeParameters = PrepareParameters(parameterNames, parameters, out delayedBindingException);

            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();
            }

            // Cancellation token is provide by invokeParameters (if the method binds to CancellationToken).
            await invoker.InvokeAsync(invokeParameters);

            // Process any out parameters and persist any pending values.

            // Ensure IValueBinder.SetValue is called in BindOrder. 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, cancellationToken);
                    }
                    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);
                    }
                }
            }
        }
コード例 #16
0
        public void Create_ReturnsFunctionInvoker()
        {
            // Arrange
            MethodInfo    method    = GetMethodInfo("StaticReturnVoid");
            IJobActivator activator = CreateDummyActivator();

            // Act
            IFunctionInvoker invoker = FunctionInvokerFactory.Create(method, activator);

            // Assert
            Assert.IsType <FunctionInvoker <FunctionInvokerFactoryTests, object> >(invoker);
        }
コード例 #17
0
 public FunctionDescriptor(
     string name,
     IFunctionInvoker invoker,
     FunctionMetadata metadata,
     Collection <ParameterDescriptor> parameters,
     Collection <CustomAttributeBuilder> attributes)
 {
     Name             = name;
     Invoker          = invoker;
     Parameters       = parameters;
     CustomAttributes = attributes;
     Metadata         = metadata;
 }
コード例 #18
0
        public void Create_IfMultipleParameters_ReturnsParameterNames()
        {
            // Arrange
            MethodInfo    method    = GetMethodInfo("ParametersFooBarBaz");
            IJobActivator activator = CreateDummyActivator();

            // Act
            IFunctionInvoker invoker = FunctionInvokerFactory.Create(method, activator);

            // Assert
            Assert.NotNull(invoker);
            Assert.Equal((IEnumerable <string>) new string[] { "foo", "bar", "baz" }, invoker.ParameterNames);
        }
コード例 #19
0
        public void Create_IfNoParameters_ReturnsEmptyParameterNames()
        {
            // Arrange
            MethodInfo    method    = GetMethodInfo("NoParameters");
            IJobActivator activator = CreateDummyActivator();

            // Act
            IFunctionInvoker invoker = FunctionInvokerFactory.Create(method, activator);

            // Assert
            Assert.NotNull(invoker);
            Assert.Equal(Enumerable.Empty <string>(), invoker.ParameterNames);
        }
コード例 #20
0
        public IFunctionDefinition CreateFunctionDefinition(IReadOnlyDictionary <string, IBinding> nonTriggerBindings,
                                                            IFunctionInvoker invoker, FunctionDescriptor functionDescriptor)
        {
            ITriggeredFunctionBinding <IStorageQueueMessage> functionBinding =
                new TriggeredFunctionBinding <IStorageQueueMessage>(_parameterName, this, nonTriggerBindings);
            ITriggeredFunctionInstanceFactory <IStorageQueueMessage> instanceFactory =
                new TriggeredFunctionInstanceFactory <IStorageQueueMessage>(functionBinding, invoker,
                                                                            functionDescriptor);
            IListenerFactory listenerFactory = new QueueListenerFactory(_queue, _queueConfiguration,
                                                                        _backgroundExceptionDispatcher, _messageEnqueuedWatcherSetter, _sharedContextProvider, _log,
                                                                        instanceFactory);

            return(new FunctionDefinition(instanceFactory, listenerFactory));
        }
コード例 #21
0
ファイル: SCFHost.cs プロジェクト: xiawei666/findjobtclooud
        /// <summary>
        /// Initializes a new instance of the <see cref="SCFHost"/> class using the configuration provided.
        /// </summary>
        /// <param name="configuration">The job host configuration.</param>
        public SCFHost(IOptions <SCFHostOptions> options, IFunctionInvoker invoker, ILogger <SCFHost> logger, IHttpClientFactory httpFactory)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            _httpFactory         = httpFactory;
            _options             = options.Value;
            _logger              = logger;
            _functionInvoker     = invoker;
            _shutdownTokenSource = new CancellationTokenSource();
            _stoppingTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_shutdownTokenSource.Token);
        }
コード例 #22
0
        public void Create_IfInstance_UsesActivatorInstanceFactory()
        {
            // Arrange
            _functionMethod = GetMethodInfo(nameof(DefaultFunctionInvokerFactoryTests.InstanceReturnVoid));

            // Act
            IFunctionInvoker invoker = _invokerFactory.Create(new TestFunctionDefinition());

            // Assert
            Assert.IsType <DefaultFunctionInvoker <DefaultFunctionInvokerFactoryTests, object> >(invoker);
            var typedInvoker = (DefaultFunctionInvoker <DefaultFunctionInvokerFactoryTests, object>)invoker;

            Assert.IsType <DefaultFunctionActivator>(typedInvoker.FunctionActivator);
        }
コード例 #23
0
        public void Create_IfInstanceAndMethodIsInherited_UsesReflectedType()
        {
            // Arrange
            _functionMethod = GetMethodInfo(typeof(Subclass), nameof(Subclass.InheritedReturnVoid));

            // Act
            IFunctionInvoker invoker = _invokerFactory.Create(new TestFunctionDefinition());

            // Assert
            Assert.IsType <DefaultFunctionInvoker <Subclass, object> >(invoker);
            var typedInvoker = (DefaultFunctionInvoker <Subclass, object>)invoker;

            Assert.IsType <DefaultFunctionActivator>(typedInvoker.FunctionActivator);
        }
コード例 #24
0
        public IFunctionDefinition CreateFunctionDefinition(IReadOnlyDictionary <string, IBinding> nonTriggerBindings,
                                                            IFunctionInvoker invoker, FunctionDescriptor functionDescriptor)
        {
            ITriggeredFunctionBinding <IStorageBlob> functionBinding =
                new TriggeredFunctionBinding <IStorageBlob>(_parameterName, this, nonTriggerBindings);
            ITriggeredFunctionInstanceFactory <IStorageBlob> instanceFactory =
                new TriggeredFunctionInstanceFactory <IStorageBlob>(functionBinding, invoker, functionDescriptor);
            IStorageBlobContainer container       = _client.GetContainerReference(_path.ContainerNamePattern);
            IListenerFactory      listenerFactory = new BlobListenerFactory(_hostIdProvider, _queueConfiguration,
                                                                            _backgroundExceptionDispatcher, _blobWrittenWatcherSetter, _messageEnqueuedWatcherSetter,
                                                                            _sharedContextProvider, _log, functionDescriptor.Id, _account, container, _path, instanceFactory);

            return(new FunctionDefinition(instanceFactory, listenerFactory));
        }
コード例 #25
0
        public void Create_IfInstanceAndMethodIsInherited_UsesReflectedType()
        {
            // Arrange
            MethodInfo    method    = GetMethodInfo(typeof(Subclass), "InheritedReturnVoid");
            IJobActivator activator = CreateDummyActivator();

            // Act
            IFunctionInvoker invoker = FunctionInvokerFactory.Create(method, activator);

            // Assert
            Assert.IsType <FunctionInvoker <Subclass, object> >(invoker);
            FunctionInvoker <Subclass, object> typedInvoker = (FunctionInvoker <Subclass, object>)invoker;

            Assert.IsType <ActivatorInstanceFactory <Subclass> >(typedInvoker.InstanceFactory);
        }
コード例 #26
0
        public void Create_IfStatic_UsesNullInstanceFactory()
        {
            // Arrange
            MethodInfo    method    = GetMethodInfo("StaticReturnVoid");
            IJobActivator activator = CreateDummyActivator();

            // Act
            IFunctionInvoker invoker = FunctionInvokerFactory.Create(method, activator);

            // Assert
            Assert.IsType <FunctionInvoker <FunctionInvokerFactoryTests, object> >(invoker);
            FunctionInvoker <FunctionInvokerFactoryTests, object> typedInvoker =
                (FunctionInvoker <FunctionInvokerFactoryTests, object>)invoker;

            Assert.IsType <NullInstanceFactory <FunctionInvokerFactoryTests> >(typedInvoker.InstanceFactory);
        }
        public void Create_ReturnsFunctionInvoker()
        {
            // Arrange
            MethodInfo method = GetMethodInfo(nameof(DefaultFunctionInvokerFactoryTests.StaticReturnVoid));

            IMethodInvokerFactory methodInvokerFactory = CreateMethodInvokerFactory();
            IFunctionActivator    activator            = CreateDummyActivator();

            IFunctionInvokerFactory _invokerFactory = new DefaultFunctionInvokerFactory(methodInvokerFactory, activator);

            // Act
            IFunctionInvoker invoker = _invokerFactory.Create(method);

            // Assert
            Assert.IsType <DefaultFunctionInvoker <DefaultFunctionInvokerFactoryTests, object> >(invoker);
        }
コード例 #28
0
        private async Task ExecuteWithLoggingAsync(IFunctionInstance instance,
                                                   IReadOnlyDictionary <string, IValueProvider> parameters,
                                                   TraceWriter trace,
                                                   ILogger logger,
                                                   IFunctionOutputDefinition outputDefinition,
                                                   IDictionary <string, ParameterLog> parameterLogCollector,
                                                   TraceLevel functionTraceLevel,
                                                   CancellationTokenSource functionCancellationTokenSource)
        {
            IFunctionInvoker invoker = instance.Invoker;

            IReadOnlyDictionary <string, IWatcher> parameterWatchers = null;
            ITaskSeriesTimer updateParameterLogTimer = null;

            if (functionTraceLevel >= TraceLevel.Info)
            {
                parameterWatchers = CreateParameterWatchers(parameters);
                IRecurrentCommand updateParameterLogCommand = outputDefinition.CreateParameterLogUpdateCommand(parameterWatchers, trace, logger);
                updateParameterLogTimer = StartParameterLogTimer(updateParameterLogCommand, _exceptionHandler);
            }

            try
            {
                await ExecuteWithWatchersAsync(instance, parameters, trace, logger, functionCancellationTokenSource);

                if (updateParameterLogTimer != null)
                {
                    // Stop the watches after calling IValueBinder.SetValue (it may do things that should show up in
                    // the watches).
                    // Also, IValueBinder.SetValue could also take a long time (flushing large caches), and so it's
                    // useful to have watches still running.
                    await updateParameterLogTimer.StopAsync(functionCancellationTokenSource.Token);
                }
            }
            finally
            {
                if (updateParameterLogTimer != null)
                {
                    ((IDisposable)updateParameterLogTimer).Dispose();
                }

                if (parameterWatchers != null)
                {
                    ValueWatcher.AddLogs(parameterWatchers, parameterLogCollector);
                }
            }
        }
コード例 #29
0
 public FunctionDescriptor(
     string name,
     IFunctionInvoker invoker,
     FunctionMetadata metadata,
     Collection <ParameterDescriptor> parameters,
     Collection <CustomAttributeBuilder> attributes,
     Collection <FunctionBinding> inputBindings,
     Collection <FunctionBinding> outputBindings)
 {
     Name             = name;
     Invoker          = invoker;
     Parameters       = parameters;
     CustomAttributes = attributes;
     Metadata         = metadata;
     InputBindings    = inputBindings;
     OutputBindings   = outputBindings;
 }
コード例 #30
0
        public virtual bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            if (functionMetadata == null)
            {
                throw new InvalidOperationException("functionMetadata");
            }

            ValidateFunction(functionMetadata);

            // parse the bindings
            Collection <FunctionBinding> inputBindings  = FunctionBinding.GetBindings(Config, BindingProviders, functionMetadata.InputBindings, FileAccess.Read);
            Collection <FunctionBinding> outputBindings = FunctionBinding.GetBindings(Config, BindingProviders, functionMetadata.OutputBindings, FileAccess.Write);

            VerifyResolvedBindings(functionMetadata, inputBindings, outputBindings);

            BindingMetadata triggerMetadata = functionMetadata.InputBindings.FirstOrDefault(p => p.IsTrigger);
            string          scriptFilePath  = Path.Combine(Config.RootScriptPath, functionMetadata.ScriptFile ?? string.Empty);

            functionDescriptor = null;
            IFunctionInvoker invoker = null;

            try
            {
                invoker = CreateFunctionInvoker(scriptFilePath, triggerMetadata, functionMetadata, inputBindings, outputBindings);

                Collection <CustomAttributeBuilder> methodAttributes = new Collection <CustomAttributeBuilder>();
                Collection <ParameterDescriptor>    parameters       = GetFunctionParameters(invoker, functionMetadata, triggerMetadata, methodAttributes, inputBindings, outputBindings);

                functionDescriptor = new FunctionDescriptor(functionMetadata.Name, invoker, functionMetadata, parameters, methodAttributes, inputBindings, outputBindings);

                return(true);
            }
            catch (Exception ex)
            {
                Host.Logger.LogTrace(ex, $"Creating function descriptor for function {functionMetadata.Name} failed");
                IDisposable disposableInvoker = invoker as IDisposable;
                if (disposableInvoker != null)
                {
                    disposableInvoker.Dispose();
                }

                throw;
            }
        }
        public void Create_IfInstanceAndMethodIsInherited_UsesReflectedType()
        {
            // Arrange
            MethodInfo method = GetMethodInfo(typeof(Subclass), nameof(Subclass.InheritedReturnVoid));

            IMethodInvokerFactory methodInvokerFactory = CreateMethodInvokerFactory();
            IFunctionActivator    activator            = new DefaultFunctionActivator();

            IFunctionInvokerFactory _invokerFactory = new DefaultFunctionInvokerFactory(methodInvokerFactory, activator);

            // Act
            IFunctionInvoker invoker = _invokerFactory.Create(method);

            // Assert
            Assert.IsType <DefaultFunctionInvoker <Subclass, object> >(invoker);
            var typedInvoker = (DefaultFunctionInvoker <Subclass, object>)invoker;

            Assert.IsType <DefaultFunctionActivator>(typedInvoker.FunctionActivator);
        }
        public void Create_IfInstance_UsesActivatorInstanceFactory()
        {
            // Arrange
            MethodInfo method = GetMethodInfo(nameof(DefaultFunctionInvokerFactoryTests.InstanceReturnVoid));

            IMethodInvokerFactory methodInvokerFactory = CreateMethodInvokerFactory();
            IFunctionActivator    activator            = new DefaultFunctionActivator();

            IFunctionInvokerFactory _invokerFactory = new DefaultFunctionInvokerFactory(methodInvokerFactory, activator);

            // Act
            IFunctionInvoker invoker = _invokerFactory.Create(method);

            // Assert
            Assert.IsType <DefaultFunctionInvoker <DefaultFunctionInvokerFactoryTests, object> >(invoker);
            var typedInvoker = (DefaultFunctionInvoker <DefaultFunctionInvokerFactoryTests, object>)invoker;

            Assert.IsType <DefaultFunctionActivator>(typedInvoker.FunctionActivator);
        }
コード例 #33
0
        protected virtual Collection<ParameterDescriptor> GetFunctionParameters(IFunctionInvoker functionInvoker, FunctionMetadata functionMetadata,
            BindingMetadata triggerMetadata, Collection<CustomAttributeBuilder> methodAttributes, Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings)
        {
            if (functionInvoker == null)
            {
                throw new ArgumentNullException("functionInvoker");
            }
            if (functionMetadata == null)
            {
                throw new ArgumentNullException("functionMetadata");
            }
            if (triggerMetadata == null)
            {
                throw new ArgumentNullException("triggerMetadata");
            }
            if (methodAttributes == null)
            {
                throw new ArgumentNullException("methodAttributes");
            }

            ApplyMethodLevelAttributes(functionMetadata, triggerMetadata, methodAttributes);

            Collection<ParameterDescriptor> parameters = new Collection<ParameterDescriptor>();
            ParameterDescriptor triggerParameter = CreateTriggerParameter(triggerMetadata);
            parameters.Add(triggerParameter);

            // Add a TraceWriter for logging
            parameters.Add(new ParameterDescriptor(ScriptConstants.SystemLogParameterName, typeof(TraceWriter)));

            // Add an IBinder to support the binding programming model
            parameters.Add(new ParameterDescriptor(ScriptConstants.SystemBinderParameterName, typeof(IBinder)));

            // Add ExecutionContext to provide access to InvocationId, etc.
            parameters.Add(new ParameterDescriptor(ScriptConstants.SystemExecutionContextParameterName, typeof(ExecutionContext)));

            return parameters;
        }
        protected virtual Collection<ParameterDescriptor> GetFunctionParameters(IFunctionInvoker functionInvoker, FunctionMetadata functionMetadata, 
            BindingMetadata triggerMetadata, Collection<CustomAttributeBuilder> methodAttributes, Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings)
        {
            if (functionInvoker == null)
            {
                throw new ArgumentNullException("functionInvoker");
            }
            if (functionMetadata == null)
            {
                throw new ArgumentNullException("functionMetadata");
            }
            if (triggerMetadata == null)
            {
                throw new ArgumentNullException("triggerMetadata");
            }
            if (methodAttributes == null)
            {
                throw new ArgumentNullException("methodAttributes");
            }

            ParameterDescriptor triggerParameter = null;
            switch (triggerMetadata.Type)
            {
                case BindingType.QueueTrigger:
                    triggerParameter = ParseQueueTrigger((QueueBindingMetadata)triggerMetadata);
                    break;
                case BindingType.EventHubTrigger:
                    triggerParameter = ParseEventHubTrigger((EventHubBindingMetadata)triggerMetadata);
                    break;
                case BindingType.BlobTrigger:
                    triggerParameter = ParseBlobTrigger((BlobBindingMetadata)triggerMetadata, typeof(Stream));
                    break;
                case BindingType.ServiceBusTrigger:
                    triggerParameter = ParseServiceBusTrigger((ServiceBusBindingMetadata)triggerMetadata);
                    break;
                case BindingType.TimerTrigger:
                    triggerParameter = ParseTimerTrigger((TimerBindingMetadata)triggerMetadata, typeof(TimerInfo));
                    break;
                case BindingType.HttpTrigger:
                    triggerParameter = ParseHttpTrigger((HttpTriggerBindingMetadata)triggerMetadata, typeof(HttpRequestMessage));
                    break;
                case BindingType.ManualTrigger:
                    triggerParameter = ParseManualTrigger(triggerMetadata);
                    break;
                case BindingType.ApiHubTrigger:
                    triggerParameter = ParseApiHubTrigger((ApiHubBindingMetadata)triggerMetadata, typeof(Stream));
                    break;
            }

            ApplyMethodLevelAttributes(functionMetadata, triggerMetadata, methodAttributes);

            Collection<ParameterDescriptor> parameters = new Collection<ParameterDescriptor>();
            triggerParameter.IsTrigger = true;
            parameters.Add(triggerParameter);

            // Add a TraceWriter for logging
            parameters.Add(new ParameterDescriptor("log", typeof(TraceWriter)));

            // Add an IBinder to support the binding programming model
            parameters.Add(new ParameterDescriptor("binder", typeof(IBinder)));

            // Add ExecutionContext to provide access to InvocationId, etc.
            parameters.Add(new ParameterDescriptor("context", typeof(ExecutionContext)));

            return parameters;
        }
        protected override Collection<ParameterDescriptor> GetFunctionParameters(IFunctionInvoker functionInvoker, FunctionMetadata functionMetadata,
            BindingMetadata triggerMetadata, Collection<CustomAttributeBuilder> methodAttributes, Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings)
        {
            if (functionInvoker == null)
            {
                throw new ArgumentNullException("functionInvoker");
            }
            if (functionMetadata == null)
            {
                throw new ArgumentNullException("functionMetadata");
            }
            if (triggerMetadata == null)
            {
                throw new ArgumentNullException("triggerMetadata");
            }
            if (methodAttributes == null)
            {
                throw new ArgumentNullException("methodAttributes");
            }

            var dotNetInvoker = functionInvoker as DotNetFunctionInvoker;
            if (dotNetInvoker == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Expected invoker of type '{0}' but received '{1}'", typeof(DotNetFunctionInvoker).Name, functionInvoker.GetType().Name));
            }

            try
            {
                ApplyMethodLevelAttributes(functionMetadata, triggerMetadata, methodAttributes);

                MethodInfo functionTarget = dotNetInvoker.GetFunctionTargetAsync().Result;
                ParameterInfo[] parameters = functionTarget.GetParameters();
                Collection<ParameterDescriptor> descriptors = new Collection<ParameterDescriptor>();
                IEnumerable<FunctionBinding> bindings = inputBindings.Union(outputBindings);
                ParameterDescriptor descriptor = null;
                foreach (var parameter in parameters)
                {
                    // Is it the trigger parameter?
                    if (string.Compare(parameter.Name, triggerMetadata.Name, StringComparison.Ordinal) == 0)
                    {
                        ParameterDescriptor triggerParameter = CreateTriggerParameter(triggerMetadata, parameter.ParameterType);
                        descriptors.Add(triggerParameter);
                    }
                    else
                    {
                        Type parameterType = parameter.ParameterType;
                        bool parameterIsByRef = parameterType.IsByRef;
                        if (parameterIsByRef)
                        {
                            parameterType = parameterType.GetElementType();
                        }

                        descriptor = new ParameterDescriptor(parameter.Name, parameter.ParameterType);
                        var binding = bindings.FirstOrDefault(b => string.Compare(b.Metadata.Name, parameter.Name, StringComparison.Ordinal) == 0);
                        if (binding != null)
                        {
                            Collection<CustomAttributeBuilder> customAttributes = binding.GetCustomAttributes(parameter.ParameterType);
                            if (customAttributes != null)
                            {
                                foreach (var customAttribute in customAttributes)
                                {
                                    descriptor.CustomAttributes.Add(customAttribute);
                                }
                            }
                        }

                        // In the C# programming model, IsOut is set for out parameters
                        // In the F# programming model, neither IsOut nor IsIn are set for byref parameters (which are used as out parameters).
                        //   Justification for this cariation of the programming model is that declaring 'out' parameters is (deliberately)
                        //   awkward in F#, they require opening System.Runtime.InteropServices and adding the [<Out>] attribute, and using 
                        //   a byref parameter. In contrast declaring a byref parameter alone (neither labelled In nor Out) is simple enough.
                        if (parameter.IsOut || (functionMetadata.ScriptType == ScriptType.FSharp && parameterIsByRef && !parameter.IsIn))
                        {
                            descriptor.Attributes |= ParameterAttributes.Out;
                        }

                        descriptors.Add(descriptor);
                    }
                }

                // Add any additional required System parameters (if they haven't already been defined by the user)
                if (!descriptors.Any(p => p.Type == typeof(ExecutionContext)))
                {
                    // Add ExecutionContext to provide access to InvocationId, etc.
                    descriptors.Add(new ParameterDescriptor(ScriptConstants.SystemExecutionContextParameterName, typeof(ExecutionContext)));
                }

                // If we have an HTTP trigger binding but no parameter binds to the raw HttpRequestMessage,
                // add it as a system parameter so it is accessible later in the pipeline.
                if (string.Compare(triggerMetadata.Type, "httptrigger", StringComparison.OrdinalIgnoreCase) == 0 &&
                    !descriptors.Any(p => p.Type == typeof(HttpRequestMessage)))
                {
                    descriptors.Add(new ParameterDescriptor(ScriptConstants.SystemTriggerParameterName, typeof(HttpRequestMessage)));
                }

                if (TryCreateReturnValueParameterDescriptor(functionTarget.ReturnType, bindings, out descriptor))
                {
                    // If a return value binding has been specified, set up an output
                    // binding to map it to. By convention, this is set up as the last
                    // parameter.
                    descriptors.Add(descriptor);
                }

                return descriptors;
            }
            catch (AggregateException exc)
            {
                if (!(exc.InnerException is CompilationErrorException))
                {
                    throw;
                }
            }
            catch (CompilationErrorException)
            {
            }

            // We were unable to compile the function to get its signature,
            // setup the descriptor with the default parameters
            methodAttributes.Clear();
            return base.GetFunctionParameters(functionInvoker, functionMetadata, triggerMetadata, methodAttributes, inputBindings, outputBindings);
        }
コード例 #36
0
 public FunctionInstanceFactory(IFunctionBinding binding, IFunctionInvoker invoker, FunctionDescriptor descriptor)
 {
     _binding = binding;
     _invoker = invoker;
     _descriptor = descriptor;
 }
コード例 #37
0
 public FunctionDescriptor(string name, IFunctionInvoker invoker, FunctionMetadata metadata, Collection<ParameterDescriptor> parameters)
     : this(name, invoker, metadata, parameters, new Collection<CustomAttributeBuilder>())
 {
 }
        protected override Collection<ParameterDescriptor> GetFunctionParameters(IFunctionInvoker functionInvoker, FunctionMetadata functionMetadata,
            BindingMetadata triggerMetadata, Collection<CustomAttributeBuilder> methodAttributes, Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings)
        {
            if (functionInvoker == null)
            {
                throw new ArgumentNullException("functionInvoker");
            }
            if (functionMetadata == null)
            {
                throw new ArgumentNullException("functionMetadata");
            }
            if (triggerMetadata == null)
            {
                throw new ArgumentNullException("triggerMetadata");
            }
            if (methodAttributes == null)
            {
                throw new ArgumentNullException("methodAttributes");
            }

            var csharpInvoker = functionInvoker as CSharpFunctionInvoker;
            if (csharpInvoker == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Expected invoker of type '{0}' but received '{1}'", typeof(CSharpFunctionInvoker).Name, functionInvoker.GetType().Name));
            }

            try
            {
                ApplyMethodLevelAttributes(functionMetadata, triggerMetadata, methodAttributes);

                MethodInfo functionTarget = csharpInvoker.GetFunctionTargetAsync().Result;
                ParameterInfo[] parameters = functionTarget.GetParameters();
                Collection<ParameterDescriptor> descriptors = new Collection<ParameterDescriptor>();
                IEnumerable<FunctionBinding> bindings = inputBindings.Union(outputBindings);
                bool addHttpRequestSystemParameter = false;
                foreach (var parameter in parameters)
                {
                    // Is it the trigger parameter?
                    if (string.Compare(parameter.Name, triggerMetadata.Name, StringComparison.Ordinal) == 0)
                    {
                        descriptors.Add(CreateTriggerParameterDescriptor(parameter, triggerMetadata));

                        if (triggerMetadata.Type == BindingType.HttpTrigger && 
                            parameter.ParameterType != typeof(HttpRequestMessage))
                        {
                            addHttpRequestSystemParameter = true;
                        }
                    }
                    else
                    {
                        Type parameterType = parameter.ParameterType;
                        if (parameterType.IsByRef)
                        {
                            parameterType = parameterType.GetElementType();
                        }

                        var descriptor = new ParameterDescriptor(parameter.Name, parameter.ParameterType);
                        var binding = bindings.FirstOrDefault(b => string.Compare(b.Metadata.Name, parameter.Name, StringComparison.Ordinal) == 0);
                        if (binding != null)
                        {
                            Collection<CustomAttributeBuilder> customAttributes = binding.GetCustomAttributes();
                            if (customAttributes != null)
                            {
                                foreach (var customAttribute in customAttributes)
                                {
                                    descriptor.CustomAttributes.Add(customAttribute);
                                }
                            }
                        }

                        if (parameter.IsOut)
                        {
                            descriptor.Attributes |= ParameterAttributes.Out;
                        }

                        descriptors.Add(descriptor);
                    }
                }

                // Add any additional common System parameters
                // Add ExecutionContext to provide access to InvocationId, etc.
                descriptors.Add(new ParameterDescriptor("context", typeof(ExecutionContext)));
                
                // If we have an HTTP trigger binding but we're not binding
                // to the HttpRequestMessage, require it as a system parameter
                if (addHttpRequestSystemParameter)
                {
                    descriptors.Add(new ParameterDescriptor(ScriptConstants.DefaultSystemTriggerParameterName, typeof(HttpRequestMessage)));
                }

                return descriptors;
            }
            catch (AggregateException exc)
            {
                if (!(exc.InnerException is CompilationErrorException))
                {
                    throw;
                }
            }
            catch (CompilationErrorException)
            {
            }

            // We were unable to compile the function to get its signature,
            // setup the descriptor with the default parameters
            return base.GetFunctionParameters(functionInvoker, functionMetadata, triggerMetadata, methodAttributes, inputBindings, outputBindings);
        }