Пример #1
0
        public override async Task EvaluateScript(IAsyncStreamReader <global::Qlik.Sse.BundledRows> requestStream, IServerStreamWriter <global::Qlik.Sse.BundledRows> responseStream, ServerCallContext context)
        {
            ScriptRequestHeader scriptHeader;
            CommonRequestHeader commonHeader;
            RserveConnection    rserveConn;
            int reqHash = requestStream.GetHashCode();

            if (!(capabilities.AllowScript))
            {
                throw new RpcException(new Status(StatusCode.PermissionDenied, $"Script evaluations disabled"));
            }

            try
            {
                rserveConn = connPool.GetConnection(rservePara);

                var header = GetHeader(context.RequestHeaders, "qlik-scriptrequestheader-bin");
                scriptHeader = ScriptRequestHeader.Parser.ParseFrom(header);

                var commonRequestHeader = GetHeader(context.RequestHeaders, "qlik-commonrequestheader-bin");
                commonHeader = CommonRequestHeader.Parser.ParseFrom(commonRequestHeader);

                logger.Info($"EvaluateScript called from client ({context.Peer}), hashid ({reqHash})");
                logger.Debug($"EvaluateScript header info: AppId ({commonHeader.AppId}), UserId ({commonHeader.UserId}), Cardinality ({commonHeader.Cardinality} rows)");
            }
            catch (Exception e)
            {
                logger.Error($"EvaluateScript with hashid ({reqHash}) failed: {e.Message}");
                throw new RpcException(new Status(StatusCode.DataLoss, e.Message));
            }

            try
            {
                var stopwatch = new Stopwatch();
                stopwatch.Start();

                var paramnames = $"EvaluateScript call with hashid({reqHash}) got Param names: ";

                foreach (var param in scriptHeader.Params)
                {
                    paramnames += $" {param.Name}";
                }
                logger.Info("{0}", paramnames);

                SexpList inputDataFrame = null;

                if (scriptHeader.Params != null && scriptHeader.Params.Count > 0)
                {
                    inputDataFrame = await AddInputData(scriptHeader.Params.ToArray(), requestStream);
                }

                var rResult = await EvaluateScriptInRserve(inputDataFrame, reqHash, scriptHeader.Script, rserveConn);

                // Disable caching (uncomment line below and comment next line if you do not want the results sent to Qlik to be cached in Qlik)
                //await GenerateResult(rResult, responseStream, context, cacheResultInQlik: false);
                await GenerateResult(rResult, responseStream, context);

                stopwatch.Stop();
                logger.Debug($"Took {stopwatch.ElapsedMilliseconds} ms, hashid ({reqHash})");
            }
            catch (Exception e)
            {
                throw new RpcException(new Status(StatusCode.InvalidArgument, $"{e.Message}"));
            }
            finally
            {
                //
            }
        }
Пример #2
0
        /// <summary>
        /// All requests are processed through evaluate script, however in the context of this connector, the script is a JSON notation string which contains the metadata required to correctly process the attached data.
        /// </summary>
        public override async Task EvaluateScript(IAsyncStreamReader <global::Qlik.Sse.BundledRows> requestStream, IServerStreamWriter <global::Qlik.Sse.BundledRows> responseStream, ServerCallContext context)
        {
            ScriptRequestHeader scriptHeader;
            CommonRequestHeader commonHeader;

            Qlik2DataRobotMetrics.RequestCounter.Inc();
            int reqHash = requestStream.GetHashCode();

            try
            {
                var header = GetHeader(context.RequestHeaders, "qlik-scriptrequestheader-bin");
                scriptHeader = ScriptRequestHeader.Parser.ParseFrom(header);

                var commonRequestHeader = GetHeader(context.RequestHeaders, "qlik-commonrequestheader-bin");
                commonHeader = CommonRequestHeader.Parser.ParseFrom(commonRequestHeader);

                Logger.Info($"{reqHash} - EvaluateScript called from client ({context.Peer}), hashid ({reqHash})");
                Logger.Debug($"{reqHash} - EvaluateScript header info: AppId ({commonHeader.AppId}), UserId ({commonHeader.UserId}), Cardinality ({commonHeader.Cardinality} rows)");
            }
            catch (Exception e)
            {
                Logger.Error($"EvaluateScript with hashid ({reqHash}) failed: {e.Message}");
                throw new RpcException(new Status(StatusCode.DataLoss, e.Message));
            }

            try
            {
                var stopwatch = new Stopwatch();
                stopwatch.Start();

                var paramnames = $"{reqHash} - EvaluateScript call with hashid({reqHash}) got Param names: ";

                foreach (var param in scriptHeader.Params)
                {
                    paramnames += $" {param.Name}";
                }
                Logger.Trace("{0}", paramnames);

                Logger.Trace(scriptHeader.Script);
                Dictionary <string, dynamic> config = JsonConvert.DeserializeObject <Dictionary <string, dynamic> >(scriptHeader.Script);

                var Params = GetParams(scriptHeader.Params.ToArray());

                string keyname = null;
                if (config.ContainsKey("keyfield"))
                {
                    keyname = Convert.ToString(config["keyfield"]);
                }


                ResultDataColumn keyField = new ResultDataColumn();
                var rowdatastream         = await ConvertBundledRowsToCSV(Params, requestStream, context, keyField, keyname);

                Logger.Debug($"{reqHash} - Input Data Size: {rowdatastream.Length}");

                var outData = await SelectFunction(config, rowdatastream, reqHash);

                rowdatastream = null;

                bool shouldCache = false;

                if (config.ContainsKey("should_cache"))
                {
                    shouldCache = config["should_cache"];
                }

                bool inc_details = false;
                bool rawExplain  = false;
                if (config.ContainsKey("inc_details"))
                {
                    inc_details = config["inc_details"];
                }

                if (config.ContainsKey("explain"))
                {
                    rawExplain = config["explain"]["return_raw"];
                }

                string request_type = config["request_type"];

                await GenerateResult(request_type, outData, responseStream, context, reqHash, cacheResultInQlik : shouldCache, keyField : keyField, keyname : keyname, includeDetail : inc_details, rawExplain : rawExplain);

                outData = null;
                stopwatch.Stop();
                Logger.Debug($"{reqHash} - Took {stopwatch.ElapsedMilliseconds} ms, hashid ({reqHash})");
                Qlik2DataRobotMetrics.DurHist.Observe(stopwatch.ElapsedMilliseconds / 1000);
            }
            catch (Exception e)
            {
                Logger.Error($"{reqHash} - ERROR: {e.Message}");
                throw new RpcException(new Status(StatusCode.InvalidArgument, $"{e.Message}"));
            }
            finally
            {
            }

            GC.Collect();
        }
Пример #3
0
        public override async Task ExecuteFunction(IAsyncStreamReader <BundledRows> requestStream, IServerStreamWriter <BundledRows> responseStream, ServerCallContext context)
        {
            FunctionRequestHeader functionHeader;
            CommonRequestHeader   commonHeader;
            RserveConnection      rserveConn;
            int reqHash = requestStream.GetHashCode();

            Qlik.Sse.FunctionDefinition sseFunction;
            DefinedFunctions.Function   internalFunction;

            if (nrOfDefinedFunctions == 0)
            {
                throw new RpcException(new Status(StatusCode.Unimplemented, $"No functions defined"));
            }

            try
            {
                rserveConn = connPool.GetConnection(rservePara);

                var header = GetHeader(context.RequestHeaders, "qlik-functionrequestheader-bin");
                functionHeader = FunctionRequestHeader.Parser.ParseFrom(header);

                var commonRequestHeader = GetHeader(context.RequestHeaders, "qlik-commonrequestheader-bin");
                commonHeader = CommonRequestHeader.Parser.ParseFrom(commonRequestHeader);

                logger.Info($"ExecuteFunction: FunctionId ({functionHeader.FunctionId}), from client ({context.Peer}), hashid ({reqHash})");
                logger.Debug($"ExecuteFunction header info: AppId ({commonHeader.AppId}), UserId ({commonHeader.UserId}), Cardinality ({commonHeader.Cardinality} rows)");

                int funcIndex = definedFunctions.GetIndexOfFuncId(functionHeader.FunctionId);

                if (funcIndex < 0)
                {
                    throw new Exception($"FunctionId ({functionHeader.FunctionId}) is not a defined function");
                }
                sseFunction      = definedFunctions.sseFunctions[funcIndex];
                internalFunction = definedFunctions.funcDefs.functions[funcIndex];
            }
            catch (Exception e)
            {
                logger.Error($"ExecuteFunction with hashid ({reqHash}) failed: {e.Message}");
                throw new RpcException(new Status(StatusCode.DataLoss, e.Message));
            }

            try
            {
                var stopwatch = new Stopwatch();
                stopwatch.Start();

                SexpList inputDataFrame = null;

                if (sseFunction.Params.Count > 0)
                {
                    inputDataFrame = await AddInputData(sseFunction.Params.ToArray(), requestStream);
                }

                var rResult = await EvaluateScriptInRserve(inputDataFrame, reqHash, internalFunction.FunctionRScript.Replace("\r", " "), rserveConn);

                await GenerateResult(rResult, responseStream, context, true, sseFunction.ReturnType, internalFunction.CacheResultInQlik);

                stopwatch.Stop();
                logger.Debug($"Took {stopwatch.ElapsedMilliseconds} ms, hashid ({reqHash})");
            }
            catch (Exception e)
            {
                throw new RpcException(new Status(StatusCode.InvalidArgument, $"{e.Message}"));
            }
            finally
            {
                //
            }
        }
Пример #4
0
        /// <summary>
        /// Convert the input data into a CSV file within memory stream
        /// </summary>
        private async Task <MemoryStream> ConvertBundledRowsToCSV(ParameterData[] Parameters, IAsyncStreamReader <global::Qlik.Sse.BundledRows> requestStream, ServerCallContext context, ResultDataColumn keyField, string keyname)
        {
            int reqHash = requestStream.GetHashCode();

            Logger.Debug($"{reqHash} - Start Create CSV");

            var memStream    = new MemoryStream();
            var streamWriter = new StreamWriter(memStream);
            var tw           = TextWriter.Synchronized(streamWriter);
            var csv          = new CsvWriter(tw);

            var keyindex = 0;

            for (int i = 0; i < Parameters.Length; i++)
            {
                var param = Parameters[i];
                if (keyname != null)
                {
                    if (param.ParamName == keyname)
                    {
                        keyindex          = i;
                        keyField.Name     = param.ParamName;
                        keyField.DataType = param.DataType;
                        switch (param.DataType)
                        {
                        case DataType.Numeric:
                        case DataType.Dual:
                            keyField.Numerics = new List <double>();
                            break;

                        case DataType.String:
                            keyField.Strings = new List <string>();
                            break;
                        }
                    }
                }

                csv.WriteField(param.ParamName);
            }

            if (keyField.Name == null && keyname != null)
            {
                throw new Exception("The keyfield was not found in the source data, please ensure you are including this field in the dataset sent from Qlik.");
            }


            csv.NextRecord();
            Logger.Debug($"{reqHash} - Finished Header");
            int a = 0;

            while (await requestStream.MoveNext())
            {
                foreach (var Row in requestStream.Current.Rows)
                {
                    for (int i = 0; i < Parameters.Length; i++)
                    {
                        var param = Parameters[i];
                        var dual  = Row.Duals[i];
                        switch (param.DataType)
                        {
                        case DataType.Numeric:

                            if (keyindex == i && keyname != null)
                            {
                                keyField.Numerics.Add(dual.NumData);
                            }
                            csv.WriteField(dual.NumData.ToString());
                            break;

                        case DataType.String:
                            if (keyindex == i && keyname != null)
                            {
                                keyField.Strings.Add(dual.StrData);
                            }
                            csv.WriteField(dual.StrData);
                            break;

                        case DataType.Dual:
                            if (keyindex == i && keyname != null)
                            {
                                keyField.Numerics.Add(dual.NumData);
                            }
                            csv.WriteField(dual.NumData.ToString());
                            break;
                        }
                    }

                    a++;
                    csv.NextRecord();
                }
            }
            csv.Flush();
            tw.Flush();
            streamWriter.Flush();
            memStream.Flush();

            memStream.Position = 0;
            Logger.Debug($"{reqHash} - Rows" + a);

            if (a == 0)
            {
                throw new Exception("There were no rows in the table sent from Qlik. Check that the table has at least 1 row of data.");
            }

            return(await Task.FromResult(memStream));
        }