public async Task ShutdownChannelsIfExistsAsync_StopsWorkerInvocations()
        {
            IRpcWorkerChannel javaWorkerChannel = CreateTestChannel(RpcWorkerConstants.JavaLanguageWorkerName);
            Guid invocationId = Guid.NewGuid();
            ScriptInvocationContext scriptInvocationContext = new ScriptInvocationContext()
            {
                ExecutionContext = new ExecutionContext()
                {
                    InvocationId = invocationId
                }
            };

            (javaWorkerChannel as TestRpcWorkerChannel).SendInvocationRequest(scriptInvocationContext);
            Assert.True(javaWorkerChannel.IsExecutingInvocation(invocationId.ToString()));
            Exception workerException = new Exception("Worker exception");
            // Channel is removed immediately but is not failed immediately
            await _rpcWorkerChannelManager.ShutdownChannelIfExistsAsync(RpcWorkerConstants.JavaLanguageWorkerName, javaWorkerChannel.Id, workerException);

            Assert.Null(_rpcWorkerChannelManager.GetChannels(RpcWorkerConstants.JavaLanguageWorkerName));

            var initializedChannel = await _rpcWorkerChannelManager.GetChannelAsync(RpcWorkerConstants.JavaLanguageWorkerName);

            Assert.Null(initializedChannel);
            // Execution will be terminated in the background - giving it 10 seconds
            await TestHelpers.Await(() =>
            {
                return(!javaWorkerChannel.IsExecutingInvocation(invocationId.ToString()));
            }, 10000);

            Assert.False(javaWorkerChannel.IsExecutingInvocation(invocationId.ToString()));
        }
Esempio n. 2
0
        public static InvocationRequest ToRpcInvocationRequest(this ScriptInvocationContext context, bool isTriggerMetadataPopulatedByWorker, ILogger logger, Capabilities capabilities)
        {
            InvocationRequest invocationRequest = new InvocationRequest()
            {
                FunctionId   = context.FunctionMetadata.FunctionId,
                InvocationId = context.ExecutionContext.InvocationId.ToString(),
                TraceContext = GetRpcTraceContext(context.Traceparent, context.Tracestate, context.Attributes, logger),
            };

            foreach (var pair in context.BindingData)
            {
                if (pair.Value != null)
                {
                    if ((pair.Value is HttpRequest) && isTriggerMetadataPopulatedByWorker)
                    {
                        continue;
                    }
                    invocationRequest.TriggerMetadata.Add(pair.Key, pair.Value.ToRpc(logger, capabilities));
                }
            }
            foreach (var input in context.Inputs)
            {
                invocationRequest.InputData.Add(new ParameterBinding()
                {
                    Name = input.name,
                    Data = input.val.ToRpc(logger, capabilities)
                });
            }

            return(invocationRequest);
        }
Esempio n. 3
0
        public async Task Drain_Verify()
        {
            var              resultSource = new TaskCompletionSource <ScriptInvocationResult>();
            Guid             invocationId = Guid.NewGuid();
            RpcWorkerChannel channel      = new RpcWorkerChannel(
                _workerId,
                _eventManager,
                _testWorkerConfig,
                _mockrpcWorkerProcess.Object,
                _logger,
                _metricsLogger,
                0,
                _testEnvironment,
                _hostOptionsMonitor);

            channel.SetupFunctionInvocationBuffers(GetTestFunctionsList("node"));
            ScriptInvocationContext scriptInvocationContext = GetTestScriptInvocationContext(invocationId, resultSource);
            await channel.SendInvocationRequest(scriptInvocationContext);

            Task result = channel.DrainInvocationsAsync();

            Assert.NotEqual(result.Status, TaskStatus.RanToCompletion);
            channel.InvokeResponse(new InvocationResponse
            {
                InvocationId = invocationId.ToString(),
                Result       = new StatusResult
                {
                    Status = StatusResult.Types.Status.Success
                },
            });
            await result;

            Assert.Equal(result.Status, TaskStatus.RanToCompletion);
        }
        internal void SendInvocationRequest(ScriptInvocationContext context)
        {
            try
            {
                if (_functionLoadErrors.ContainsKey(context.FunctionMetadata.FunctionId))
                {
                    _workerChannelLogger.LogDebug($"Function {context.FunctionMetadata.Name} failed to load");
                    context.ResultSource.TrySetException(_functionLoadErrors[context.FunctionMetadata.FunctionId]);
                    _executingInvocations.TryRemove(context.ExecutionContext.InvocationId.ToString(), out ScriptInvocationContext _);
                }
                else
                {
                    if (context.CancellationToken.IsCancellationRequested)
                    {
                        context.ResultSource.SetCanceled();
                        return;
                    }
                    InvocationRequest invocationRequest = context.ToRpcInvocationRequest(IsTriggerMetadataPopulatedByWorker(), _workerChannelLogger, _workerCapabilities);
                    _executingInvocations.TryAdd(invocationRequest.InvocationId, context);

                    SendStreamingMessage(new StreamingMessage
                    {
                        InvocationRequest = invocationRequest
                    });
                }
            }
            catch (Exception invokeEx)
            {
                context.ResultSource.TrySetException(invokeEx);
            }
        }
Esempio n. 5
0
        internal async Task SendInvocationRequest(ScriptInvocationContext context)
        {
            try
            {
                if (_functionLoadErrors.ContainsKey(context.FunctionMetadata.GetFunctionId()))
                {
                    _workerChannelLogger.LogDebug($"Function {context.FunctionMetadata.Name} failed to load");
                    context.ResultSource.TrySetException(_functionLoadErrors[context.FunctionMetadata.GetFunctionId()]);
                    _executingInvocations.TryRemove(context.ExecutionContext.InvocationId.ToString(), out ScriptInvocationContext _);
                }
                else
                {
                    if (context.CancellationToken.IsCancellationRequested)
                    {
                        context.ResultSource.SetCanceled();
                        return;
                    }
                    var invocationRequest = await context.ToRpcInvocationRequest(_workerChannelLogger, _workerCapabilities, _isSharedMemoryDataTransferEnabled, _sharedMemoryManager);

                    _executingInvocations.TryAdd(invocationRequest.InvocationId, context);

                    SendStreamingMessage(new StreamingMessage
                    {
                        InvocationRequest = invocationRequest
                    });
                }
            }
            catch (Exception invokeEx)
            {
                context.ResultSource.TrySetException(invokeEx);
            }
        }
        public void TestSetRetryContext_Retry()
        {
            ScriptInvocationContext context = new ScriptInvocationContext()
            {
                ExecutionContext = new ExecutionContext()
                {
                    RetryContext = new Host.RetryContext()
                    {
                        RetryCount    = 1,
                        MaxRetryCount = 2,
                        Exception     = new Exception("test")
                    }
                }
            };
            HttpScriptInvocationContext testContext = new HttpScriptInvocationContext()
            {
                Data     = new Dictionary <string, object>(),
                Metadata = new Dictionary <string, object>()
            };

            ScriptInvocationContextExtensions.SetRetryContext(context, testContext);
            var retryContext = (RetryContext)testContext.Metadata["RetryContext"];

            Assert.NotNull(retryContext);
            Assert.Equal(retryContext.RetryCount, context.ExecutionContext.RetryContext.RetryCount);
            Assert.Equal(retryContext.MaxRetryCount, context.ExecutionContext.RetryContext.MaxRetryCount);
            Assert.NotNull(retryContext.Exception);
        }
Esempio n. 7
0
        public void SendInvocationRequest_IsInExecutingInvocation()
        {
            ScriptInvocationContext scriptInvocationContext = GetTestScriptInvocationContext(Guid.NewGuid(), null);

            _workerChannel.SendInvocationRequest(scriptInvocationContext);
            Assert.True(_workerChannel.IsExecutingInvocation(scriptInvocationContext.ExecutionContext.InvocationId.ToString()));
            Assert.False(_workerChannel.IsExecutingInvocation(Guid.NewGuid().ToString()));
        }
Esempio n. 8
0
 public Task InvokeAsync(ScriptInvocationContext scriptInvocationContext)
 {
     if (scriptInvocationContext.FunctionMetadata.IsHttpInAndOutFunction)
     {
         return(ProcessHttpInAndOutInvocationRequest(scriptInvocationContext));
     }
     return(ProcessDefaultInvocationRequest(scriptInvocationContext));
 }
Esempio n. 9
0
        internal void SendInvocationRequest(ScriptInvocationContext context)
        {
            try
            {
                if (_functionLoadErrors.ContainsKey(context.FunctionMetadata.FunctionId))
                {
                    _workerChannelLogger.LogDebug($"Function {context.FunctionMetadata.Name} failed to load");
                    context.ResultSource.TrySetException(_functionLoadErrors[context.FunctionMetadata.FunctionId]);
                    _executingInvocations.TryRemove(context.ExecutionContext.InvocationId.ToString(), out ScriptInvocationContext _);
                }
                else
                {
                    if (context.CancellationToken.IsCancellationRequested)
                    {
                        context.ResultSource.SetCanceled();
                        return;
                    }

                    var functionMetadata = context.FunctionMetadata;

                    InvocationRequest invocationRequest = new InvocationRequest()
                    {
                        FunctionId   = functionMetadata.FunctionId,
                        InvocationId = context.ExecutionContext.InvocationId.ToString(),
                    };
                    foreach (var pair in context.BindingData)
                    {
                        if (pair.Value != null)
                        {
                            if ((pair.Value is HttpRequest) && IsTriggerMetadataPopulatedByWorker())
                            {
                                continue;
                            }
                            invocationRequest.TriggerMetadata.Add(pair.Key, pair.Value.ToRpc(_workerChannelLogger, _workerCapabilities));
                        }
                    }
                    foreach (var input in context.Inputs)
                    {
                        invocationRequest.InputData.Add(new ParameterBinding()
                        {
                            Name = input.name,
                            Data = input.val.ToRpc(_workerChannelLogger, _workerCapabilities)
                        });
                    }

                    _executingInvocations.TryAdd(invocationRequest.InvocationId, context);

                    SendStreamingMessage(new StreamingMessage
                    {
                        InvocationRequest = invocationRequest
                    });
                }
            }
            catch (Exception invokeEx)
            {
                context.ResultSource.TrySetException(invokeEx);
            }
        }
        private static async Task LogHttpContent(ScriptInvocationContext scriptInvocationContext, HttpContent httpContent)
        {
            string stringContent = await GetHttpContentAsString(httpContent);

            if (!string.IsNullOrEmpty(stringContent))
            {
                scriptInvocationContext.Logger.LogTrace($"{stringContent}");
            }
        }
Esempio n. 11
0
        public void SendInvocationRequest_PublishesOutboundEvent()
        {
            ScriptInvocationContext scriptInvocationContext = GetTestScriptInvocationContext(Guid.NewGuid(), null);

            _workerChannel.SendInvocationRequest(scriptInvocationContext);
            var traces = _logger.GetLogMessages();

            Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, _expectedLogMsg)));
        }
Esempio n. 12
0
        public void TestSetRetryContext_NoRetry()
        {
            ScriptInvocationContext context = new ScriptInvocationContext()
            {
                ExecutionContext = new ExecutionContext()
            };
            InvocationRequest request = new InvocationRequest();

            Grpc.ScriptInvocationContextExtensions.SetRetryContext(context, request);

            Assert.Null(request.RetryContext);
        }
Esempio n. 13
0
        public static async Task <InvocationRequest> ToRpcInvocationRequest(this ScriptInvocationContext context, ILogger logger, GrpcCapabilities capabilities)
        {
            bool excludeHttpTriggerMetadata = !string.IsNullOrEmpty(capabilities.GetCapabilityState(RpcWorkerConstants.RpcHttpTriggerMetadataRemoved));

            var invocationRequest = new InvocationRequest
            {
                FunctionId   = context.FunctionMetadata.GetFunctionId(),
                InvocationId = context.ExecutionContext.InvocationId.ToString(),
                TraceContext = GetRpcTraceContext(context.Traceparent, context.Tracestate, context.Attributes, logger),
            };

            var rpcValueCache = new Dictionary <object, TypedData>();

            foreach (var input in context.Inputs)
            {
                TypedData rpcValue = null;
                if (input.val == null || !rpcValueCache.TryGetValue(input.val, out rpcValue))
                {
                    rpcValue = await input.val.ToRpc(logger, capabilities);

                    if (input.val != null)
                    {
                        rpcValueCache.Add(input.val, rpcValue);
                    }
                }

                var parameterBinding = new ParameterBinding
                {
                    Name = input.name,
                    Data = rpcValue
                };
                invocationRequest.InputData.Add(parameterBinding);
            }

            foreach (var pair in context.BindingData)
            {
                if (ShouldSkipBindingData(pair, context, excludeHttpTriggerMetadata))
                {
                    continue;
                }

                if (!rpcValueCache.TryGetValue(pair.Value, out TypedData rpcValue))
                {
                    rpcValue = await pair.Value.ToRpc(logger, capabilities);

                    rpcValueCache.Add(pair.Value, rpcValue);
                }

                invocationRequest.TriggerMetadata.Add(pair.Key, rpcValue);
            }

            return(invocationRequest);
        }
Esempio n. 14
0
        internal async Task ProcessHttpInAndOutInvocationRequest(ScriptInvocationContext scriptInvocationContext)
        {
            _logger.LogDebug("Will invoke simple httpTrigger function: '{functionName}' invocationId: '{invocationId}'", scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);

            ScriptInvocationResult scriptInvocationResult = new ScriptInvocationResult()
            {
                Outputs = new Dictionary <string, object>()
            };

            HttpRequestMessage httpRequestMessage = null;

            (string name, DataType type, object request)input = scriptInvocationContext.Inputs.First();

            HttpRequest httpRequest = input.request as HttpRequest;

            if (httpRequest == null)
            {
                throw new InvalidOperationException($"HttpTrigger value for: `{input.name}` is null");
            }

            try
            {
                // Build HttpRequestMessage from HttpTrigger binding
                HttpRequestMessageFeature httpRequestMessageFeature = new HttpRequestMessageFeature(httpRequest.HttpContext);
                httpRequestMessage = httpRequestMessageFeature.HttpRequestMessage;

                AddRequestHeadersAndSetRequestUri(httpRequestMessage, scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId.ToString());

                // Populate query params from httpTrigger
                string httpWorkerUri = QueryHelpers.AddQueryString(httpRequestMessage.RequestUri.ToString(), httpRequest.GetQueryCollectionAsDictionary());
                httpRequestMessage.RequestUri = new Uri(httpWorkerUri);

                _logger.LogDebug("Sending http request message for simple httpTrigger function: '{functionName}' invocationId: '{invocationId}'", scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);

                HttpResponseMessage invocationResponse = await _httpClient.SendAsync(httpRequestMessage);

                _logger.LogDebug("Received http response for simple httpTrigger function: '{functionName}' invocationId: '{invocationId}'", scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);

                BindingMetadata httpOutputBinding = scriptInvocationContext.FunctionMetadata.OutputBindings.FirstOrDefault();
                if (httpOutputBinding != null)
                {
                    // handle http output binding
                    scriptInvocationResult.Outputs.Add(httpOutputBinding.Name, invocationResponse);
                    // handle $return
                    scriptInvocationResult.Return = invocationResponse;
                }
                scriptInvocationContext.ResultSource.SetResult(scriptInvocationResult);
            }
            catch (Exception responseEx)
            {
                scriptInvocationContext.ResultSource.TrySetException(responseEx);
            }
        }
Esempio n. 15
0
        public async Task SendInvocationRequest_InputsTransferredOverSharedMemory()
        {
            EnableSharedMemoryDataTransfer();

            // Send invocation which will be using RpcSharedMemory for the inputs
            ScriptInvocationContext scriptInvocationContext = GetTestScriptInvocationContextWithSharedMemoryInputs(Guid.NewGuid(), null);
            await _workerChannel.SendInvocationRequest(scriptInvocationContext);

            var traces = _logger.GetLogMessages();

            Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, _expectedLogMsg)));
        }
 internal static void SetRetryContext(ScriptInvocationContext scriptInvocationContext, HttpScriptInvocationContext httpScriptInvocationContext)
 {
     if (scriptInvocationContext.ExecutionContext.RetryContext != null)
     {
         var retryContext = scriptInvocationContext.ExecutionContext.RetryContext;
         httpScriptInvocationContext.Metadata["RetryContext"] = new RetryContext()
         {
             MaxRetryCount = retryContext.MaxRetryCount,
             RetryCount    = retryContext.RetryCount,
             Exception     = retryContext.Exception,
         };
     }
 }
 public Task InvokeAsync(ScriptInvocationContext scriptInvocationContext)
 {
     if (scriptInvocationContext.FunctionMetadata.IsHttpInAndOutFunction())
     {
         // type is empty for httpWorker section. EnableForwardingHttpRequest is opt-in for custom handler section.
         if (_httpWorkerOptions.Type == CustomHandlerType.None || _httpWorkerOptions.EnableForwardingHttpRequest)
         {
             return(ProcessHttpInAndOutInvocationRequest(scriptInvocationContext));
         }
         return(ProcessDefaultInvocationRequest(scriptInvocationContext));
     }
     return(ProcessDefaultInvocationRequest(scriptInvocationContext));
 }
Esempio n. 18
0
        public void InFlight_Functions_FailedWithException()
        {
            var resultSource = new TaskCompletionSource <ScriptInvocationResult>();
            ScriptInvocationContext scriptInvocationContext = GetTestScriptInvocationContext(Guid.NewGuid(), resultSource);

            _workerChannel.SendInvocationRequest(scriptInvocationContext);
            Assert.True(_workerChannel.IsExecutingInvocation(scriptInvocationContext.ExecutionContext.InvocationId.ToString()));
            Exception workerException = new Exception("worker failed");

            _workerChannel.TryFailExecutions(workerException);
            Assert.False(_workerChannel.IsExecutingInvocation(scriptInvocationContext.ExecutionContext.InvocationId.ToString()));
            Assert.Equal(TaskStatus.Faulted, resultSource.Task.Status);
            Assert.Equal(workerException, resultSource.Task.Exception.InnerException);
        }
        internal async Task ProcessHttpInAndOutInvocationRequest(ScriptInvocationContext scriptInvocationContext)
        {
            _logger.LogDebug("Will invoke simple httpTrigger function: '{functionName}' invocationId: '{invocationId}'", scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);

            ScriptInvocationResult scriptInvocationResult = new ScriptInvocationResult()
            {
                Outputs = new Dictionary <string, object>()
            };

            (string name, DataType type, object request)input = scriptInvocationContext.Inputs.First();

            HttpRequest httpRequest = input.request as HttpRequest;

            if (httpRequest == null)
            {
                throw new InvalidOperationException($"HttpTrigger value for: `{input.name}` is null");
            }

            try
            {
                string uriPathValue = GetPathValue(_httpWorkerOptions, scriptInvocationContext.FunctionMetadata.Name, httpRequest);
                string uri          = BuildAndGetUri(uriPathValue);

                using (HttpRequestMessage httpRequestMessage = httpRequest.ToHttpRequestMessage(uri))
                {
                    AddHeaders(httpRequestMessage, scriptInvocationContext.ExecutionContext.InvocationId.ToString());

                    _logger.LogDebug("Forwarding http request for httpTrigger function: '{functionName}' invocationId: '{invocationId}'", scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);
                    HttpResponseMessage invocationResponse = await _httpClient.SendAsync(httpRequestMessage);

                    _logger.LogDebug("Received http response for httpTrigger function: '{functionName}' invocationId: '{invocationId}'", scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);

                    BindingMetadata httpOutputBinding = scriptInvocationContext.FunctionMetadata.OutputBindings.FirstOrDefault();
                    if (httpOutputBinding != null)
                    {
                        // handle http output binding
                        scriptInvocationResult.Outputs.Add(httpOutputBinding.Name, invocationResponse);
                        // handle $return
                        scriptInvocationResult.Return = invocationResponse;
                    }
                    scriptInvocationContext.ResultSource.SetResult(scriptInvocationResult);
                }
            }
            catch (Exception responseEx)
            {
                scriptInvocationContext.ResultSource.TrySetException(responseEx);
            }
        }
        public async Task InvokeAsync(ScriptInvocationContext invocationContext)
        {
            try
            {
                IEnumerable <ILanguageWorkerChannel> workerChannels = GetInitializedWorkerChannels();
                var languageWorkerChannel = _functionDispatcherLoadBalancer.GetLanguageWorkerChannel(workerChannels, _maxProcessCount);
                BufferBlock <ScriptInvocationContext> bufferBlock = await GetFunctionInvocationBufferBlock(languageWorkerChannel, invocationContext.FunctionMetadata.FunctionId);

                _logger.LogDebug("Posting invocation id:{InvocationId} on workerId:{workerChannelId}", invocationContext.ExecutionContext.InvocationId, languageWorkerChannel.Id);
                languageWorkerChannel.FunctionInputBuffers[invocationContext.FunctionMetadata.FunctionId].Post(invocationContext);
            }
            catch (Exception invokeEx)
            {
                invocationContext.ResultSource.TrySetException(invokeEx);
            }
        }
        internal async Task ProcessDefaultInvocationRequest(ScriptInvocationContext scriptInvocationContext)
        {
            try
            {
                HttpScriptInvocationContext httpScriptInvocationContext = await scriptInvocationContext.ToHttpScriptInvocationContext();

                string uri = BuildAndGetUri(scriptInvocationContext.FunctionMetadata.Name);

                // Build httpRequestMessage from scriptInvocationContext
                using (HttpRequestMessage httpRequestMessage = httpScriptInvocationContext.ToHttpRequestMessage(uri))
                {
                    AddHeaders(httpRequestMessage, scriptInvocationContext.ExecutionContext.InvocationId.ToString());

                    _logger.LogDebug("Sending http request for function:{functionName} invocationId:{invocationId}", scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);
                    HttpResponseMessage response = await _httpClient.SendAsync(httpRequestMessage);

                    _logger.LogDebug("Received http response for function:{functionName} invocationId:{invocationId}", scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);

                    // Only process output bindings if response is succeess code
                    response.EnsureSuccessStatusCode();

                    HttpScriptInvocationResult httpScriptInvocationResult = await response.Content.ReadAsAsync <HttpScriptInvocationResult>();

                    if (httpScriptInvocationResult != null)
                    {
                        if (httpScriptInvocationResult.Outputs == null || !httpScriptInvocationResult.Outputs.Any())
                        {
                            _logger.LogWarning("Outputs not set on http response for invocationId:{invocationId}", scriptInvocationContext.ExecutionContext.InvocationId);
                        }
                        if (httpScriptInvocationResult.ReturnValue == null)
                        {
                            _logger.LogWarning("ReturnValue not set on http response for invocationId:{invocationId}", scriptInvocationContext.ExecutionContext.InvocationId);
                        }

                        ProcessLogsFromHttpResponse(scriptInvocationContext, httpScriptInvocationResult);

                        ScriptInvocationResult scriptInvocationResult = httpScriptInvocationResult.ToScriptInvocationResult(scriptInvocationContext);
                        scriptInvocationContext.ResultSource.SetResult(scriptInvocationResult);
                    }
                }
            }
            catch (Exception responseEx)
            {
                scriptInvocationContext.ResultSource.TrySetException(responseEx);
            }
        }
Esempio n. 22
0
        public Task <string> Get(int id)
        {
            if (_languageWorkerChannel == null)
            {
                _languageWorkerChannel = _functionDispatcher.WorkerChannels.FirstOrDefault();
            }
            ScriptInvocationContext invocationContext = new ScriptInvocationContext()
            {
                FunctionId   = id.ToString(),
                InvocationId = Guid.NewGuid().ToString(),
                ResultSource = new TaskCompletionSource <string>()
            };

            _languageWorkerChannel.SendInvocationRequest(invocationContext);
            return(invocationContext.ResultSource.Task);
            //return $"{id}-succeeed-{invocationContext.InvocationId}";
        }
        public async Task InvokeAsync(ScriptInvocationContext invocationContext)
        {
            // This could throw if no initialized workers are found. Shut down instance and retry.
            IEnumerable <IRpcWorkerChannel> workerChannels = await GetInitializedWorkerChannelsAsync();

            var rpcWorkerChannel = _functionDispatcherLoadBalancer.GetLanguageWorkerChannel(workerChannels, _maxProcessCount);

            if (rpcWorkerChannel.FunctionInputBuffers.TryGetValue(invocationContext.FunctionMetadata.GetFunctionId(), out BufferBlock <ScriptInvocationContext> bufferBlock))
            {
                _logger.LogTrace("Posting invocation id:{InvocationId} on workerId:{workerChannelId}", invocationContext.ExecutionContext.InvocationId, rpcWorkerChannel.Id);
                rpcWorkerChannel.FunctionInputBuffers[invocationContext.FunctionMetadata.GetFunctionId()].Post(invocationContext);
            }
            else
            {
                throw new InvalidOperationException($"Function:{invocationContext.FunctionMetadata.Name} is not loaded by the language worker: {rpcWorkerChannel.Id}");
            }
        }
        public void TestSetRetryContext_NoRetry()
        {
            ScriptInvocationContext scriptInvocationContext = new ScriptInvocationContext()
            {
                ExecutionContext = new ExecutionContext()
            };

            HttpScriptInvocationContext testContext = new HttpScriptInvocationContext()
            {
                Data     = new Dictionary <string, object>(),
                Metadata = new Dictionary <string, object>()
            };

            ScriptInvocationContextExtensions.SetRetryContext(scriptInvocationContext, testContext);

            Assert.Empty(testContext.Metadata);
        }
Esempio n. 25
0
        public void Invoke(ScriptInvocationContext context)
        {
            if (_functionLoadErrors.ContainsKey(context.FunctionMetadata.FunctionId))
            {
                _logger.LogTrace($"Function {context.FunctionMetadata.Name} failed to load");
                context.ResultSource.TrySetException(_functionLoadErrors[context.FunctionMetadata.FunctionId]);
                _executingInvocations.TryRemove(context.ExecutionContext.InvocationId.ToString(), out ScriptInvocationContext _);
            }
            else
            {
                if (context.CancellationToken.IsCancellationRequested)
                {
                    context.ResultSource.SetCanceled();
                    return;
                }

                var functionMetadata = context.FunctionMetadata;

                InvocationRequest invocationRequest = new InvocationRequest()
                {
                    FunctionId   = functionMetadata.FunctionId,
                    InvocationId = context.ExecutionContext.InvocationId.ToString(),
                };
                foreach (var pair in context.BindingData)
                {
                    invocationRequest.TriggerMetadata.Add(pair.Key, pair.Value.ToRpc());
                }
                foreach (var input in context.Inputs)
                {
                    invocationRequest.InputData.Add(new ParameterBinding()
                    {
                        Name = input.name,
                        Data = input.val.ToRpc()
                    });
                }

                _executingInvocations.TryAdd(invocationRequest.InvocationId, context);

                Send(new StreamingMessage
                {
                    InvocationRequest = invocationRequest
                });
            }
        }
Esempio n. 26
0
        private async Task <HttpResponseMessage> SendInvocationRequestAsync(ScriptInvocationContext scriptInvocationContext, HttpRequestMessage httpRequestMessage)
        {
            // Only log Request / Response when running locally
            if (_enableRequestTracing)
            {
                scriptInvocationContext.Logger.LogTrace($"Invocation Request:{httpRequestMessage}");
                await TraceHttpContent(httpRequestMessage.Content, scriptInvocationContext.Logger);
            }
            _logger.LogDebug("Sending http request for function:{functionName} invocationId:{invocationId}", scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);
            HttpResponseMessage invocationResponse = await _httpClient.SendAsync(httpRequestMessage);

            if (_enableRequestTracing)
            {
                scriptInvocationContext.Logger.LogTrace($"Invocation Response:{invocationResponse}");
                await TraceHttpContent(invocationResponse.Content, scriptInvocationContext.Logger);
            }
            _logger.LogDebug("Received http response for httpTrigger function: '{functionName}' invocationId: '{invocationId}'", scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);
            return(invocationResponse);
        }
        private async Task <HttpResponseMessage> SendInvocationRequestAsync(ScriptInvocationContext scriptInvocationContext, HttpRequestMessage httpRequestMessage)
        {
            // Only log Request / Response when running locally
            if (_enableRequestTracing)
            {
                scriptInvocationContext.Logger.LogTrace($"Invocation Request:{httpRequestMessage}");
                await LogHttpContent(scriptInvocationContext, httpRequestMessage.Content);
            }
            _logger.CustomHandlerSendingInvocation(scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);
            HttpResponseMessage invocationResponse = await _httpClient.SendAsync(httpRequestMessage);

            if (_enableRequestTracing)
            {
                scriptInvocationContext.Logger.LogTrace($"Invocation Response:{invocationResponse}");
                await LogHttpContent(scriptInvocationContext, invocationResponse.Content);
            }
            _logger.CustomHandlerReceivedInvocationResponse(scriptInvocationContext.FunctionMetadata.Name, scriptInvocationContext.ExecutionContext.InvocationId);
            return(invocationResponse);
        }
 public void Invoke(ScriptInvocationContext invocationContext)
 {
     try
     {
         IEnumerable <ILanguageWorkerChannel> workerChannels = GetInitializedWorkerChannels();
         var languageWorkerChannel = _functionDispatcherLoadBalancer.GetLanguageWorkerChannel(workerChannels, _maxProcessCount);
         if (languageWorkerChannel.FunctionInputBuffers.TryGetValue(invocationContext.FunctionMetadata.FunctionId, out BufferBlock <ScriptInvocationContext> bufferBlock))
         {
             _logger.LogDebug("Posting invocation id:{InvocationId} on workerId:{workerChannelId}", invocationContext.ExecutionContext.InvocationId, languageWorkerChannel.Id);
             languageWorkerChannel.FunctionInputBuffers[invocationContext.FunctionMetadata.FunctionId].Post(invocationContext);
         }
         else
         {
             throw new InvalidOperationException($"Function:{invocationContext.FunctionMetadata.Name} is not loaded by the language worker: {languageWorkerChannel.Id}");
         }
     }
     catch (Exception invokeEx)
     {
         invocationContext.ResultSource.TrySetException(invokeEx);
     }
 }
Esempio n. 29
0
 internal static void SetRetryContext(ScriptInvocationContext context, InvocationRequest invocationRequest)
 {
     if (context.ExecutionContext.RetryContext != null)
     {
         invocationRequest.RetryContext = new RetryContext()
         {
             RetryCount    = context.ExecutionContext.RetryContext.RetryCount,
             MaxRetryCount = context.ExecutionContext.RetryContext.MaxRetryCount
         };
         // RetryContext.Exception should not be null, check just in case
         if (context.ExecutionContext.RetryContext.Exception != null)
         {
             invocationRequest.RetryContext.Exception = new RpcException()
             {
                 Message    = ExceptionFormatter.GetFormattedException(context.ExecutionContext.RetryContext.Exception), // merge message from InnerException
                 StackTrace = context.ExecutionContext.RetryContext.Exception.StackTrace ?? string.Empty,
                 Source     = context.ExecutionContext.RetryContext.Exception.Source ?? string.Empty
             };
         }
     }
 }
 internal void ProcessLogsFromHttpResponse(ScriptInvocationContext scriptInvocationContext, HttpScriptInvocationResult invocationResult)
 {
     if (scriptInvocationContext == null)
     {
         throw new ArgumentNullException(nameof(scriptInvocationContext));
     }
     if (invocationResult == null)
     {
         throw new ArgumentNullException(nameof(invocationResult));
     }
     if (invocationResult.Logs != null)
     {
         // Restore the execution context from the original invocation. This allows AsyncLocal state to flow to loggers.
         System.Threading.ExecutionContext.Run(scriptInvocationContext.AsyncExecutionContext, (s) =>
         {
             foreach (var userLog in invocationResult.Logs)
             {
                 scriptInvocationContext.Logger?.LogInformation(userLog);
             }
         }, null);
     }
 }