public void Register(PluginInfo pluginInfo)
        {
            try
            {
                if (pluginInfo.Type != PluginType.BackgroundThread)
                {
                    throw new ArgumentException("Plugin must be a BackgroundThread type", nameof(pluginInfo));
                }

                var existing = _registrations.FirstOrDefault(r => r.PluginGuid.Equals(pluginInfo.Guid.ToString(), StringComparison.OrdinalIgnoreCase));

                if (existing == null)
                {
                    existing = BackgroundThreadPluginRegistration.Create(pluginInfo);
                    _registrations.Add(existing);
                }

                existing.CreateEndpointInstances(_hubContext);

                var list = Hubs.BackgroundPluginHub.BgPluginsList();
                _hubContext.Clients.Group(Hubs.BackgroundPluginHub.ADMIN_GROUP_NAME).SendAsync("updateList", list);
            }
            catch (Exception ex)
            {
                SessionLog.Error($"Failed to instantiate plugin '{pluginInfo.Name}' ({pluginInfo.Guid}) from assembly {pluginInfo.Assembly.FullName}. See exception that follows.");
                SessionLog.Exception(ex);
            }
        }
        private static void ProcessPluginExecutionExceptionHandlers(List <ExecutionPlugin> pluginList,
                                                                    SqlConnection con,
                                                                    Exception ex,
                                                                    string additionalInfo,
                                                                    string appTitle,
                                                                    string appVersion,
                                                                    out string externalRef)
        {
            externalRef = null;
            if (pluginList == null)
            {
                return;
            }

            foreach (var plugin in pluginList)
            {
                try
                {
                    string msg            = null;
                    string externalRefTmp = null;

                    plugin.OnExecutionException(con, ex, additionalInfo, appTitle, appVersion, out externalRefTmp, out msg);

                    if (!string.IsNullOrWhiteSpace(externalRefTmp))
                    {
                        externalRef = externalRefTmp;
                    }
                }
                catch (Exception e)
                {
                    SessionLog.Error("Plugin {0} OnExecutionException failed", plugin.Name);
                    SessionLog.Exception(e);
                }
            }
        }
示例#3
0
        // called after Endpoint is deserialized from the Settings json
        public async void AfterDeserializationInit()
        {
            if (!string.IsNullOrEmpty(this.PullMetadataFromEndpointId))
            {
                var srcEndPoint = Settings.SettingsInstance.Instance.FindEndpointById(this.PullMetadataFromEndpointId);

                if (srcEndPoint != null)
                {
                    var cachedRoutineList = await srcEndPoint._cachedRoutinesPromise.Task;
                    this.CachedRoutineList = cachedRoutineList;
                }
                else
                {
                    SessionLog.Error($"Endpoint {this.Pedigree} is configured to pull metadata from an endpoint with id {this.PullMetadataFromEndpointId} but that endpoint does not exist.");
                }
            }
            else
            {
                await this.LoadCacheAsync();
            }

            if (this.ExecutionConnection != null)
            {
                this.ExecutionConnection.Endpoint = this;
                this.ExecutionConnection.Type     = "execution";
            }

            if (this.MetadataConnection != null)
            {
                this.MetadataConnection.Endpoint = this;
                this.MetadataConnection.Type     = "metadata";
            }
        }
        public void Start()
        {
            if (_counterMonitor != null)
            {
                return;
            }

            _counterMonitor = new CounterMonitor(_pid, GetProviders());
            _counterMonitor.CounterUpdate += OnCounterUpdate;

            Task monitorTask = new Task(() =>
            {
                try
                {
                    _counterMonitor.Start();
                }
                catch (Exception x)
                {
                    SessionLog.Error("DotNet Counter failure");
                    SessionLog.Exception(x);
                    //   Environment.FailFast("Error while listening to counters", x);
                }
            });

            monitorTask.Start();
        }
示例#5
0
        public Connection GetSqlConnection()
        {
            if (this.ExecutionConnection == null)
            {
                SessionLog.Error($"Execution connection not found on endpoint '{this.Name}'({ this.Id }).");
            }

            return(this.ExecutionConnection);
        }
        public async Task <IActionResult> ScanPdf417(string blobRef, [FromQuery] bool?raw = false, [FromQuery] bool?veh = false, [FromQuery] bool?drv = false)
        {
            var res = this.Response;
            var req = this.Request;

            try
            {
                // always start off not caching whatever we send back
                res.Headers["Cache-Control"] = "no-cache, no-store, must-revalidate, max-age=0";
                res.Headers["Pragma"]        = "no-cache"; // HTTP 1.0.
                res.Headers["Content-Type"]  = "application/json";

                if (!BlobStore.Exists(blobRef))
                {
                    return(NotFound($"Invalid, non-existent or expired blob reference specified: '{blobRef}'"));
                }

                var blobData = BlobStore.Get(blobRef);

                var client = new System.Net.Http.HttpClient();

                using (var content = new System.Net.Http.ByteArrayContent(blobData.Data))
                {
                    var barcodeServiceUrl = this.config["AppSettings:BarcodeService.URL"].TrimEnd('/');
                    var postUrl           = $"{barcodeServiceUrl}/scan/pdf417?raw={raw}&veh={veh}&drv={drv}";

                    var response = await client.PostAsync(postUrl, content);

                    var responseText = await response.Content.ReadAsStringAsync();

                    if (response.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        var json = JsonConvert.DeserializeObject(responseText);

                        return(Ok(ApiResponse.Payload(json)));
                    }
                    else
                    {
                        SessionLog.Error("Barcode failed. postUrl = {0}; contentLength: {1}; responseText={2}", postUrl ?? "(null)", blobData?.Data?.Length ?? -1, responseText ?? "(null)");

                        //return StatusCode((int)response.StatusCode, responseText);
                        //return new ContentResult() { Content = responseText, StatusCode = (int)response.StatusCode, ContentType = "text/plain" };
                        return(BadRequest(responseText));
                    }
                }
            }
            catch (Exception ex)
            {
                return(Ok(ApiResponse.Exception(ex)));
            }
        }
示例#7
0
        private void ProcessMessagesLoop()
        {
            try
            {
                IsRunning = true;

                var nextFlush = DateTime.Now.AddSeconds(_flushTimeoutInSeconds);

                if (!string.IsNullOrWhiteSpace(_threadName))
                {
                    System.Threading.Thread.CurrentThread.Name = _threadName;
                }

                while (IsRunning && !Program.IsShuttingDown)
                {
                    // timeout or count trigger check
                    if (DateTime.Now >= nextFlush || _queue.Count >= _flushCountThreshold)
                    {
                        ProcessQueueUntilEmpty();

                        nextFlush = DateTime.Now.AddSeconds(_flushTimeoutInSeconds);
                    }

                    // perform any additional work that might be required
                    DoWork();

                    Thread.Sleep(60);
                }

                // flush any remaining items out
                ProcessQueueUntilEmpty();
                DoFinalWork();
            }
            catch (Exception ex)
            {
                Log.Error(ex, "ProcessMessagesLoop failed");
                ExceptionLogger.LogException(ex);
                SessionLog.Error("ProcessMessagesLoop failed");
                SessionLog.Exception(ex);
            }
            finally
            {
                IsRunning = false;
            }
        }
示例#8
0
        public void BuildAndCacheServerMethodJsAndTSD()
        {
            try
            {
                var registrations = ServerMethodManager.GetRegistrationsForApp(this);

                if (registrations.Count() > 0)
                {
                    this.GenerateX(registrations);
                }
                else
                {
                    this.ServerMethodJs = this.ServerMethodTSD = this.ServerMethodJsEtag = this.ServerMethodTSDEtag = null;
                }
            }
            catch (Exception ex)
            {
                SessionLog.Error($"Failed to generate ServerMethod output files for {this.Project.Name}/{this.Name}.See exception that follows.");
                SessionLog.Exception(ex);
            }
        }
        public static void Register(string pluginAssemblyInstanceId, PluginInfo pluginInfo)
        {
            try
            {
                var reg = ServerMethodPluginRegistration.Create(pluginAssemblyInstanceId, pluginInfo);

                lock (GlobalRegistrations)
                {
                    if (!GlobalRegistrations.ContainsKey(pluginAssemblyInstanceId))
                    {
                        GlobalRegistrations.Add(pluginAssemblyInstanceId, new List <ServerMethodPluginRegistration>());
                    }

                    GlobalRegistrations[pluginAssemblyInstanceId].Add(reg);
                }
            }
            catch (Exception ex)
            {
                SessionLog.Error($"Failed to instantiate plugin '{pluginInfo.Name}' ({pluginInfo.Guid}) from assembly {pluginInfo.Assembly.FullName}. See exception that follows.");
                SessionLog.Exception(ex);
            }
        }
示例#10
0
        // TODO: Consider reworking this - ExecPlugins should only get instantiated once?! The assembly is instantiated once so maybe creating new instances of the plugin class is not that bad?
        private static List <ExecutionPlugin> InitPlugins(Application app, Dictionary <string, string> queryString, Dictionary <string, string> requestHeaders)
        {
            var concretePlugins = new List <ExecutionPlugin>();

            if (PluginLoader.Instance.PluginAssemblies != null && app.Plugins != null)
            {
                foreach (string pluginGuid in app.Plugins)
                {
                    var plugin = PluginLoader.Instance
                                 .PluginAssemblies
                                 .SelectMany(a => a.Plugins)
                                 .Where(p => p.Type == PluginType.Execution)
                                 .FirstOrDefault(p => p.Guid.ToString().Equals(pluginGuid, StringComparison.OrdinalIgnoreCase));

                    if (plugin != null)
                    {
                        try
                        {
                            var concrete = (ExecutionPlugin)plugin.Assembly.CreateInstance(plugin.TypeInfo.FullName);

                            initPluginMethod.Invoke(concrete, new object[] { queryString, requestHeaders });

                            concretePlugins.Add(concrete);
                        }
                        catch (Exception ex)
                        {
                            SessionLog.Error("Failed to instantiate '{0}' ({1}) on assembly '{2}'", plugin.TypeInfo.FullName, pluginGuid, plugin.Assembly.FullName);
                            SessionLog.Exception(ex);
                            ExceptionLogger.LogExceptionThrottled(ex, "ExecController::InitPlugins", 2);
                        }
                    }
                }
            }

            return(concretePlugins);
        }
示例#11
0
        public static void ProcessMessagesLoop()
        {
            try
            {
                IsRunning = true;

                var flushTimeoutInSeconds      = 25;
                var checkpointTimeoutInSeconds = 3 * 60;

                var nextFlush      = DateTime.Now.AddSeconds(flushTimeoutInSeconds);
                var nextCheckpoint = DateTime.Now.AddSeconds(checkpointTimeoutInSeconds);

                System.Threading.Thread.CurrentThread.Name = "Stats DB";

                while (IsRunning && !Program.IsShuttingDown)
                {
                    // timeout or count trigger check
                    if (DateTime.Now >= nextFlush || _executionQueue.Count >= 100)
                    {
                        while (!_executionQueue.IsEmpty)
                        {
                            if (_executionQueue.TryDequeue(out var statsRoutineExecution))
                            {
                                InsertUpdate(statsRoutineExecution);
                            }
                        }

                        nextFlush = DateTime.Now.AddSeconds(flushTimeoutInSeconds);
                    }

                    // checkpoint
                    if (DateTime.Now >= nextCheckpoint)
                    {
                        _database.Checkpoint();

                        nextCheckpoint = DateTime.Now.AddSeconds(checkpointTimeoutInSeconds);
                    }

                    Thread.Sleep(60);
                }

                // flush any remaining items out
                while (!_executionQueue.IsEmpty)
                {
                    if (_executionQueue.TryDequeue(out var statsRoutineExecution))
                    {
                        InsertUpdate(statsRoutineExecution);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "StatsDB::ProcessMessagesLoop failed");
                SessionLog.Error("StatsDB::ProcessMessagesLoop failed");
                SessionLog.Exception(ex);
            }
            finally
            {
                IsRunning = false;
            }
        }
示例#12
0
        public (plugin.ServerMethodPlugin, ServerMethodRegistrationMethod /*matched Method*/, string /*error*/) GetServerMethodPluginInstance(string nameSpace,
                                                                                                                                              string methodName, Dictionary <string, string> inputParameters)
        {
            // find all registered ServerMethods for this app
            var registrations = ServerMethodManager.GetRegistrationsForApp(this.Application);

            // TODO: To support overloading we need to match name + best fit parameter list
            var methodCandidates = registrations.SelectMany(reg => reg.Methods)
                                   .Where(m => ((nameSpace == null && m.Namespace == null) || (m.Namespace?.Equals(nameSpace, StringComparison.Ordinal) ?? false)) && m.Name.Equals(methodName, StringComparison.Ordinal))
                                   .Select(m => m);

            if (methodCandidates.Count() == 0)
            {
                return(null, null, "Method name not found.");
            }

            var weightedMethodList = new List <(decimal /*weight*/, string /*error*/, ServerMethodRegistrationMethod)>();

            // find the best matching overload (if any)
            foreach (var regMethod in methodCandidates)
            {
                var methodParameters = regMethod.AssemblyMethodInfo.GetParameters();

                if (inputParameters.Count > methodParameters.Length)
                {
                    weightedMethodList.Add((1M, "Too many parameters specified", regMethod));
                    continue;
                }

                var joined = from methodParam in methodParameters
                             join inputParam in inputParameters on methodParam.Name equals inputParam.Key into grp
                             from parm in grp.DefaultIfEmpty()
                             select new { HasMatch = parm.Key != null, Param = methodParam };

                var matched    = joined.Where(e => e.HasMatch);
                var notmatched = joined.Where(e => !e.HasMatch);


                var expectedCnt = methodParameters.Count();
                var matchedCnt  = matched.Count();

                // out/ref/optional parameters are added as extra credit below (but does not contribute to actual weight)
                var outRefSum = (from p in joined
                                 where (p.Param.IsOut || p.Param.IsOptional || p.Param.ParameterType.IsByRef) && !p.HasMatch
                                 select 1.0M).Sum();


                if (matchedCnt == expectedCnt || matchedCnt + outRefSum == expectedCnt)
                {
                    weightedMethodList.Add((matchedCnt, null, regMethod));
                }
                else
                {
                    //weightedMethodList.Add((matchedCnt, $"Following parameters not specified: {string.Join("\r\n", notmatched.Select(nm => nm.Param.Name))}", regMethod));
                    weightedMethodList.Add((matchedCnt, "Parameter mismatch", regMethod));
                }
            }

            var bestMatch = weightedMethodList.OrderByDescending(k => k.Item1).FirstOrDefault();

            if (!string.IsNullOrWhiteSpace(bestMatch.Item2))
            {
                var parms    = bestMatch.Item3.AssemblyMethodInfo.GetParameters();
                var parmDesc = "(no parameters)";
                if (parms.Length > 0)
                {
                    parmDesc = string.Join("\r\n", parms.Select(p => $"{p.Name} ({p.ParameterType.ToString()})")); // TODO: Provide "easy to read" description for type, e.g. nullabe Int32 can be something like 'int?' and 'List<string>' just 'string[]'
                }

                return(null, bestMatch.Item3, $"Failed to find suitable overload.\r\nError: {bestMatch.Item2}\r\nBest match requires parameters:\r\n{parmDesc}");
            }

            var matchedRegMethod = bestMatch.Item3;

            var cacheKey = $"{matchedRegMethod.Registration.PluginAssemblyInstanceId}; {matchedRegMethod.Registration.TypeInfo.FullName}";

            plugin.ServerMethodPlugin pluginInstance = null;

            lock (ServerMethodInstanceCache)
            {
                if (ServerMethodInstanceCache.ContainsKey(cacheKey))
                {
                    pluginInstance = ServerMethodInstanceCache[cacheKey];
                }
                else // instantiate a new instance
                {
                    try
                    {
                        pluginInstance = (plugin.ServerMethodPlugin)matchedRegMethod.Registration.Assembly.CreateInstance(matchedRegMethod.Registration.TypeInfo.FullName);
                        var initMethod = typeof(plugin.ServerMethodPlugin).GetMethod("InitSM", BindingFlags.Instance | BindingFlags.NonPublic);

                        if (initMethod != null)
                        {
                            initMethod.Invoke(pluginInstance, new object[] {
                                new Func <SqlConnection>(() => {
                                    if (this.ExecutionConnection != null)
                                    {
                                        var con = new SqlConnection(this.ExecutionConnection.ConnectionStringDecrypted);

                                        con.Open();

                                        return(con);
                                    }

                                    return(new SqlConnection());
                                })
                            });
                        }
                        else
                        {
                            SessionLog.Warning($"Failed to find InitSM method on plugin {matchedRegMethod.Registration.TypeInfo.FullName} from assembly {matchedRegMethod.Registration.Assembly.FullName}. Make sure the correct version of the jsdal plugin is used and that you derive from the correct base class (should be ServerMethodPlugin).");
                        }

                        var setGetServicesFuncMethod = typeof(plugin.PluginBase).GetMethod("SetGetServicesFunc", BindingFlags.Instance | BindingFlags.NonPublic);

                        if (setGetServicesFuncMethod != null)
                        {
                            setGetServicesFuncMethod.Invoke(pluginInstance, new object[] { new Func <Type, plugin.PluginService>(serviceType =>
                                {
                                    if (serviceType == typeof(plugin.BlobStoreBase))
                                    {
                                        return(BlobStore.Instance);
                                    }

                                    return(null);
                                }) });
                        }

                        ServerMethodManager.RegisterInstanceUse(this, matchedRegMethod);
                        ServerMethodInstanceCache.Add(cacheKey, pluginInstance);
                    }
                    catch (Exception ex)
                    {
                        SessionLog.Error($"Failed to instantiate plugin {matchedRegMethod.Registration.TypeInfo.FullName} from assembly {matchedRegMethod.Registration.Assembly.FullName}. See exception that follows.");
                        SessionLog.Exception(ex);
                    }
                }
            } // lock

            return(pluginInstance, matchedRegMethod, null);
        }
示例#13
0
        public void Run()
        {
            try
            {
                IsRunning = true;
                System.Threading.Thread.CurrentThread.Name = "jsDALHealthMonitorThread thread";

                var sw = new Stopwatch();

                var dbCollection = _database.GetCollection <jsDALHealthDbEntry>($"HealthData");

                dbCollection.EnsureIndex("Created", unique: false);

                while (IsRunning && !Program.IsShuttingDown)
                {
                    if (!_nextCheck.HasValue || DateTime.Now >= _nextCheck.Value)
                    {
                        // var endpoints = Settings.SettingsInstance.Instance.ProjectList.SelectMany(p => p.Applications).SelectMany(a => a.Endpoints);

                        // sw.Restart();

                        // var q = from ep in endpoints
                        //         select new EndpointStats()
                        //         {
                        //             Endpoint = ep.Pedigree,
                        //             CachedRoutinesCount = ep.CachedRoutines.Count,
                        //             CachedRoutinesSizeInBytes = CalculateEstSizeInBytes(ep.CachedRoutines)
                        //         };

                        // var endpointStats = q.ToList();

                        // sw.Stop();

                        var proc = Process.GetCurrentProcess();

                        var blobStats = BlobStore.Instance.GetStats();

                        var memInfo = GC.GetGCMemoryInfo();

                        var newEntry = new jsDALHealthDbEntry()
                        {
                            Created = DateTime.Now,
                            // TimeToCalculateSizesInMS = sw.ElapsedMilliseconds,
                            // WorkingSet64 = proc.WorkingSet64,
                            //EndpointStats = endpointStats,
                            HeapSizeMB          = (double)memInfo.HeapSizeBytes / 1024.0 / 1024.0,
                            BlobCnt             = blobStats.TotalItemsInCache,
                            BlobsBytesInCache   = blobStats.TotalBytesInCache,
                            PrivateMemorySize64 = proc.PrivateMemorySize64,
                            ExceutionsInFlight  = Controllers.ExecController.ExceutionsInFlight
                        };

                        dbCollection.Insert(newEntry);

                        // delete entries older than 5 days
                        dbCollection.DeleteMany(x => x.Created.Value <= DateTime.Now.AddDays(-5));

                        _database.Checkpoint();
                        _nextCheck = DateTime.Now.AddSeconds(45);
                    }

                    Thread.Sleep(60);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "jsDALHealthMonitorThread failed");
                ExceptionLogger.LogException(ex);
                SessionLog.Error("jsDALHealthMonitorThread failed");
                SessionLog.Exception(ex);
            }
            finally
            {
                IsRunning = false;

                if (_database != null)
                {
                    _database.Checkpoint();
                    _database.Dispose();
                    _database = null;
                }
            }
        }
示例#14
0
        public void CreateEndpointInstances(IHubContext <Hubs.BackgroundPluginHub> hub)
        {
            IHubClients hubClients = hub.Clients;


            // TODO: Need to look at EP Creation Event and EP stopped & deleted event.

            var apps = Settings.SettingsInstance.Instance
                       .ProjectList
                       .SelectMany(proj => proj.Applications)
                       .Where(app => app.IsPluginIncluded(this.PluginGuid.ToString()));

            var endpointCollection = apps.SelectMany(app => app.Endpoints);

            // create a default instance just to read the Default Value collection
            var defaultInstance = (BackgroundThreadPlugin)this.Assembly.CreateInstance(this.TypeInfo.FullName);

            var defaultConfig = defaultInstance.GetDefaultConfig();

            if (defaultConfig?.ContainsKey("IsEnabled") ?? false)
            {
                var defIsEnabled = defaultConfig["IsEnabled"];
                // TODO: Convert to better typed class (e.g. true/false)
                // TODO: Match up with Endpoint config. EP Config needs to be persisted somewhere
            }

            // TODO: For each BG Plugin catalog the 'server methods' available. (do this once per assembly, not per EP as they are the same for all EPs)

            foreach (var endpoint in endpointCollection)
            {
                try
                {
                    // TODO: Look for an existing instance on the EP
                    // TODO: If no longer ENABLED on EP kill instance? Won't currently be in collection above

                    var existingInstance = FindPluginInstance(endpoint);

                    if (existingInstance != null)
                    {
                        // no need to instantiate again
                        continue;
                    }

                    var pluginInstance = (BackgroundThreadPlugin)this.Assembly.CreateInstance(this.TypeInfo.FullName);
                    var initMethod     = typeof(BackgroundThreadPlugin).GetMethod("Init", BindingFlags.Instance | BindingFlags.NonPublic);
                    //      var initMethod = typeof(BackgroundThreadPlugin).GetMethod("Init", BindingFlags.Instance | BindingFlags.NonPublic);

                    if (initMethod != null)
                    {
                        var instanceWrapper = new BackgroundThreadPluginInstance(endpoint, pluginInstance);

                        var logExceptionCallback = new Action <Exception, string>((exception, additionalInfo) =>
                        {
                            // TODO: Throttle logging if it happens too frequently. Possibly stop plugin if too many exceptions?
                            ExceptionLogger.LogException(exception, new Controllers.ExecController.ExecOptions()
                            {
                                project     = endpoint.Application.Project.Name,
                                application = endpoint.Application.Name,
                                endpoint    = endpoint.Name,
                                schema      = "BG PLUGIN",
                                routine     = this.PluginName,
                                type        = Controllers.ExecController.ExecType.BackgroundThread
                            }, additionalInfo, $"BG PLUGIN - {this.PluginName}", endpoint.Pedigree);
                        });

                        var openSqlConnectionCallback = new Func <SqlConnection>(() =>
                        {
                            try
                            {
                                var execConn = endpoint.GetSqlConnection();
                                if (execConn == null)
                                {
                                    throw new Exception($"Execution connection not configured on endpoint {endpoint.Pedigree}");
                                }

                                var cb = new SqlConnectionStringBuilder(execConn.ConnectionStringDecrypted);

                                cb.ApplicationName = $"{this.PluginName}";

                                var sqlCon = new SqlConnection(cb.ConnectionString);

                                sqlCon.Open();
                                return(sqlCon);
                            }
                            catch (Exception ex)
                            {
                                ExceptionLogger.LogExceptionThrottled(ex, $"{this.PluginName}-{endpoint.Pedigree}::OpenSqlConnection", 20);
                                throw;
                            }
                        });

                        var updateDataCallback = new Func <ExpandoObject, bool>(data =>
                        {
                            dynamic eo = data;

                            eo.InstanceId = instanceWrapper.Id;
                            eo.Endpoint   = endpoint.Pedigree;

                            hubClients.Group(Hubs.BackgroundPluginHub.ADMIN_GROUP_NAME).SendAsync("updateData", (object)eo);

                            return(true);
                        });

                        var browserConsoleSendCallback = new Func <string, string, bool>((method, line) =>
                        {
                            hubClients.Group(Hubs.BackgroundPluginHub.BROWSER_CONSOLE_GROUP_NAME).SendAsync(method, new
                            {
                                InstanceId = instanceWrapper.Id,
                                Endpoint   = endpoint.Pedigree,
                                Line       = line
                            });
                            return(true);
                        });

                        var addToGroupAsync = new Func <string, string, CancellationToken, Task>((connectionId, groupName, cancellationToken) =>
                        {
                            return(hub.Groups.AddToGroupAsync(connectionId, $"{endpoint.Pedigree}.{groupName}", cancellationToken));
                        });

                        var sendToGroupsAsync = new Func <string, string, object[], Task>((groupName, methodName, args) =>
                        {
                            groupName = $"{endpoint.Pedigree}.{groupName}";

                            if (args == null || args.Length == 0)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName));
                            }
                            else if (args.Length == 1)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName, args[0]));
                            }
                            else if (args.Length == 2)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName, args[0], args[1]));
                            }
                            else if (args.Length == 3)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName, args[0], args[1], args[2]));
                            }
                            else if (args.Length == 4)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName, args[0], args[1], args[2], args[3]));
                            }
                            else if (args.Length == 5)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName, args[0], args[1], args[2], args[3], args[4]));
                            }
                            else if (args.Length == 6)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName, args[0], args[1], args[2], args[3], args[4], args[5]));
                            }
                            else if (args.Length == 7)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName, args[0], args[1], args[2], args[3], args[4], args[5], args[6]));
                            }
                            else if (args.Length == 8)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]));
                            }
                            else if (args.Length == 9)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]));
                            }
                            else if (args.Length == 10)
                            {
                                return(hub.Clients.Groups(groupName).SendAsync(methodName, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]));
                            }

                            return(null);
                        });

                        var dataCollectorBeginCallback = new Func <string, string, string>((schema, routine) =>
                        {
                            string dataCollectorEntryShortId = DataCollectorThread.Enqueue(endpoint,
                                                                                           new Controllers.ExecController.ExecOptions()
                            {
                                project         = endpoint.Application.Project.Name,
                                application     = endpoint.Application.Name,
                                endpoint        = endpoint.Name,
                                schema          = schema,
                                routine         = routine,
                                type            = Controllers.ExecController.ExecType.BackgroundThread,
                                inputParameters = new Dictionary <string, string>()    // TODO: needs to be an input parameter
                            });

                            return(dataCollectorEntryShortId);
                        });


                        initMethod.Invoke(pluginInstance,
                                          new object[] {
                            endpoint.Pedigree,
                            logExceptionCallback,
                            openSqlConnectionCallback,
                            updateDataCallback,
                            browserConsoleSendCallback,
                            addToGroupAsync,
                            sendToGroupsAsync,
                            null /*configKeys*/,
                            null    /*configSource*/
                        });


                        {
                            var setGetServicesFuncMethod = typeof(PluginBase).GetMethod("SetGetServicesFunc", BindingFlags.Instance | BindingFlags.NonPublic);

                            if (setGetServicesFuncMethod != null)
                            {
                                setGetServicesFuncMethod.Invoke(pluginInstance, new object[] { new Func <Type, PluginService>(serviceType =>
                                    {
                                        if (serviceType == typeof(BlobStoreBase))
                                        {
                                            return(BlobStore.Instance);
                                        }

                                        return(null);
                                    }) });
                            }
                        }

                        this.AddEnpointInstance(endpoint, instanceWrapper);

                        SessionLog.Info($"BG plugin '{this.PluginName}' instantiated successfully on endpoint {endpoint.Pedigree}");
                    }
                    else
                    {
                        throw new Exception("Expected Init method not found");
                    }
                }
                catch (Exception ex)
                {
                    SessionLog.Error($"Failed to instantiate plugin '{this.PluginName}' ({this.PluginGuid}) from assembly {this.Assembly.FullName} on endpoint {endpoint.Pedigree}. See exception that follows.");
                    SessionLog.Exception(ex);
                }
            }
        }
示例#15
0
        public static string GetTypescriptTypeFromSql(string sqlType, Dictionary <string, Dictionary <string, RoutineParameterCustomType> > customType,
                                                      ref ConcurrentDictionary <string, string> customTypeLookupWithTypeScriptDef)
        {
            var elems = sqlType.ToLower().Split('.'); // types like geography could come through as sys.CATALOG.geography
            var dt    = elems[elems.Length - 1];

            switch (dt)
            {
            case Strings.SQL.TABLE_TYPE:
                return(Strings.TS.OBJECT);

            case Strings.SQL.TIME:
                return(Strings.TS.DATE);

            case Strings.SQL.DATE:
                return(Strings.TS.DATE);

            case Strings.SQL.DATETIME:
                return(Strings.TS.DATE);

            case Strings.SQL.SMALLDATETIME:
                return(Strings.TS.DATE);

            case Strings.SQL.INT:
                return(Strings.TS.NUMBER);

            case Strings.SQL.SMALLINT:
                return(Strings.TS.NUMBER);

            case Strings.SQL.BIGINT:
                return(Strings.TS.NUMBER);

            case Strings.SQL.REAL:
                return(Strings.TS.NUMBER);

            case Strings.SQL.BIT:
                return(Strings.TS.BOOLEAN);

            case Strings.SQL.NVARCHAR:
                return(Strings.TS.STRING);

            case Strings.SQL.VARCHAR:
                return(Strings.TS.STRING);

            case Strings.SQL.TEXT:
                return(Strings.TS.STRING);

            case Strings.SQL.NTEXT:
                return(Strings.TS.STRING);

            case Strings.SQL.VARBINARY:
                return(Strings.TS.BLOB);    // TODO: Not sure about this one...worst case, make it a string

            case Strings.SQL.DECIMAL:
                return(Strings.TS.NUMBER);

            case Strings.SQL.UNIQUEIDENTIFIER:
                return(Strings.TS.STRING);

            case Strings.SQL.MONEY:
                return(Strings.TS.NUMBER);

            case Strings.SQL.CHAR:
                return(Strings.TS.STRING);

            case Strings.SQL.NCHAR:
                return(Strings.TS.STRING);

            case Strings.SQL.XML:
                return(Strings.TS.STRING);

            case Strings.SQL.FLOAT:
                return(Strings.TS.NUMBER);

            case Strings.SQL.IMAGE:
                return(Strings.TS.BLOB);    // TODO: Not sure about this one...worst case, make it a string

            case Strings.SQL.TINYINT:
                return(Strings.TS.NUMBER);

            case Strings.SQL.GEOGRAPHY:
                return(Strings.TS.jsDAL_LatLng);

            case Strings.SQL.SQL_VARIANT:
                return(Strings.TS.STRING);

            case Strings.SQL.TIMESTAMP:
                return(Strings.TS.STRING);

            case Strings.SQL.BINARY:
                return(Strings.TS.BLOB);    // TODO: Not sure about this one...worst case, make it a string

            case Strings.SQL.NUMERIC:
                return(Strings.TS.NUMBER);

            case Strings.SQL.SYSNAME:
                return(Strings.TS.ANY);

            default:
            {
                if (customType != null && customType.Keys.Count > 0)
                {
                    //?  lock (customTypeLookupWithTypeScriptDef)
                    {
                        var customTypeName = customType.Keys.First();
                        var typeName       = $"$CustomType_{customTypeName}";

                        if (customTypeLookupWithTypeScriptDef.ContainsKey(typeName))
                        {
                            return(typeName);
                        }

                        var properties = new Dictionary <string, string>();

                        foreach (var kv in customType[customTypeName])
                        {
                            var fieldName = kv.Key;
                            var dataType  = kv.Value.DataType;

                            var tsTypeDef = GetTypescriptTypeFromSql(kv.Value.DataType, null, ref customTypeLookupWithTypeScriptDef);

                            properties.Add(fieldName, tsTypeDef);
                        }

                        var customTSD = string.Join(", ", from kv in properties select $"{kv.Key}: {kv.Value}");

                        //TODO: Custom types are not necessarily arrays?
                        if (!customTypeLookupWithTypeScriptDef.TryAdd(typeName, $"{{{ customTSD }}}[]"))
                        {
                            SessionLog.Error($"Failed to add custom type {typeName} to dictionary");
                        }

                        return(typeName);
                    }
                }

                return("any");
            }
            }
        }