public async Task LogFunctionCompletedAsync_CallsTraceWriter()
        {
            FunctionDescriptor descriptor = new FunctionDescriptor
            {
                ShortName = "TestJob"
            };
            FunctionCompletedMessage successMessage = new FunctionCompletedMessage
            {
                Function = descriptor
            };

            Exception ex = new Exception("Kaboom!");
            FunctionCompletedMessage failureMessage = new FunctionCompletedMessage
            {
                Function = descriptor,
                Failure = new FunctionFailure { Exception = ex },
                FunctionInstanceId = new Guid("8d71c9e3-e809-4cfb-bb78-48ae25c7d26d")
            };

            _mockTraceWriter.Setup(p => p.Trace(TraceLevel.Info, Host.TraceSource.Execution, "Executed: 'TestJob' (Succeeded)", null));
            _mockTraceWriter.Setup(p => p.Trace(TraceLevel.Error, Host.TraceSource.Execution, "Executed: 'TestJob' (Failed)", ex));
            _mockTraceWriter.Setup(p => p.Trace(TraceLevel.Error, Host.TraceSource.Host, "  Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID is '8d71c9e3-e809-4cfb-bb78-48ae25c7d26d'", null));

            await _logger.LogFunctionCompletedAsync(successMessage, CancellationToken.None);
            await _logger.LogFunctionCompletedAsync(failureMessage, CancellationToken.None);

            _mockTraceWriter.VerifyAll();
        }
        private static async Task<Dictionary<string, object>> GetFunctionArgumentsAsync(FunctionDescriptor function, HttpRequestMessage request)
        {
            ParameterDescriptor triggerParameter = function.Parameters.First(p => p.IsTrigger);
            Dictionary<string, object> arguments = new Dictionary<string, object>();
            object triggerArgument = null;
            if (triggerParameter.Type == typeof(HttpRequestMessage))
            {
                triggerArgument = request;
            }
            else
            {
                // We'll replace the trigger argument but still want to flow the request
                // so add it to the arguments, as a system argument
                arguments.Add(ScriptConstants.DefaultSystemTriggerParameterName, request);

                HttpTriggerBindingMetadata httpFunctionMetadata = (HttpTriggerBindingMetadata)function.Metadata.InputBindings.FirstOrDefault(p => p.Type == BindingType.HttpTrigger);
                if (!string.IsNullOrEmpty(httpFunctionMetadata.WebHookType))
                {
                    WebHookHandlerContext webHookContext;
                    if (request.Properties.TryGetValue(ScriptConstants.AzureFunctionsWebHookContextKey, out webHookContext))
                    {
                        triggerArgument = GetWebHookData(triggerParameter.Type, webHookContext);
                    }
                }

                if (triggerArgument == null)
                {
                    triggerArgument = await request.Content.ReadAsAsync(triggerParameter.Type);
                }
            }

            arguments.Add(triggerParameter.Name, triggerArgument);

            return arguments;
        }
        public async Task CreateAsync_SkipsDisabledFunctions(Type jobType, string methodName)
        {
            Environment.SetEnvironmentVariable("EnvironmentSettingTrue", "True");

            Mock<IFunctionDefinition> mockFunctionDefinition = new Mock<IFunctionDefinition>();
            Mock<IFunctionInstanceFactory> mockInstanceFactory = new Mock<IFunctionInstanceFactory>(MockBehavior.Strict);
            Mock<IListenerFactory> mockListenerFactory = new Mock<IListenerFactory>(MockBehavior.Strict);
            SingletonManager singletonManager = new SingletonManager();
            TestTraceWriter traceWriter = new TestTraceWriter(TraceLevel.Verbose);

            // create a bunch of function definitions that are disabled
            List<FunctionDefinition> functions = new List<FunctionDefinition>();
            FunctionDescriptor descriptor = new FunctionDescriptor
            {
                Method = jobType.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static),
                ShortName = string.Format("{0}.{1}", jobType.Name, methodName)
            };
            FunctionDefinition definition = new FunctionDefinition(descriptor, mockInstanceFactory.Object, mockListenerFactory.Object);
            functions.Add(definition);

            // Create the composite listener - this will fail if any of the
            // function definitions indicate that they are not disabled
            HostListenerFactory factory = new HostListenerFactory(functions, singletonManager, DefaultJobActivator.Instance, null, traceWriter);
            IListener listener = await factory.CreateAsync(CancellationToken.None);

            Assert.Equal(1, traceWriter.Traces.Count);
            Assert.Equal(TraceLevel.Info, traceWriter.Traces[0].Level);
            Assert.Equal(TraceSource.Host, traceWriter.Traces[0].Source);
            Assert.Equal(string.Format("Function '{0}' is disabled", descriptor.ShortName), traceWriter.Traces[0].Message);

            Environment.SetEnvironmentVariable("EnvironmentSettingTrue", null);
        }
        public async Task<HttpResponseMessage> HandleRequestAsync(FunctionDescriptor function, HttpRequestMessage request, Func<HttpRequestMessage, Task<HttpResponseMessage>> invokeFunction)
        {
            // First check if there is a registered WebHook Receiver for this request, and if
            // so use it
            HttpTriggerBindingMetadata httpFunctionMetadata = (HttpTriggerBindingMetadata)function.Metadata.InputBindings.FirstOrDefault(p => p.Type == BindingType.HttpTrigger);
            string webHookReceiver = httpFunctionMetadata.WebHookType;
            IWebHookReceiver receiver = null;
            if (string.IsNullOrEmpty(webHookReceiver) || !_receiverLookup.TryGetValue(webHookReceiver, out receiver))
            {
                // The function is not correctly configured. Log an error and return 500
                string configurationError = string.Format(CultureInfo.InvariantCulture, "Invalid WebHook configuration. Unable to find a receiver for WebHook type '{0}'", webHookReceiver);
                function.Invoker.OnError(new FunctionInvocationException(configurationError));

                return new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);
            }

            HttpRequestContext context = new HttpRequestContext
            {
                Configuration = _httpConfiguration
            };
            request.SetConfiguration(_httpConfiguration);

            // add the anonymous handler function from above to the request properties
            // so our custom WebHookHandler can invoke it at the right time
            request.Properties.Add(AzureFunctionsCallbackKey, invokeFunction);

            // Request content can't be read multiple
            // times, so this forces it to buffer
            await request.Content.LoadIntoBufferAsync();

            string receiverId = function.Name.ToLowerInvariant();
            return await receiver.ReceiveAsync(receiverId, context, request);
        }
        public FunctionExecutorTests()
        {
            _descriptor = new FunctionDescriptor();
            _mockFunctionInstance = new Mock<IFunctionInstance>(MockBehavior.Strict);
            _mockFunctionInstance.Setup(p => p.FunctionDescriptor).Returns(_descriptor);

            _cancellationTokenSource = new CancellationTokenSource();
            _traceWriter = new TestTraceWriter(TraceLevel.Verbose);
        }
 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;
 }
        public void Add(IFunctionDefinition function, FunctionDescriptor descriptor, MethodInfo method)
        {
            string id = descriptor.Id;

            if (_functionsById.ContainsKey(id))
            {
                throw new InvalidOperationException("Method overloads are not supported. " +
                    "There are multiple methods with the name '" + id + "'.");
            }

            _functionsById.Add(id, function);
            _functionsByMethod.Add(method, function);
            _functionDescriptors.Add(descriptor);
        }
        public void FormatReason_BlobTriggeredFunction_ReturnsExpectedReason()
        {
            FunctionStartedMessage message = new FunctionStartedMessage();
            message.Reason = ExecutionReason.AutomaticTrigger;

            BlobTriggerParameterDescriptor triggerParameterDescriptor = new BlobTriggerParameterDescriptor
            {
                Name = "paramName"
            };
            FunctionDescriptor function = new FunctionDescriptor();
            function.Parameters = new ParameterDescriptor[] { triggerParameterDescriptor };
            message.Function = function;
            message.Arguments = new Dictionary<string, string>() { { "paramName", "blob/path" } };

            string result = message.FormatReason();
            Assert.Equal("New blob detected: blob/path", result);
        }
        public async Task Generate_EndToEnd()
        {
            // construct our TimerTrigger attribute ([TimerTrigger("00:00:02", RunOnStartup = true)])
            Collection<ParameterDescriptor> parameters = new Collection<ParameterDescriptor>();
            ParameterDescriptor parameter = new ParameterDescriptor("timerInfo", typeof(TimerInfo));
            ConstructorInfo ctorInfo = typeof(TimerTriggerAttribute).GetConstructor(new Type[] { typeof(string) });
            PropertyInfo runOnStartupProperty = typeof(TimerTriggerAttribute).GetProperty("RunOnStartup");
            CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(
                ctorInfo,
                new object[] { "00:00:02" },
                new PropertyInfo[] { runOnStartupProperty },
                new object[] { true });
            parameter.CustomAttributes.Add(attributeBuilder);
            parameters.Add(parameter);

            // create the FunctionDefinition
            FunctionMetadata metadata = new FunctionMetadata();
            TestInvoker invoker = new TestInvoker();
            FunctionDescriptor function = new FunctionDescriptor("TimerFunction", invoker, metadata, parameters);
            Collection<FunctionDescriptor> functions = new Collection<FunctionDescriptor>();
            functions.Add(function);

            // generate the Type
            Type functionType = FunctionGenerator.Generate("TestScriptHost", "TestFunctions", functions);

            // verify the generated function
            MethodInfo method = functionType.GetMethod("TimerFunction");
            ParameterInfo triggerParameter = method.GetParameters()[0];
            TimerTriggerAttribute triggerAttribute = triggerParameter.GetCustomAttribute<TimerTriggerAttribute>();
            Assert.NotNull(triggerAttribute);

            // start the JobHost which will start running the timer function
            JobHostConfiguration config = new JobHostConfiguration()
            {
                TypeLocator = new TypeLocator(functionType)
            };
            config.UseTimers();
            JobHost host = new JobHost(config);

            await host.StartAsync();
            await Task.Delay(3000);
            await host.StopAsync();

            // verify our custom invoker was called
            Assert.True(invoker.InvokeCount >= 2);
        }
Example #10
0
 public string GetFunctionGroupString(FunctionDescriptor.FunctionGroup grp)
 {
     switch (grp)
     {
         case FunctionDescriptor.FunctionGroup.NumberGroup:
             return StrRes.GetString(StrRes.STR_NUMBER_GROUP);
         case FunctionDescriptor.FunctionGroup.CoordinateGroup:
             return StrRes.GetString(StrRes.STR_COORDINATE_GROUP);
         case FunctionDescriptor.FunctionGroup.TextGroup:
             return StrRes.GetString(StrRes.STR_TEXT_GROUP);
         case FunctionDescriptor.FunctionGroup.ContextGroup:
             return StrRes.GetString(StrRes.STR_CONTEXT_GROUP);
         case FunctionDescriptor.FunctionGroup.TrigonometricGroup:
             return StrRes.GetString(StrRes.STR_TRIGONOMETRIC_GROUP);
         default:
             return StrRes.GetString(StrRes.STR_UNKNOWN_GROUP);
     }
 }
        public void FormatReason_QueueTriggeredFunction_ReturnsExpectedReason()
        {
            FunctionStartedMessage message = new FunctionStartedMessage();

            QueueTriggerParameterDescriptor triggerParameterDescriptor = new QueueTriggerParameterDescriptor
            {
                Name = "paramName",
                QueueName = "testqueue"
            };
            FunctionDescriptor function = new FunctionDescriptor
            {
                Parameters = new ParameterDescriptor[] { triggerParameterDescriptor }
            };
            message.Function = function;
            message.Reason = ExecutionReason.AutomaticTrigger;

            string result = message.FormatReason();
            Assert.Equal("New queue message detected on 'testqueue'.", result);
        }
        public async Task LogFunctionCompletedAsync_CallsTraceWriter()
        {
            FunctionDescriptor descriptor = new FunctionDescriptor
            {
                ShortName = "TestJob",
                FullName = "TestNamespace.TestJob"
            };
            FunctionCompletedMessage successMessage = new FunctionCompletedMessage
            {
                Function = descriptor,
                FunctionInstanceId = Guid.NewGuid()
            };

            Exception ex = new Exception("Kaboom!");
            FunctionCompletedMessage failureMessage = new FunctionCompletedMessage
            {
                Function = descriptor,
                Failure = new FunctionFailure { Exception = ex },
                FunctionInstanceId = new Guid("8d71c9e3-e809-4cfb-bb78-48ae25c7d26d")
            };

            await _logger.LogFunctionCompletedAsync(successMessage, CancellationToken.None);
            await _logger.LogFunctionCompletedAsync(failureMessage, CancellationToken.None);

            Assert.Equal(3, _traceWriter.Traces.Count);

            TraceEvent traceEvent = _traceWriter.Traces[0];
            Assert.Equal(TraceLevel.Info, traceEvent.Level);
            Assert.Equal(Host.TraceSource.Execution, traceEvent.Source);
            Assert.Equal("Executed: 'TestJob' (Succeeded)", traceEvent.Message);

            traceEvent = _traceWriter.Traces[1];
            Assert.Equal(TraceLevel.Error, traceEvent.Level);
            Assert.Equal(Host.TraceSource.Execution, traceEvent.Source);
            Assert.Equal("Executed: 'TestJob' (Failed)", traceEvent.Message);
            Assert.Same(ex, traceEvent.Exception);

            traceEvent = _traceWriter.Traces[2];
            Assert.Equal(TraceLevel.Error, traceEvent.Level);
            Assert.Equal(Host.TraceSource.Host, traceEvent.Source);
            Assert.Equal("  Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID is '8d71c9e3-e809-4cfb-bb78-48ae25c7d26d'", traceEvent.Message);
            Assert.Same(ex, traceEvent.Exception);
        }
        public async Task<HttpResponseMessage> HandleRequestAsync(FunctionDescriptor function, HttpRequestMessage request, CancellationToken cancellationToken)
        {
            // All authentication is assumed to have been done on the request
            // BEFORE this method is called

            // Invoke the function
            ParameterDescriptor triggerParameter = function.Parameters.First(p => p.IsTrigger);
            Dictionary<string, object> arguments = new Dictionary<string, object>
            {
                { triggerParameter.Name, request }
            };
            await Instance.CallAsync(function.Name, arguments, cancellationToken);

            // Get the response
            HttpResponseMessage response = null;
            if (!request.Properties.TryGetValue<HttpResponseMessage>("MS_AzureFunctionsHttpResponse", out response))
            {
                // the function was successful but did not write an explicit response
                response = new HttpResponseMessage(HttpStatusCode.OK);
            }

            return response;
        }
        public async Task<HttpResponseMessage> HandleRequestAsync(FunctionDescriptor function, HttpRequestMessage request, CancellationToken cancellationToken)
        {
            // All authentication is assumed to have been done on the request
            // BEFORE this method is called

            Dictionary<string, object> arguments = await GetFunctionArgumentsAsync(function, request);

            // Suspend the current synchronization context so we don't pass the ASP.NET
            // context down to the function.
            using (var syncContextSuspensionScope = new SuspendedSynchronizationContextScope())
            {
                await Instance.CallAsync(function.Name, arguments, cancellationToken);
            }

            // Get the response
            HttpResponseMessage response = null;
            if (!request.Properties.TryGetValue<HttpResponseMessage>("MS_AzureFunctionsHttpResponse", out response))
            {
                // the function was successful but did not write an explicit response
                response = new HttpResponseMessage(HttpStatusCode.OK);
            }

            return response;
        }
Example #15
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="DSVarArgFunction"/> class.
 /// </summary>
 /// <param name="descriptor">Function descritor.</param>
 public DSVarArgFunction(FunctionDescriptor descriptor)
     : base(new ZeroTouchVarArgNodeController <FunctionDescriptor>(descriptor))
 {
     VarInputController = new ZeroTouchVarInputController(this);
     defaultNumInputs   = descriptor.Parameters.Count();
 }
        public override async Task <HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
        {
            HttpRequestMessage request = controllerContext.Request;

            // First see if the request maps to an HTTP function
            FunctionDescriptor function = _scriptHostManager.GetHttpFunctionOrNull(request.RequestUri);

            if (function == null)
            {
                return(new HttpResponseMessage(HttpStatusCode.NotFound));
            }

            // Determine the authorization level of the request
            SecretManager      secretManager      = (SecretManager)controllerContext.Configuration.DependencyResolver.GetService(typeof(SecretManager));
            AuthorizationLevel authorizationLevel = AuthorizationLevelAttribute.GetAuthorizationLevel(request, secretManager, functionName: function.Name);

            if (function.Metadata.IsDisabled &&
                authorizationLevel != AuthorizationLevel.Admin)
            {
                // disabled functions are not publically addressable w/o Admin level auth
                return(new HttpResponseMessage(HttpStatusCode.NotFound));
            }

            // Dispatch the request
            HttpTriggerBindingMetadata httpFunctionMetadata = (HttpTriggerBindingMetadata)function.Metadata.InputBindings.FirstOrDefault(p => p.Type == BindingType.HttpTrigger);
            bool isWebHook = !string.IsNullOrEmpty(httpFunctionMetadata.WebHookType);
            HttpResponseMessage response = null;

            if (isWebHook)
            {
                if (authorizationLevel == AuthorizationLevel.Admin)
                {
                    // Admin level requests bypass the WebHook auth pipeline
                    response = await _scriptHostManager.HandleRequestAsync(function, request, cancellationToken);
                }
                else
                {
                    // This is a WebHook request so define a delegate for the user function.
                    // The WebHook Receiver pipeline will first validate the request fully
                    // then invoke this callback.
                    Func <HttpRequestMessage, Task <HttpResponseMessage> > invokeFunction = async(req) =>
                    {
                        // Reset the content stream before passing the request down to the function
                        Stream stream = await req.Content.ReadAsStreamAsync();

                        stream.Seek(0, SeekOrigin.Begin);

                        return(await _scriptHostManager.HandleRequestAsync(function, req, cancellationToken));
                    };
                    response = await _webHookReceiverManager.HandleRequestAsync(function, request, invokeFunction);
                }
            }
            else
            {
                // Authorize
                if (authorizationLevel < httpFunctionMetadata.AuthLevel)
                {
                    return(new HttpResponseMessage(HttpStatusCode.Unauthorized));
                }

                // Validate the HttpMethod
                // Note that for WebHook requests, WebHook receiver does its own validation
                if (httpFunctionMetadata.Methods != null && !httpFunctionMetadata.Methods.Contains(request.Method))
                {
                    return(new HttpResponseMessage(HttpStatusCode.MethodNotAllowed));
                }

                // Not a WebHook request so dispatch directly
                response = await _scriptHostManager.HandleRequestAsync(function, request, cancellationToken);
            }

            return(response);
        }
        internal async Task GeneratedMethods_WithOutParams_DoNotCauseDeadlocks(string fixture)
        {
            var traceWriter = new TestTraceWriter(TraceLevel.Verbose);

            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                RootScriptPath = @"TestScripts\FunctionGeneration",
                TraceWriter    = traceWriter
            };

            string             secretsPath     = Path.Combine(Path.GetTempPath(), @"FunctionTests\Secrets");
            ISecretsRepository repository      = new FileSystemSecretsRepository(secretsPath);
            WebHostSettings    webHostSettings = new WebHostSettings();

            webHostSettings.SecretsPath = secretsPath;

            var secretManager = new SecretManager(SettingsManager, repository, NullTraceWriter.Instance);

            using (var manager = new WebScriptHostManager(config, new TestSecretManagerFactory(secretManager), SettingsManager, webHostSettings))
            {
                Thread runLoopThread = new Thread(_ =>
                {
                    manager.RunAndBlock(CancellationToken.None);
                });
                runLoopThread.IsBackground = true;
                runLoopThread.Start();

                await TestHelpers.Await(() =>
                {
                    return(manager.State == ScriptHostState.Running);
                });

                var request = new HttpRequestMessage(HttpMethod.Get, string.Format("http://localhost/api/httptrigger-{0}", fixture));
                FunctionDescriptor function = manager.GetHttpFunctionOrNull(request);

                SynchronizationContext currentContext = SynchronizationContext.Current;
                var resetEvent = new ManualResetEventSlim();

                try
                {
                    var requestThread = new Thread(() =>
                    {
                        var context = new SingleThreadedSynchronizationContext();
                        SynchronizationContext.SetSynchronizationContext(context);

                        manager.HandleRequestAsync(function, request, CancellationToken.None)
                        .ContinueWith(task => resetEvent.Set());

                        Thread.Sleep(500);
                        context.Run();
                    });

                    requestThread.IsBackground = true;
                    requestThread.Start();

                    bool threadSignaled = resetEvent.Wait(TimeSpan.FromSeconds(10));

                    requestThread.Abort();

                    Assert.True(threadSignaled, "Thread execution did not complete");
                }
                finally
                {
                    SynchronizationContext.SetSynchronizationContext(currentContext);
                    manager.Stop();
                }
            }
        }
Example #18
0
 public void UpdateEntityDescriptor()
 {
     if (!this.EntityDescriptorUpdated)
     {
         if (this.entry.MediaResource != null)
         {
             if (this.entry.MediaResource.ReadLink != null)
             {
                 this.EntityDescriptor.ReadStreamUri = this.entry.MediaResource.ReadLink;
             }
             if (this.entry.MediaResource.EditLink != null)
             {
                 this.EntityDescriptor.EditStreamUri = this.entry.MediaResource.EditLink;
             }
             if (this.entry.MediaResource.ETag != null)
             {
                 this.EntityDescriptor.StreamETag = this.entry.MediaResource.ETag;
             }
         }
         foreach (ODataProperty property in this.Properties)
         {
             ODataStreamReferenceValue value2 = property.Value as ODataStreamReferenceValue;
             if (value2 != null)
             {
                 StreamDescriptor descriptor = this.EntityDescriptor.AddStreamInfoIfNotPresent(property.Name);
                 if (value2.ReadLink != null)
                 {
                     descriptor.SelfLink = value2.ReadLink;
                 }
                 if (value2.EditLink != null)
                 {
                     descriptor.EditLink = value2.EditLink;
                 }
                 descriptor.ETag = value2.ETag;
                 descriptor.ContentType = value2.ContentType;
             }
         }
         foreach (ODataAssociationLink link in this.entry.AssociationLinks)
         {
             this.EntityDescriptor.AddAssociationLink(link.Name, link.Url);
         }
         foreach (ODataFunction function in this.entry.Functions)
         {
             FunctionDescriptor operationDescriptor = new FunctionDescriptor {
                 Title = function.Title,
                 Metadata = function.Metadata,
                 Target = function.Target
             };
             this.EntityDescriptor.AddOperationDescriptor(operationDescriptor);
         }
         foreach (ODataAction action in this.entry.Actions)
         {
             ActionDescriptor descriptor3 = new ActionDescriptor {
                 Title = action.Title,
                 Metadata = action.Metadata,
                 Target = action.Target
             };
             this.EntityDescriptor.AddOperationDescriptor(descriptor3);
         }
         this.EntityDescriptorUpdated = true;
     }
 }
        public void CreateSnapshot_CreatesExpectedSnapshot()
        {
            FunctionDescriptor function = new FunctionDescriptor
            {
                Id = "FunctionId",
                FullName = "FullName",
                ShortName = "ShortName",
                Parameters = new ParameterDescriptor[] 
                { 
                    new ParameterDescriptor { Name = "param1" },
                    new ParameterDescriptor { Name = "param2" }
                }
            };

            FunctionStartedMessage message = new FunctionStartedMessage
            {
                FunctionInstanceId = Guid.NewGuid(),
                HostInstanceId = Guid.NewGuid(),
                InstanceQueueName = "InstanceQueueName",
                Reason = ExecutionReason.AutomaticTrigger,
                ReasonDetails = "A trigger fired!",
                Heartbeat = new HeartbeatDescriptor
                {
                    InstanceBlobName = "InstanceBlobName",
                    SharedContainerName = "SharedContainerName",
                    SharedDirectoryName = "SharedDirectoryName",
                    ExpirationInSeconds = 5
                },
                SharedQueueName = "SharedQueueName",
                Function = function,
                Arguments = new Dictionary<string, string> 
                {
                    { "param1", "foo" },
                    { "param2", "bar" }
                },
                ParentId = Guid.NewGuid(),
                StartTime = DateTime.Now,
                OutputBlob = new LocalBlobDescriptor { BlobName = "OutputBlobName", ContainerName = "OutputBlobContainerName" },
                ParameterLogBlob = new LocalBlobDescriptor { BlobName = "ParameterLogBlobName", ContainerName = "ParameterLogBlobContainerName" },
                WebJobRunIdentifier = new WebJobRunIdentifier { JobName = "JobName", JobType = WebJobTypes.Triggered, RunId = "RunId", WebSiteName = "WebSiteName" }
            };

            FunctionInstanceSnapshot snapshot = FunctionIndexer.CreateSnapshot(message);

            Assert.Equal(message.FunctionInstanceId, snapshot.Id);
            Assert.Equal(message.HostInstanceId, snapshot.HostInstanceId);
            Assert.Equal(message.InstanceQueueName, snapshot.InstanceQueueName);
            Assert.Same(message.Heartbeat, snapshot.Heartbeat);
            Assert.Equal("SharedQueueName_FunctionId", snapshot.FunctionId);
            Assert.Equal(message.Function.FullName, snapshot.FunctionFullName);
            Assert.Equal(message.Function.ShortName, snapshot.FunctionShortName);
            Assert.Equal(2, snapshot.Arguments.Count);
            Assert.Equal("foo", snapshot.Arguments["param1"].Value);
            Assert.Equal("bar", snapshot.Arguments["param2"].Value);
            Assert.Equal(message.ParentId, snapshot.ParentId);
            Assert.Equal(message.ReasonDetails, snapshot.Reason);
            Assert.Equal(message.StartTime, snapshot.QueueTime);
            Assert.Equal(message.StartTime, snapshot.StartTime);
            Assert.Equal(message.OutputBlob, snapshot.OutputBlob);
            Assert.Same(message.ParameterLogBlob, snapshot.ParameterLogBlob);
            Assert.Equal(message.WebJobRunIdentifier.WebSiteName, snapshot.WebSiteName);
            Assert.Equal(message.WebJobRunIdentifier.JobType.ToString(), snapshot.WebJobType);
            Assert.Equal(message.WebJobRunIdentifier.JobName, snapshot.WebJobName);
            Assert.Equal(message.WebJobRunIdentifier.RunId, snapshot.WebJobRunId);
        }
        public void Generate_WithOutParams_CorrectlyUpdatesOutput()
        {
            string functionName = "FunctionWithOutValue";
            Collection<ParameterDescriptor> parameters = new Collection<ParameterDescriptor>();

            parameters.Add(new ParameterDescriptor("param1", typeof(string).MakeByRefType()) { Attributes = ParameterAttributes.Out });

            FunctionMetadata metadata = new FunctionMetadata();
            object[] invocationArguments = null;
              TestInvoker invoker = new TestInvoker(args =>
            {
                invocationArguments = args;
                invocationArguments[0] = "newvalue";
            });
            FunctionDescriptor function = new FunctionDescriptor(functionName, invoker, metadata, parameters);
            Collection<FunctionDescriptor> functions = new Collection<FunctionDescriptor>();
            functions.Add(function);

            // generate the Type
            Type functionType = FunctionGenerator.Generate("TestScriptHost", "TestFunctions", functions);

            // verify the generated function
            MethodInfo method = functionType.GetMethod(functionName);
            ParameterInfo[] functionParams = method.GetParameters();

            // Verify that we have the correct number of parameters
            Assert.Equal(parameters.Count, functionParams.Length);

            // Verify that the method is invocable
            DateTimeOffset input = DateTimeOffset.Now;
            method.Invoke(null, new object[] { null });

            // verify our custom invoker was called
            Assert.Equal(1, invoker.InvokeCount);

            Assert.NotNull(invocationArguments);
            Assert.Equal("newvalue", (string)invocationArguments[0]);
        }
 public FunctionInstanceFactory(IFunctionBinding binding, IFunctionInvoker invoker, FunctionDescriptor descriptor)
 {
     _binding = binding;
     _invoker = invoker;
     _descriptor = descriptor;
 }
Example #22
0
        public ZeroTouchSearchElement(FunctionDescriptor functionDescriptor)
        {
            this.functionDescriptor = functionDescriptor;

            Name = functionDescriptor.UserFriendlyName;

            if (functionDescriptor.IsOverloaded)
            {
                var parameters = new StringBuilder();
                parameters.Append("(");
                parameters.Append(String.Join(", ", functionDescriptor.Parameters.Select(x => x.Name)));
                parameters.Append(")");

                Parameters = parameters.ToString();
            }

            FullCategoryName = functionDescriptor.Category;
            Description      = functionDescriptor.Description;
            Assembly         = functionDescriptor.Assembly;

            ElementType = ElementTypes.ZeroTouch;

            if (functionDescriptor.IsBuiltIn)
            {
                ElementType |= ElementTypes.BuiltIn;
            }

            if (functionDescriptor.IsPackageMember)
            {
                ElementType |= ElementTypes.Packaged;
            }

            inputParameters  = new List <Tuple <string, string> >(functionDescriptor.InputParameters);
            outputParameters = new List <string>()
            {
                functionDescriptor.ReturnType.ToShortString()
            };

            foreach (var tag in functionDescriptor.GetSearchTags())
            {
                SearchKeywords.Add(tag);
            }

            var weights = functionDescriptor.GetSearchTagWeights();

            foreach (var weight in weights)
            {
                // Search tag weight can't be more then 1.
                if (weight <= 1)
                {
                    keywordWeights.Add(weight);
                }
            }

            int weightsCount = weights.Count();

            // If there weren't added weights for search tags, then add default value - 0.5
            if (weightsCount != SearchKeywords.Count)
            {
                int numberOfLackingWeights = SearchKeywords.Count - weightsCount;

                // Number of lacking weights should be more than 0.
                // It can be less then 0 only if there was some mistake in xml file.
                if (numberOfLackingWeights > 0)
                {
                    for (int i = 0; i < numberOfLackingWeights; i++)
                    {
                        keywordWeights.Add(0.5);
                    }
                }
            }

            iconName = GetIconName();
        }
Example #23
0
        public override async Task <HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
        {
            HttpRequestMessage request = controllerContext.Request;

            // First see if the request maps to an HTTP function
            FunctionDescriptor function = _scriptHostManager.GetHttpFunctionOrNull(request);

            if (function == null)
            {
                return(new HttpResponseMessage(HttpStatusCode.NotFound));
            }

            // Determine the authorization level of the request
            ISecretManager secretManager      = controllerContext.Configuration.DependencyResolver.GetService <ISecretManager>();
            var            settings           = controllerContext.Configuration.DependencyResolver.GetService <WebHostSettings>();
            var            authorizationLevel = settings.IsAuthDisabled
                ? AuthorizationLevel.Admin
                : await AuthorizationLevelAttribute.GetAuthorizationLevelAsync(request, secretManager, functionName : function.Name);

            if (function.Metadata.IsExcluded ||
                (function.Metadata.IsDisabled && authorizationLevel != AuthorizationLevel.Admin))
            {
                // disabled functions are not publicly addressable w/o Admin level auth,
                // and excluded functions are also ignored here (though the check above will
                // already exclude them)
                return(new HttpResponseMessage(HttpStatusCode.NotFound));
            }

            // Dispatch the request
            HttpTriggerBindingMetadata httpFunctionMetadata = (HttpTriggerBindingMetadata)function.Metadata.InputBindings.FirstOrDefault(p => string.Compare("HttpTrigger", p.Type, StringComparison.OrdinalIgnoreCase) == 0);
            bool isWebHook = !string.IsNullOrEmpty(httpFunctionMetadata.WebHookType);
            HttpResponseMessage response = null;

            if (isWebHook)
            {
                if (authorizationLevel == AuthorizationLevel.Admin)
                {
                    // Admin level requests bypass the WebHook auth pipeline
                    response = await _scriptHostManager.HandleRequestAsync(function, request, cancellationToken);
                }
                else
                {
                    // This is a WebHook request so define a delegate for the user function.
                    // The WebHook Receiver pipeline will first validate the request fully
                    // then invoke this callback.
                    Func <HttpRequestMessage, Task <HttpResponseMessage> > invokeFunction = async(req) =>
                    {
                        // Reset the content stream before passing the request down to the function
                        Stream stream = await req.Content.ReadAsStreamAsync();

                        stream.Seek(0, SeekOrigin.Begin);

                        return(await _scriptHostManager.HandleRequestAsync(function, req, cancellationToken));
                    };
                    response = await _webHookReceiverManager.HandleRequestAsync(function, request, invokeFunction);
                }
            }
            else
            {
                // Authorize
                if (authorizationLevel < httpFunctionMetadata.AuthLevel)
                {
                    return(new HttpResponseMessage(HttpStatusCode.Unauthorized));
                }

                // Not a WebHook request so dispatch directly
                response = await _scriptHostManager.HandleRequestAsync(function, request, cancellationToken);
            }

            return(response);
        }
        private void Log(LogLevel level, FunctionDescriptor descriptor, Guid functionId, string message, Exception exception = null)
        {
            ILogger logger = _loggerFactory?.CreateLogger(LogCategories.CreateFunctionCategory(descriptor.LogName));

            logger?.Log(level, 0, message, exception, (s, e) => s);
        }
        private void Log(LogLevel level, FunctionDescriptor descriptor, string message, params object[] args)
        {
            ILogger logger = _loggerFactory?.CreateLogger(LogCategories.CreateFunctionCategory(descriptor.LogName));

            logger?.Log(level, 0, message, args);
        }
Example #26
0
 public ZeroTouchNodeController(
     EngineController engineController, FunctionDescriptor zeroTouchDef) :
     base(zeroTouchDef)
 {
     this.engineController = engineController;
 }
Example #27
0
 public DSVarArgFunction(WorkspaceModel workspaceModel, FunctionDescriptor descriptor)
     : base(workspaceModel, new ZeroTouchVarArgNodeController(workspaceModel.DynamoModel.EngineController, descriptor))
 {
     VarInputController = new ZeroTouchVarInputController(this);
 }
Example #28
0
        public async Task Generate_EndToEnd()
        {
            // construct our TimerTrigger attribute ([TimerTrigger("00:00:02", RunOnStartup = true)])
            Collection <ParameterDescriptor> parameters = new Collection <ParameterDescriptor>();

            ParameterDescriptor    parameter            = new ParameterDescriptor("timerInfo", typeof(TimerInfo));
            ConstructorInfo        ctorInfo             = typeof(TimerTriggerAttribute).GetConstructor(new Type[] { typeof(string) });
            PropertyInfo           runOnStartupProperty = typeof(TimerTriggerAttribute).GetProperty("RunOnStartup");
            CustomAttributeBuilder attributeBuilder     = new CustomAttributeBuilder(
                ctorInfo,
                new object[] { "00:00:02" },
                new PropertyInfo[] { runOnStartupProperty },
                new object[] { true });

            parameter.CustomAttributes.Add(attributeBuilder);
            parameters.Add(parameter);

            // create the FunctionDefinition
            FunctionMetadata   metadata = new FunctionMetadata();
            TestInvoker        invoker  = new TestInvoker();
            FunctionDescriptor function = new FunctionDescriptor("TimerFunction", invoker, metadata, parameters, null, null, null);
            Collection <FunctionDescriptor> functions = new Collection <FunctionDescriptor>();

            functions.Add(function);

            // Get the Type Attributes (in this case, a TimeoutAttribute)
            ScriptJobHostOptions scriptConfig = new ScriptJobHostOptions();

            scriptConfig.FunctionTimeout = TimeSpan.FromMinutes(5);
            Collection <CustomAttributeBuilder> typeAttributes = new Collection <CustomAttributeBuilder>();

            // generate the Type
            Type functionType = FunctionGenerator.Generate("TestScriptHost", "TestFunctions", typeAttributes, functions);

            // verify the generated function
            MethodInfo            method           = functionType.GetMethod("TimerFunction");
            ParameterInfo         triggerParameter = method.GetParameters()[0];
            TimerTriggerAttribute triggerAttribute = triggerParameter.GetCustomAttribute <TimerTriggerAttribute>();

            Assert.NotNull(triggerAttribute);

            // start the JobHost which will start running the timer function
            var builder = new HostBuilder()
                          .ConfigureWebJobs(b =>
            {
                b.AddTimers()
                .AddAzureStorageCoreServices();
            })
                          .ConfigureServices(s =>
            {
                s.AddSingleton <ITypeLocator>(new TestTypeLocator(functionType));
                s.AddSingleton <ILoggerFactory>(new LoggerFactory());

                TestHelpers.AddTestAzureBlobStorageProvider(s, TestHelpers.GetTestConfiguration());
                TestHostBuilderExtensions.AddMockedSingleton <IScriptHostManager>(s);
            });

            using (var host = builder.Build())
            {
                await host.StartAsync();

                await Task.Delay(3000);

                await host.StopAsync();
            }

            // verify our custom invoker was called
            Assert.True(invoker.InvokeCount >= 2);
        }
        public void Generate_WithMultipleOutParameters()
        {
            string functionName = "FunctionWithOuts";
            Collection<ParameterDescriptor> parameters = new Collection<ParameterDescriptor>();

            parameters.Add(new ParameterDescriptor("param1", typeof(string)));
            parameters.Add(new ParameterDescriptor("param2", typeof(string).MakeByRefType()) { Attributes = ParameterAttributes.Out });
            parameters.Add(new ParameterDescriptor("param3", typeof(string).MakeByRefType()) { Attributes = ParameterAttributes.Out });

            FunctionMetadata metadata = new FunctionMetadata();
            TestInvoker invoker = new TestInvoker();
            FunctionDescriptor function = new FunctionDescriptor(functionName, invoker, metadata, parameters);
            Collection<FunctionDescriptor> functions = new Collection<FunctionDescriptor>();
            functions.Add(function);

            // generate the Type
            Type functionType = FunctionGenerator.Generate("TestScriptHost", "TestFunctions", functions);

            // verify the generated function
            MethodInfo method = functionType.GetMethod(functionName);
            ParameterInfo[] functionParams = method.GetParameters();

            // Verify that we have the correct number of parameters
            Assert.Equal(parameters.Count, functionParams.Length);

            // Verify that out parameters were correctly generated
            Assert.True(functionParams[1].IsOut);
            Assert.True(functionParams[2].IsOut);

            // Verify that the method is invocable
            method.Invoke(null, new object[] { "test", null, null });

            // verify our custom invoker was called
            Assert.Equal(1, invoker.InvokeCount);
        }
Example #30
0
        public void TypedParametersToStringTest()
        {
            //1. Foo(x: double, y : double) -> Foo.double-double
            //2. Foo(point : Point) -> Foo.Point
            //3. Foo(a : bool [ ] [ ] , b : var[], c : double[][]) -> Foo.bool2-var1-double2
            //4. Foo(arr : var[]..[], a : int) -> Foo.varN-int
            //5. Foo(a: Autodesk.DesignScript.Geometry.Circle, b: Xxxx.Yyy.Curve)
            //6. Empty string(a: int)

            // 1 case
            var parameters1 = new List <TypedParameter>();

            parameters1.Add(new TypedParameter("x", new ProtoCore.Type {
                Name = "double"
            }));
            parameters1.Add(new TypedParameter("y", new ProtoCore.Type {
                Name = "double"
            }));
            var functionItem1 = new FunctionDescriptor(new FunctionDescriptorParams
            {
                FunctionName = "Foo", Parameters = parameters1, FunctionType = FunctionType.GenericFunction
            });

            System.Console.WriteLine(functionItem1.Parameters.Count());
            Assert.AreEqual("Foo.double-double", Utils.TypedParametersToString(functionItem1));

            //2 case
            var parameters2 = new List <TypedParameter>();

            parameters2.Add(new TypedParameter("point", new ProtoCore.Type {
                Name = "Point"
            }));
            var functionItem2 = new FunctionDescriptor(new FunctionDescriptorParams
            {
                FunctionName = "Foo", Parameters = parameters2, FunctionType = FunctionType.GenericFunction
            });

            Assert.AreEqual("Foo.Point", Utils.TypedParametersToString(functionItem2));

            //3 case
            var parameters3 = new List <TypedParameter>();

            parameters3.Add(new TypedParameter("a", new ProtoCore.Type {
                Name = "bool [ ] [ ] "
            }));
            parameters3.Add(new TypedParameter("b", new ProtoCore.Type {
                Name = "var[]"
            }));
            parameters3.Add(new TypedParameter("c", new ProtoCore.Type {
                Name = "double[][]"
            }));
            var functionItem3 = new FunctionDescriptor(new FunctionDescriptorParams
            {
                FunctionName = "Foo", Parameters = parameters3, FunctionType = FunctionType.GenericFunction
            });

            Assert.AreEqual("Foo.bool2-var1-double2", Utils.TypedParametersToString(functionItem3));

            //4 case
            var parameters4 = new List <TypedParameter>();

            parameters4.Add(new TypedParameter("arr", new ProtoCore.Type {
                Name = "var[]..[]"
            }));
            parameters4.Add(new TypedParameter("a", new ProtoCore.Type {
                Name = "int"
            }));
            var functionItem4 = new FunctionDescriptor(new FunctionDescriptorParams
            {
                FunctionName = "Foo", Parameters = parameters4, FunctionType = FunctionType.GenericFunction
            });

            Assert.AreEqual("Foo.varN-int", Utils.TypedParametersToString(functionItem4));

            //5 case
            var parameters5 = new List <TypedParameter>();

            parameters5.Add(new TypedParameter("a", new ProtoCore.Type {
                Name = "Autodesk.DesignScript.Geometry.Circle"
            }));
            parameters5.Add(new TypedParameter("b", new ProtoCore.Type {
                Name = "Xxxx.Yyy.Curve"
            }));
            var functionItem5 = new FunctionDescriptor(new FunctionDescriptorParams
            {
                FunctionName = "Foo", Parameters = parameters5, FunctionType = FunctionType.GenericFunction
            });

            Assert.AreEqual("Foo.Circle-Curve", Utils.TypedParametersToString(functionItem5));

            //6 case
            var parameters6 = new List <TypedParameter>();

            parameters6.Add(new TypedParameter("a", new ProtoCore.Type {
                Name = "int"
            }));
            var functionItem6 = new FunctionDescriptor(new FunctionDescriptorParams
            {
                FunctionName = "", Parameters = parameters6, FunctionType = FunctionType.GenericFunction
            });

            Assert.AreEqual(".int", Utils.TypedParametersToString(functionItem6));
        }
Example #31
0
 public DSFunction(WorkspaceModel workspaceModel, FunctionDescriptor descriptor)
     : base(workspaceModel, new ZeroTouchNodeController(workspaceModel.DynamoModel.EngineController,
                                                        descriptor))
 {
 }
 public FunctionDefinition(FunctionDescriptor descriptor, IFunctionInstanceFactory instanceFactory, IListenerFactory listenerFactory)
 {
     _descriptor = descriptor;
     _instanceFactory = instanceFactory;
     _listenerFactory = listenerFactory;
 }
 public TriggeredFunctionExecutor(FunctionDescriptor descriptor, IFunctionExecutor executor, ITriggeredFunctionInstanceFactory <TTriggerValue> instanceFactory)
 {
     _descriptor      = descriptor;
     _executor        = executor;
     _instanceFactory = instanceFactory;
 }
Example #34
0
 public FunctionCall(FunctionDescriptor descriptor, params IJsonMasherOperator[] arguments)
 {
     Descriptor = descriptor;
     Arguments  = arguments.ToList();
 }
        public async Task Generate_EndToEnd()
        {
            // construct our TimerTrigger attribute ([TimerTrigger("00:00:02", RunOnStartup = true)])
            Collection <ParameterDescriptor> parameters = new Collection <ParameterDescriptor>();
            ParameterDescriptor    parameter            = new ParameterDescriptor("timerInfo", typeof(TimerInfo));
            ConstructorInfo        ctorInfo             = typeof(TimerTriggerAttribute).GetConstructor(new Type[] { typeof(string) });
            PropertyInfo           runOnStartupProperty = typeof(TimerTriggerAttribute).GetProperty("RunOnStartup");
            CustomAttributeBuilder attributeBuilder     = new CustomAttributeBuilder(
                ctorInfo,
                new object[] { "00:00:02" },
                new PropertyInfo[] { runOnStartupProperty },
                new object[] { true });

            parameter.CustomAttributes.Add(attributeBuilder);
            parameters.Add(parameter);

            // create the FunctionDefinition
            FunctionMetadata   metadata = new FunctionMetadata();
            TestInvoker        invoker  = new TestInvoker();
            FunctionDescriptor function = new FunctionDescriptor("TimerFunction", invoker, metadata, parameters);
            Collection <FunctionDescriptor> functions = new Collection <FunctionDescriptor>();

            functions.Add(function);

            // Get the Type Attributes (in this case, a TimeoutAttribute)
            ScriptHostConfiguration scriptConfig = new ScriptHostConfiguration();

            scriptConfig.FunctionTimeout = TimeSpan.FromMinutes(5);
            Collection <CustomAttributeBuilder> typeAttributes = ScriptHost.CreateTypeAttributes(scriptConfig);

            // generate the Type
            Type functionType = FunctionGenerator.Generate("TestScriptHost", "TestFunctions", typeAttributes, functions);

            // verify the generated function
            MethodInfo       method           = functionType.GetMethod("TimerFunction");
            TimeoutAttribute timeoutAttribute = (TimeoutAttribute)functionType.GetCustomAttributes().Single();

            Assert.Equal(TimeSpan.FromMinutes(5), timeoutAttribute.Timeout);
            Assert.True(timeoutAttribute.ThrowOnTimeout);
            Assert.True(timeoutAttribute.TimeoutWhileDebugging);
            ParameterInfo         triggerParameter = method.GetParameters()[0];
            TimerTriggerAttribute triggerAttribute = triggerParameter.GetCustomAttribute <TimerTriggerAttribute>();

            Assert.NotNull(triggerAttribute);

            // start the JobHost which will start running the timer function
            JobHostConfiguration config = new JobHostConfiguration()
            {
                TypeLocator = new TypeLocator(functionType)
            };

            config.UseTimers();
            JobHost host = new JobHost(config);

            await host.StartAsync();

            await Task.Delay(3000);

            await host.StopAsync();

            // verify our custom invoker was called
            Assert.True(invoker.InvokeCount >= 2);
        }
Example #36
0
 public FunctionCall(FunctionDescriptor descriptor, List <IJsonMasherOperator> arguments)
 {
     Descriptor = descriptor;
     Arguments  = arguments;
 }
Example #37
0
        internal async Task IndexMethodAsyncCore(MethodInfo method, IFunctionIndexCollector index, CancellationToken cancellationToken)
        {
            Debug.Assert(method != null);
            bool hasNoAutomaticTriggerAttribute = method.GetCustomAttribute <NoAutomaticTriggerAttribute>() != null;

            ITriggerBinding             triggerBinding   = null;
            ParameterInfo               triggerParameter = null;
            IEnumerable <ParameterInfo> parameters       = method.GetParameters();

            foreach (ParameterInfo parameter in parameters)
            {
                ITriggerBinding possibleTriggerBinding = await _triggerBindingProvider.TryCreateAsync(new TriggerBindingProviderContext(parameter, cancellationToken));

                if (possibleTriggerBinding != null)
                {
                    if (triggerBinding == null)
                    {
                        triggerBinding   = possibleTriggerBinding;
                        triggerParameter = parameter;
                    }
                    else
                    {
                        throw new InvalidOperationException("More than one trigger per function is not allowed.");
                    }
                }
            }

            Dictionary <string, IBinding>      nonTriggerBindings = new Dictionary <string, IBinding>();
            IReadOnlyDictionary <string, Type> bindingDataContract;

            if (triggerBinding != null)
            {
                bindingDataContract = triggerBinding.BindingDataContract;

                // See if a regular binding can handle it.
                IBinding binding = await _bindingProvider.TryCreateAsync(new BindingProviderContext(triggerParameter, bindingDataContract, cancellationToken));

                if (binding != null)
                {
                    triggerBinding = new TriggerWrapper(triggerBinding, binding);
                }
            }
            else
            {
                bindingDataContract = null;
            }

            bool      hasParameterBindingAttribute  = false;
            Exception invalidInvokeBindingException = null;

            ReturnParameterInfo returnParameter = null;
            bool triggerHasReturnBinding        = false;

            if (TypeUtility.TryGetReturnType(method, out Type methodReturnType))
            {
                if (bindingDataContract != null && bindingDataContract.TryGetValue(ReturnParamName, out Type triggerReturnType))
                {
                    // The trigger will handle the return value.
                    triggerHasReturnBinding = true;
                }

                // We treat binding to the return type the same as binding to an 'out T' parameter.
                // An explicit return binding takes precedence over an implicit trigger binding.
                returnParameter = new ReturnParameterInfo(method, methodReturnType);
                parameters      = parameters.Concat(new ParameterInfo[] { returnParameter });
            }

            foreach (ParameterInfo parameter in parameters)
            {
                if (parameter == triggerParameter)
                {
                    continue;
                }

                IBinding binding = await _bindingProvider.TryCreateAsync(new BindingProviderContext(parameter, bindingDataContract, cancellationToken));

                if (binding == null)
                {
                    if (parameter == returnParameter)
                    {
                        if (triggerHasReturnBinding)
                        {
                            // Ok. Skip and let trigger own the return binding.
                            continue;
                        }
                        else
                        {
                            // If the method has a return value, then we must have a binding to it.
                            // This is similar to the error we used to throw.
                            invalidInvokeBindingException = new InvalidOperationException("Functions must return Task or void, have a binding attribute for the return value, or be triggered by a binding that natively supports return values.");
                        }
                    }

                    if (triggerBinding != null && !hasNoAutomaticTriggerAttribute)
                    {
                        throw new InvalidOperationException(
                                  string.Format(Constants.UnableToBindParameterFormat,
                                                parameter.Name, parameter.ParameterType.Name, Constants.ExtensionInitializationMessage));
                    }
                    else
                    {
                        // Host.Call-only parameter
                        binding = InvokeBinding.Create(parameter.Name, parameter.ParameterType);
                        if (binding == null && invalidInvokeBindingException == null)
                        {
                            // This function might not have any attribute, in which case we shouldn't throw an
                            // exception when we can't bind it. Instead, save this exception for later once we determine
                            // whether or not it is an SDK function.
                            invalidInvokeBindingException = new InvalidOperationException(
                                string.Format(Constants.UnableToBindParameterFormat,
                                              parameter.Name, parameter.ParameterType.Name, Constants.ExtensionInitializationMessage));
                        }
                    }
                }
                else if (!hasParameterBindingAttribute)
                {
                    hasParameterBindingAttribute = binding.FromAttribute;
                }

                nonTriggerBindings.Add(parameter.Name, binding);
            }

            // Only index functions with some kind of attribute on them. Three ways that could happen:
            // 1. There's an attribute on a trigger parameter (all triggers come from attributes).
            // 2. There's an attribute on a non-trigger parameter (some non-trigger bindings come from attributes).
            if (triggerBinding == null && !hasParameterBindingAttribute)
            {
                // 3. There's an attribute on the method itself (NoAutomaticTrigger).
                if (method.GetCustomAttribute <NoAutomaticTriggerAttribute>() == null)
                {
                    return;
                }
            }

            if (TypeUtility.IsAsyncVoid(method))
            {
                string msg = $"Function '{method.Name}' is async but does not return a Task. Your function may not run correctly.";
                _logger?.LogWarning(msg);
            }

            if (invalidInvokeBindingException != null)
            {
                throw invalidInvokeBindingException;
            }

            // Validation: prevent multiple ConsoleOutputs
            if (nonTriggerBindings.OfType <TraceWriterBinding>().Count() > 1)
            {
                throw new InvalidOperationException("Can't have multiple TraceWriter/TextWriter parameters in a single function.");
            }

            string              triggerParameterName = triggerParameter != null ? triggerParameter.Name : null;
            FunctionDescriptor  functionDescriptor   = CreateFunctionDescriptor(method, triggerParameterName, triggerBinding, nonTriggerBindings);
            IFunctionInvoker    invoker = FunctionInvokerFactory.Create(method, _activator);
            IFunctionDefinition functionDefinition;

            if (triggerBinding != null)
            {
                Type triggerValueType = triggerBinding.TriggerValueType;
                var  methodInfo       = typeof(FunctionIndexer).GetMethod("CreateTriggeredFunctionDefinition", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(triggerValueType);
                functionDefinition = (FunctionDefinition)methodInfo.Invoke(this, new object[] { triggerBinding, triggerParameterName, functionDescriptor, nonTriggerBindings, invoker });

                if (hasNoAutomaticTriggerAttribute && functionDefinition != null)
                {
                    functionDefinition = new FunctionDefinition(functionDescriptor, functionDefinition.InstanceFactory, listenerFactory: null);
                }
            }
            else
            {
                IFunctionInstanceFactory instanceFactory = new FunctionInstanceFactory(new FunctionBinding(functionDescriptor, nonTriggerBindings, _singletonManager), invoker, functionDescriptor);
                functionDefinition = new FunctionDefinition(functionDescriptor, instanceFactory, listenerFactory: null);
            }

            index.Add(functionDefinition, functionDescriptor, method);
        }
Example #38
0
 /// <summary>
 /// Creates a new instance
 /// </summary>
 /// <param name="descriptor">The <see cref="FunctionDescriptor"/> to create a listener for.</param>
 /// <param name="executor">The <see cref="ITriggeredFunctionExecutor"/> that should be used to invoke the
 /// target job function when the trigger fires.</param>
 /// <param name="sharedQueue">The shared queue.</param>
 /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
 internal ListenerFactoryContext(FunctionDescriptor descriptor, ITriggeredFunctionExecutor executor, SharedQueueHandler sharedQueue, CancellationToken cancellationToken)
     : this(descriptor, executor, cancellationToken)
 {
     _sharedQueue = sharedQueue;
 }
        public void TryGetFunctionFromException_FunctionMatch()
        {
            string stack = "TypeError: Cannot read property 'is' of undefined\n" +
                           "at Timeout._onTimeout(D:\\home\\site\\wwwroot\\HttpTriggerNode\\index.js:7:35)\n" +
                           "at tryOnTimeout (timers.js:224:11)\n" +
                           "at Timer.listOnTimeout(timers.js:198:5)";
            Collection<FunctionDescriptor> functions = new Collection<FunctionDescriptor>();
            var exception = new InvalidOperationException(stack);

            // no match - empty functions
            FunctionDescriptor functionResult = null;
            bool result = ScriptHost.TryGetFunctionFromException(functions, exception, out functionResult);
            Assert.False(result);
            Assert.Null(functionResult);

            // no match - one non-matching function
            FunctionMetadata metadata = new FunctionMetadata
            {
                Name = "SomeFunction",
                Source = "D:\\home\\site\\wwwroot\\SomeFunction\\index.js"
            };
            FunctionDescriptor function = new FunctionDescriptor("TimerFunction", new TestInvoker(), metadata, new Collection<ParameterDescriptor>());
            functions.Add(function);
            result = ScriptHost.TryGetFunctionFromException(functions, exception, out functionResult);
            Assert.False(result);
            Assert.Null(functionResult);

            // match - exact
            metadata = new FunctionMetadata
            {
                Name = "HttpTriggerNode",
                Source = "D:\\home\\site\\wwwroot\\HttpTriggerNode\\index.js"
            };
            function = new FunctionDescriptor("TimerFunction", new TestInvoker(), metadata, new Collection<ParameterDescriptor>());
            functions.Add(function);
            result = ScriptHost.TryGetFunctionFromException(functions, exception, out functionResult);
            Assert.True(result);
            Assert.Same(function, functionResult);

            // match - different file from the same function
            stack = "TypeError: Cannot read property 'is' of undefined\n" +
                           "at Timeout._onTimeout(D:\\home\\site\\wwwroot\\HttpTriggerNode\\npm\\lib\\foo.js:7:35)\n" +
                           "at tryOnTimeout (timers.js:224:11)\n" +
                           "at Timer.listOnTimeout(timers.js:198:5)";
            exception = new InvalidOperationException(stack);
            result = ScriptHost.TryGetFunctionFromException(functions, exception, out functionResult);
            Assert.True(result);
            Assert.Same(function, functionResult);
        }
 public void DescriptorIsFromConstructor()
 {
     var descriptor = new FunctionDescriptor();
     var eventArgs = new ReceivingResponseEventArgs(new ResponseMessageSimulator(null), descriptor);
     eventArgs.Descriptor.Should().BeSameAs(descriptor);
 }
        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));
        }
Example #42
0
 public DSFunction(FunctionDescriptor definition)
 {
     ArgumentLacing = LacingStrategy.Shortest;
     Definition     = definition;
     Initialize();
 }
        internal async Task IndexMethodAsyncCore(MethodInfo method, IFunctionIndexCollector index, CancellationToken cancellationToken)
        {
            Debug.Assert(method != null);
            bool hasNoAutomaticTriggerAttribute = method.GetCustomAttribute <NoAutomaticTriggerAttribute>() != null;

            ITriggerBinding triggerBinding   = null;
            ParameterInfo   triggerParameter = null;

            ParameterInfo[] parameters = method.GetParameters();

            foreach (ParameterInfo parameter in parameters)
            {
                ITriggerBinding possibleTriggerBinding = await _triggerBindingProvider.TryCreateAsync(new TriggerBindingProviderContext(parameter, cancellationToken));

                if (possibleTriggerBinding != null)
                {
                    if (triggerBinding == null)
                    {
                        triggerBinding   = possibleTriggerBinding;
                        triggerParameter = parameter;
                    }
                    else
                    {
                        throw new InvalidOperationException("More than one trigger per function is not allowed.");
                    }
                }
            }

            Dictionary <string, IBinding>      nonTriggerBindings = new Dictionary <string, IBinding>();
            IReadOnlyDictionary <string, Type> bindingDataContract;

            if (triggerBinding != null)
            {
                bindingDataContract = triggerBinding.BindingDataContract;
            }
            else
            {
                bindingDataContract = null;
            }

            bool      hasParameterBindingAttribute  = false;
            Exception invalidInvokeBindingException = null;

            foreach (ParameterInfo parameter in parameters)
            {
                if (parameter == triggerParameter)
                {
                    continue;
                }

                IBinding binding = await _bindingProvider.TryCreateAsync(new BindingProviderContext(parameter, bindingDataContract, cancellationToken));

                if (binding == null)
                {
                    if (triggerBinding != null && !hasNoAutomaticTriggerAttribute)
                    {
                        throw new InvalidOperationException(
                                  string.Format(Constants.UnableToBindParameterFormat,
                                                parameter.Name, parameter.ParameterType.Name, Constants.ExtensionInitializationMessage));
                    }
                    else
                    {
                        // Host.Call-only parameter
                        binding = InvokeBinding.Create(parameter.Name, parameter.ParameterType);
                        if (binding == null && invalidInvokeBindingException == null)
                        {
                            // This function might not have any attribute, in which case we shouldn't throw an
                            // exception when we can't bind it. Instead, save this exception for later once we determine
                            // whether or not it is an SDK function.
                            invalidInvokeBindingException = new InvalidOperationException(
                                string.Format(Constants.UnableToBindParameterFormat,
                                              parameter.Name, parameter.ParameterType.Name, Constants.ExtensionInitializationMessage));
                        }
                    }
                }
                else if (!hasParameterBindingAttribute)
                {
                    hasParameterBindingAttribute = binding.FromAttribute;
                }

                nonTriggerBindings.Add(parameter.Name, binding);
            }

            // Only index functions with some kind of attribute on them. Three ways that could happen:
            // 1. There's an attribute on a trigger parameter (all triggers come from attributes).
            // 2. There's an attribute on a non-trigger parameter (some non-trigger bindings come from attributes).
            if (triggerBinding == null && !hasParameterBindingAttribute)
            {
                // 3. There's an attribute on the method itself (NoAutomaticTrigger).
                if (method.GetCustomAttribute <NoAutomaticTriggerAttribute>() == null)
                {
                    return;
                }
            }

            Type returnType = method.ReturnType;

            if (returnType != typeof(void) && returnType != typeof(Task))
            {
                throw new InvalidOperationException("Functions must return Task or void.");
            }

            if (invalidInvokeBindingException != null)
            {
                throw invalidInvokeBindingException;
            }

            // Validation: prevent multiple ConsoleOutputs
            if (nonTriggerBindings.OfType <TraceWriterBinding>().Count() > 1)
            {
                throw new InvalidOperationException("Can't have multiple TraceWriter/TextWriter parameters in a single function.");
            }

            string              triggerParameterName = triggerParameter != null ? triggerParameter.Name : null;
            FunctionDescriptor  functionDescriptor   = CreateFunctionDescriptor(method, triggerParameterName, triggerBinding, nonTriggerBindings);
            IFunctionInvoker    invoker = FunctionInvokerFactory.Create(method, _activator);
            IFunctionDefinition functionDefinition;

            if (triggerBinding != null)
            {
                functionDefinition = CreateTriggeredFunctionDefinition(triggerBinding, triggerParameterName, _executor, functionDescriptor, nonTriggerBindings, invoker, _singletonManager);

                if (hasNoAutomaticTriggerAttribute && functionDefinition != null)
                {
                    functionDefinition = new FunctionDefinition(functionDescriptor, functionDefinition.InstanceFactory, listenerFactory: null);
                }
            }
            else
            {
                IFunctionInstanceFactory instanceFactory = new FunctionInstanceFactory(new FunctionBinding(functionDescriptor, nonTriggerBindings, _singletonManager), invoker, functionDescriptor);
                functionDefinition = new FunctionDefinition(functionDescriptor, instanceFactory, listenerFactory: null);
            }

            index.Add(functionDefinition, functionDescriptor, method);
        }
 private static FunctionSnapshot CreateFunctionSnapshot(string queueName, HeartbeatDescriptor heartbeat,
     FunctionDescriptor function, DateTimeOffset hostVersion)
 {
     return new FunctionSnapshot
     {
         HostVersion = hostVersion,
         Id = new FunctionIdentifier(queueName, function.Id).ToString(),
         QueueName = queueName,
         HeartbeatSharedContainerName = heartbeat != null ? heartbeat.SharedContainerName : null,
         HeartbeatSharedDirectoryName = heartbeat != null ? heartbeat.SharedDirectoryName : null,
         HeartbeatExpirationInSeconds = heartbeat != null ? (int?)heartbeat.ExpirationInSeconds : null,
         HostFunctionId = function.Id,
         FullName = function.FullName,
         ShortName = function.ShortName,
         Parameters = CreateParameterSnapshots(function.Parameters)
     };
 }
        public void Generate_WithValueTypes_Succeeds()
        {
            string functionName = "FunctionWithValueTypes";
            Collection<ParameterDescriptor> parameters = new Collection<ParameterDescriptor>();

            parameters.Add(new ParameterDescriptor("param1", typeof(string)));
            parameters.Add(new ParameterDescriptor("param2", typeof(DateTimeOffset)));
            parameters.Add(new ParameterDescriptor("param3", typeof(int)));

            FunctionMetadata metadata = new FunctionMetadata();
            object[] invocationArguments = null;
            TestInvoker invoker = new TestInvoker(args => { invocationArguments = args; });
            FunctionDescriptor function = new FunctionDescriptor(functionName, invoker, metadata, parameters);
            Collection<FunctionDescriptor> functions = new Collection<FunctionDescriptor>();
            functions.Add(function);

            // generate the Type
            Type functionType = FunctionGenerator.Generate("TestScriptHost", "TestFunctions", functions);

            // verify the generated function
            MethodInfo method = functionType.GetMethod(functionName);
            ParameterInfo[] functionParams = method.GetParameters();

            // Verify that we have the correct number of parameters
            Assert.Equal(parameters.Count, functionParams.Length);

            // Verify that the method is invocable
            DateTimeOffset input = DateTimeOffset.Now;
            method.Invoke(null, new object[] { "test", input, 44 });

            // verify our custom invoker was called
            Assert.Equal(1, invoker.InvokeCount);

            Assert.NotNull(invocationArguments);
            Assert.Equal(input, (DateTimeOffset)invocationArguments[1]);
            Assert.Equal(44, (int)invocationArguments[2]);
        }
        public override bool TryCreate(JObject function, out FunctionDescriptor functionDescriptor)
        {
            functionDescriptor = null;

            string sourceFileName = (string)function["source"];
            string name = (string)function["name"];
            if (string.IsNullOrEmpty(name))
            {
                // if a method name isn't explicitly provided, derive it
                // from the script file name
                name = Path.GetFileNameWithoutExtension(sourceFileName);
                name = name.Substring(0, 1).ToUpper() + name.Substring(1);
            }

            string scriptFilePath = Path.Combine(_applicationRoot, "scripts", sourceFileName);
            ScriptInvoker invoker = new ScriptInvoker(scriptFilePath);

            JObject trigger = (JObject)function["trigger"];
            string triggerType = (string)trigger["type"];

            string parameterName = (string)trigger["name"];
            if (string.IsNullOrEmpty(parameterName))
            {
                // default the name to simply 'input'
                trigger["name"] = "input";
            }

            ParameterDescriptor triggerParameter = null;
            switch (triggerType)
            {
                case "queue":
                    triggerParameter = ParseQueueTrigger(trigger);
                    break;
                case "blob":
                    triggerParameter = ParseBlobTrigger(trigger);
                    break;
                case "serviceBus":
                    triggerParameter = ParseServiceBusTrigger(trigger);
                    break;
                case "timer":
                    triggerParameter = ParseTimerTrigger(trigger, typeof(TimerInfo));
                    break;
                case "webHook":
                    triggerParameter = ParseWebHookTrigger(trigger);
                    break;
            }

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

            // Add a TraceWriter for logging
            ParameterDescriptor textWriter = new ParameterDescriptor
            {
                Name = "log",
                Type = typeof(TextWriter)
            };
            parameters.Add(textWriter);

            functionDescriptor = new FunctionDescriptor
            {
                Name = name,
                Invoker = invoker,
                Parameters = parameters
            };

            return true;
        }
Example #47
0
 public ZeroTouchVarArgNodeController(EngineController engineController,
                                      FunctionDescriptor zeroTouchDef) : base(engineController, zeroTouchDef)
 {
 }
Example #48
0
 public DSVarArgFunction(FunctionDescriptor definition)
 {
     Definition = definition;
     Initialize();
 }
 public IListenerFactory CreateListenerFactory(FunctionDescriptor descriptor, ITriggeredFunctionExecutor executor)
 {
     if (_queueName != null)
     {
         return new ServiceBusQueueListenerFactory(_account, _queueName, executor, _accessRights);
     }
     else
     {
         return new ServiceBusSubscriptionListenerFactory(_account, _topicName, _subscriptionName, executor, _accessRights);
     }
 }
Example #50
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="DSFunction"/> class.
 /// </summary>
 /// <param name="description">EFunction descritor.</param>
 public DSFunction(FunctionDescriptor functionDescription)
     : base(new ZeroTouchNodeController <FunctionDescriptor>(functionDescription))
 {
 }
Example #51
0
 public DSVarArgFunction(FunctionDescriptor descriptor)
     : base(new ZeroTouchVarArgNodeController <FunctionDescriptor>(descriptor))
 {
     VarInputController = new ZeroTouchVarInputController(this);
 }
        public QueueListener(QueueClient queue,
                             QueueClient poisonQueue,
                             ITriggerExecutor <QueueMessage> triggerExecutor,
                             IWebJobsExceptionHandler exceptionHandler,
                             ILoggerFactory loggerFactory,
                             SharedQueueWatcher sharedWatcher,
                             QueuesOptions queueOptions,
                             IQueueProcessorFactory queueProcessorFactory,
                             FunctionDescriptor functionDescriptor,
                             string functionId           = null,
                             TimeSpan?maxPollingInterval = null)
        {
            if (queueOptions == null)
            {
                throw new ArgumentNullException(nameof(queueOptions));
            }

            if (queueProcessorFactory == null)
            {
                throw new ArgumentNullException(nameof(queueProcessorFactory));
            }

            if (loggerFactory == null)
            {
                throw new ArgumentNullException(nameof(loggerFactory));
            }

            if (queueOptions.BatchSize <= 0)
            {
                throw new ArgumentException("BatchSize must be greater than zero.");
            }

            if (queueOptions.MaxDequeueCount <= 0)
            {
                throw new ArgumentException("MaxDequeueCount must be greater than zero.");
            }

            _timer              = new TaskSeriesTimer(this, exceptionHandler, Task.Delay(0));
            _queue              = queue;
            _poisonQueue        = poisonQueue;
            _triggerExecutor    = triggerExecutor;
            _exceptionHandler   = exceptionHandler;
            _queueOptions       = queueOptions;
            _logger             = loggerFactory.CreateLogger <QueueListener>();
            _functionDescriptor = functionDescriptor ?? throw new ArgumentNullException(nameof(functionDescriptor));
            _functionId         = functionId ?? _functionDescriptor.Id;

            // if the function runs longer than this, the invisibility will be updated
            // on a timer periodically for the duration of the function execution
            _visibilityTimeout = TimeSpan.FromMinutes(10);

            if (sharedWatcher != null)
            {
                // Call Notify whenever a function adds a message to this queue.
                sharedWatcher.Register(queue.Name, this);
                _sharedWatcher = sharedWatcher;
            }

            EventHandler <PoisonMessageEventArgs> poisonMessageEventHandler = _sharedWatcher != null ? OnMessageAddedToPoisonQueue : (EventHandler <PoisonMessageEventArgs>)null;

            _queueProcessor = CreateQueueProcessor(_queue, _poisonQueue, loggerFactory, queueProcessorFactory, _queueOptions, poisonMessageEventHandler);

            TimeSpan maximumInterval = _queueProcessor.MaxPollingInterval;

            if (maxPollingInterval.HasValue && maximumInterval > maxPollingInterval.Value)
            {
                // enforce the maximum polling interval if specified
                maximumInterval = maxPollingInterval.Value;
            }

            _delayStrategy = new RandomizedExponentialBackoffStrategy(SharedQueuePollingIntervals.Minimum, maximumInterval);

            _scaleMonitorDescriptor          = new ScaleMonitorDescriptor($"{_functionId}-QueueTrigger-{_queue.Name}".ToLower(CultureInfo.InvariantCulture));
            _shutdownCancellationTokenSource = new CancellationTokenSource();
        }
        internal static bool TryGetFunctionFromException(Collection<FunctionDescriptor> functions, Exception exception, out FunctionDescriptor function)
        {
            function = null;

            string errorStack = exception.ToString().ToLowerInvariant();
            foreach (var currFunction in functions)
            {
                // For each function, we search the entire error stack trace to see if it contains
                // the function entry/primary script path. If it does, we're virtually certain that
                // that function caused the error (e.g. as in the case of global unhandled exceptions
                // coming from Node.js scripts).
                // We use the directory name for the script rather than the full script path itself to ensure
                // that we handle cases where the error might be coming from some other script (e.g. an NPM
                // module) that is part of the function.
                string absoluteScriptPath = Path.GetFullPath(currFunction.Metadata.Source).ToLowerInvariant();
                string functionDirectory = Path.GetDirectoryName(absoluteScriptPath);
                if (errorStack.Contains(functionDirectory))
                {
                    function = currFunction;
                    return true;
                }
            }

            return false;
        }
Example #54
0
 public FunctionInstanceFactory(IFunctionBinding binding, IFunctionInvoker invoker, FunctionDescriptor descriptor)
 {
     _binding    = binding;
     _invoker    = invoker;
     _descriptor = descriptor;
 }
 public IListenerFactory CreateListenerFactory(FunctionDescriptor descriptor, ITriggeredFunctionExecutor executor)
 {
     return new QueueListenerFactory(_queue, _queueConfiguration, _backgroundExceptionDispatcher, 
         _messageEnqueuedWatcherSetter, _sharedContextProvider, _log, executor);
 }
Example #56
0
 public void Add(IFunctionDefinition function, FunctionDescriptor descriptor, MethodInfo method)
 {
     Functions.Add(descriptor);
 }
Example #57
0
 private void AddFunction(string name, FunctionDescriptor.FunctionGroup functionGroup, 
     string[] alternates, Functor functor, string description)
 {
     _functionList.Add(
         new FunctionDescriptor(
             name,
             functionGroup,
             alternates,
             functor,
             description
         )
     );
 }
Example #58
0
        internal static bool TryGetFunctionFromException(ICollection <FunctionDescriptor> functions, Exception exception, out FunctionDescriptor function)
        {
            function = null;
            if (functions == null)
            {
                return(false);
            }
            string errorStack = exception.ToString().ToLowerInvariant();

            foreach (var currFunction in functions)
            {
                // For each function, we search the entire error stack trace to see if it contains
                // the function entry/primary script path. If it does, we're virtually certain that
                // that function caused the error (e.g. as in the case of global unhandled exceptions
                // coming from Node.js scripts).
                // We use the directory name for the script rather than the full script path itself to ensure
                // that we handle cases where the error might be coming from some other script (e.g. an NPM
                // module) that is part of the function.
                string absoluteScriptPath = Path.GetFullPath(currFunction.Metadata.ScriptFile).ToLowerInvariant();
                string functionDirectory  = Path.GetDirectoryName(absoluteScriptPath);
                if (errorStack.Contains(functionDirectory))
                {
                    function = currFunction;
                    return(true);
                }
            }

            return(false);
        }
 /// <summary>
 /// Creates a new instance
 /// </summary>
 /// <param name="descriptor">The <see cref="FunctionDescriptor"/> to create a listener for.</param>
 /// <param name="executor">The <see cref="ITriggeredFunctionExecutor"/> that should be used to invoke the
 /// target job function when the trigger fires.</param>
 /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
 public ListenerFactoryContext(FunctionDescriptor descriptor, ITriggeredFunctionExecutor executor, CancellationToken cancellationToken)
 {
     Descriptor = descriptor;
     Executor = executor;
     CancellationToken = cancellationToken;
 }
Example #60
0
 public ListenerFactory(FunctionDescriptor descriptor, ITriggeredFunctionExecutor executor, ITriggerBinding binding)
 {
     _descriptor = descriptor;
     _executor   = executor;
     _binding    = binding;
 }