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); } }
public static bool LoadSettingsFromFile() { try { if (!File.Exists(SettingsInstance.SettingsFilePath)) { Log.Warning("Settings file not found at {0}", Path.GetFullPath(SettingsInstance.SettingsFilePath)); Log.Information("Creating blank Settings..."); SettingsInstance._instance = JsDalServerConfig.CreateDefault(); return(true); } var data = File.ReadAllText(SettingsInstance.SettingsFilePath, System.Text.Encoding.UTF8); var settingsInst = JsonConvert.DeserializeObject <JsDalServerConfig>(data, new JsonConverter[] { new ObjectModel.RuleJsonConverter() }); //? settingsInst.ProjectList.ForEach(p => p.AfterDeserializationInit()); SettingsInstance._instance = settingsInst; return(true); } catch (Exception ex) { SessionLog.Exception(ex); return(false); } }
public void AddUpdate(Endpoint endpoint, JsFile jsFile, List <ChangeDescriptor> changes) { try { if (!_entries.ContainsKey(endpoint.Pedigree)) { _entries.Add(endpoint.Pedigree, new Dictionary <string, List <ChangeDescriptor> >()); } var epEntry = _entries[endpoint.Pedigree]; var jsFileKey = $"{jsFile.Filename.ToLower()}.{jsFile.Version}"; if (!epEntry.ContainsKey(jsFileKey)) { epEntry.Add(jsFileKey, new List <ChangeDescriptor>()); } // add unique entries epEntry[jsFileKey].AddRange(changes.Where(c => !epEntry[jsFileKey].Exists(existing => existing.Description.Equals(c.Description, StringComparison.OrdinalIgnoreCase)))); } catch (Exception ex) { 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); } } }
public bool ClearCache() { try { var cachePath = "./cache"; if (!Directory.Exists(cachePath)) { return(true); } var cacheFilePath = Path.Combine(cachePath, this.CacheFilename); if (!File.Exists(cacheFilePath)) { return(true); } this.CachedRoutineList.Clear(); File.Delete(cacheFilePath); WorkSpawner.ResetMaxRowDate(this); this.LastUpdateDate = DateTime.Now; return(true); } catch (Exception ex) { SessionLog.Exception(ex); return(false); } }
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(); }
public IActionResult GetServerDetail() { try { if (SettingsInstance.Instance.ProjectList == null || SettingsInstance.Instance.ProjectList.Count == 0) { return(null); } var currentETagHeader = this.Request.Headers["If-None-Match"].FirstOrDefault(); var q = (from p in SettingsInstance.Instance.ProjectList select new { Name = p.Name, Apps = p.Applications.Select(app => new { app.Name, Endpoints = app.Endpoints.Select(ep => new { ep.Name, Files = app.JsFiles.Select(f => f.Filename) }) }) }) .ToList(); var json = Newtonsoft.Json.JsonConvert.SerializeObject(q); using (var md5 = MD5.Create()) { var result = md5.ComputeHash(Encoding.ASCII.GetBytes(json)); var hash = Convert.ToBase64String(result); if (currentETagHeader != null && currentETagHeader.Equals(hash)) { this.Response.Headers.Clear(); return(StatusCode(304)); } this.Response.Headers["ETag"] = hash; this.Response.Headers["Cache-Control"] = "max-age=0"; this.Response.Headers["Pragma"] = "no-cache"; // HTTP 1.0. } return(Ok(q)); } catch (Exception ex) { SessionLog.Exception(ex); throw; } }
public ApiResponse GetAppTitlesCbo() { try { return(ApiResponse.Payload(ExceptionLogger.AppTitles)); } catch (Exception ex) { SessionLog.Exception(ex); return(ApiResponse.Exception(ex)); } }
static ServerMethodManager() { try { ServerMethodManager.TEMPLATE_ServerMethodContainer = File.ReadAllText("./resources/ServerMethodContainer.txt"); ServerMethodManager.TEMPLATE_ServerMethodFunctionTemplate = File.ReadAllText("./resources/ServerMethodTemplate.txt"); ServerMethodManager.TEMPLATE_ServerMethodTypescriptDefinitionsContainer = File.ReadAllText("./resources/ServerMethodsTSDContainer.d.ts"); } catch (Exception ex) { SessionLog.Exception(ex); } }
public IActionResult ServeCommonTSD() { try { var typescriptDefinitionsCommon = System.IO.File.ReadAllText("./resources/TypeScriptDefinitionsCommon.d.ts"); return(Ok(typescriptDefinitionsCommon)); } catch (Exception ex) { SessionLog.Exception(ex); return(BadRequest(ex.Message)); } }
public bool TryDecrypt(string encryptedText, out string decryptedText) { try { decryptedText = _protector.Unprotect(encryptedText); return(true); } catch (CryptographicException ce) { decryptedText = null; SessionLog.Exception(ce); return(false); } }
public List <dynamic> ListProjects() {// TODO: Handle No Projects exist try { var q = (from p in SettingsInstance.Instance.ProjectList select new { Name = p.Name, Guid = (string)null }).ToList <dynamic>(); return(q); } catch (Exception ex) { SessionLog.Exception(ex); throw; } }
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; } }
public static void Add(RoutineExecution e) { try { var ri = new RealtimeInfo(e); lock (_realtimeItemList) { _realtimeItemList.Add(ri); Hubs.Performance.RealtimeMonitor.Instance.NotifyObservers(); } } catch (Exception ex) { SessionLog.Exception(ex); } }
public IActionResult ServeServerMethods([FromQuery] string project, [FromQuery] string app, [FromQuery] long v = 0, [FromQuery] bool min = false, [FromQuery] bool tsd = false) { try { if (SettingsInstance.Instance.ProjectList == null) { return(NotFound()); } if (!ControllerHelper.GetProjectAndApp(project, app, out var proj, out var application, out var resp)) { return(NotFound()); } FileResult ret = null; string content = tsd ? application.ServerMethodTSD : application.ServerMethodJs; if (string.IsNullOrWhiteSpace(content)) { return(NotFound()); } var etagFromRequest = this.Request.Headers["If-None-Match"]; string etag = tsd ? application.ServerMethodTSDEtag : application.ServerMethodJsEtag; if (!string.IsNullOrWhiteSpace(etagFromRequest) && !string.IsNullOrWhiteSpace(etag)) { if (etag == etagFromRequest) { return(StatusCode(StatusCodes.Status304NotModified)); } } ret = File(System.Text.Encoding.UTF8.GetBytes(content), "text/javascript"); ret.EntityTag = new Microsoft.Net.Http.Headers.EntityTagHeaderValue(etag); return(ret); } catch (Exception ex) { SessionLog.Exception(ex); return(BadRequest(ex.Message)); } }
public async Task LoadCacheAsync() { try { string cachePath = "./cache"; string cacheFilePath = Path.Combine(cachePath, this.CacheFilename); if (!File.Exists(cacheFilePath)) { return; } this.CachedRoutineList = new List <CachedRoutine>(); var data = await File.ReadAllTextAsync(cacheFilePath, System.Text.Encoding.UTF8); var allCacheEntries = Newtonsoft.Json.JsonConvert.DeserializeObject <List <CachedRoutine> >(data /*, new BoolJsonConverter()*/); //var options = new System.Text.Json.JsonSerializerOptions() { IncludeFields = true/*, Converters = { new InternedStringConverter() }*/ }; //var allCacheEntries = System.Text.Json.JsonSerializer.Deserialize<List<CachedRoutine>>(data, options); this.CachedRoutineList = allCacheEntries; // pre-calc to build up initial CustomTypeLookupWithTypeScriptDef this.CachedRoutineList.AsParallel().ForAll(r => { try { r.PrecalculateJsGenerationValues(this); } catch (Exception ee) { r.PrecalcError = ee.ToString(); } }); _cachedRoutinesPromise.TrySetResult(this.CachedRoutineList); } catch (Exception ex) { SessionLog.Exception(ex); } }
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); } }
static StatsDB() { try { // TODO: Deprecated in favour of the DataCollector // _executionQueue = new ConcurrentQueue<StatsRoutineExecution>(); // _database = new LiteDB.LiteDatabase("data/stats.db"); // // reset stats on startup // _database.DropCollection("TotalCount"); // SessionLog.Info("Starting up StatsDB thread"); // _winThread = new Thread(new ThreadStart(ProcessMessagesLoop)); // _winThread.Start(); } catch (Exception ex) { SessionLog.Exception(ex); Log.Error(ex, "Failed to initiate Stats DB"); } }
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); } }
public IActionResult GetThreadStatus(Guid dbSourceGuid) { try { dynamic workThread = null;//!JsFileGenerator.GetThread(dbSourceGuid); if (workThread == null) { return(Content($"The specified DB source {dbSourceGuid} is invalid or does not have a thread running.")); /* * return new HttpResponseMessage(HttpStatusCode.NotFound) * { * Content = new StringContent($"The specified DB source {dbSourceGuid} is invalid or does not have a thread running.") * };*/ } //var ret = new HttpResponseMessage(HttpStatusCode.OK); var obj = new { workThread.CreateDate, workThread.IsRunning, workThread.Status }; //ret.Content = new StringContent(JsonConvert.SerializeObject(obj)); //ret.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); return(Ok(obj)); } catch (Exception ex) { SessionLog.Exception(ex); return(BadRequest(ex.Message)); } }
public IActionResult GetFileChanges([FromQuery] string project, [FromQuery] string app, [FromQuery] string endpoint, [FromQuery] string file, [FromQuery] int from = 0, [FromQuery] int to = 0) { try { if (SettingsInstance.Instance.ProjectList == null) { return(NotFound()); } if (!ControllerHelper.GetProjectAndAppAndEndpoint(project, app, endpoint, out var proj, out var application, out var ep, out var resp)) { return(NotFound()); } var jsFile = application.GetJsFile(file); if (jsFile == null) { return(NotFound()); } var jsFileDescriptor = $"{project}/{app}/{endpoint}/{file}"; if (to == -1) { to = jsFile.Version; } var changes = JsFileChangesTracker.Instance.BuildChangeList(ep, jsFile, from, to); return(Ok(changes)); } catch (Exception ex) { SessionLog.Exception(ex); return(BadRequest(ex.Message)); } }
//[Newtonsoft.Json.JsonIgnore] // public object _cacheLock = new object(); public async Task SaveCacheAsync() { //lock (_cacheLock) { string cachePath = "./cache"; if (!Directory.Exists(cachePath)) { try { Directory.CreateDirectory(cachePath); } catch (Exception e) { SessionLog.Exception(e); } } var cacheFilePath = Path.Combine(cachePath, this.CacheFilename); var json = Newtonsoft.Json.JsonConvert.SerializeObject(this.CachedRoutineList); await File.WriteAllTextAsync(cacheFilePath, json, System.Text.Encoding.UTF8); } }
// 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); }
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; } }
public ApiResponse GetException([FromRoute] string id, [FromQuery(Name = "parent")] string parentId) { try { ExceptionWrapper ret = null; if (!string.IsNullOrWhiteSpace(parentId)) { var parent = ExceptionLogger.GetException(parentId); if (parent == null) { return(ApiResponse.ExclamationModal($"A parent exception with id \"{parentId}\" could not be found.")); } var child = parent.GetRelated(id); if (child == null) { return(ApiResponse.ExclamationModal($"An exception with id \"{id}\" could not be found.")); } ret = child; } else { var ex = ExceptionLogger.GetException(id); if (ex == null) { ex = ExceptionLogger.DeepFindRelated(id); } if (ex == null) { return(ApiResponse.ExclamationModal($"An exception with id \"{id}\" could not be found.")); } ret = ex; } return(ApiResponse.Payload(new { ret.appTitle, ret.appVersion, ret.created, ret.errorCode, ret.execOptions, id = ret.sId, ret.innerException, ret.level, ret.line, ret.message, ret.procedure, ret.server, //?ret.sqlErrorType, ret.stackTrace, ret.state, ret.type, ret.additionalInfo })); } catch (Exception ex) { SessionLog.Exception(ex); return(ApiResponse.Exception(ex)); } }
public ApiResponse GetRecentExceptions([FromQuery] int?top, [FromQuery] string endpoint, [FromQuery] string app, [FromQuery] string routine) { try { if (!top.HasValue) { top = 20; } if (top > 800) { top = 800; } string[] endpointLookup = null; string[] appLookup = null; if (string.IsNullOrEmpty(endpoint) || endpoint.Equals("all", StringComparison.OrdinalIgnoreCase)) { endpoint = null; } if (string.IsNullOrEmpty(app) || app.Equals("all", StringComparison.OrdinalIgnoreCase)) { app = null; } if (string.IsNullOrEmpty(routine)) { routine = null; } if (endpoint != null) { endpointLookup = endpoint.Split(',', StringSplitOptions.RemoveEmptyEntries); if (endpointLookup.FirstOrDefault(e => e.Equals("all", StringComparison.OrdinalIgnoreCase)) != null) { endpointLookup = null; } } if (app != null) { appLookup = app.Split(',', StringSplitOptions.RemoveEmptyEntries); if (appLookup.FirstOrDefault(a => a.Equals("all", StringComparison.OrdinalIgnoreCase)) != null) { appLookup = null; } } var ret = from exception in ExceptionLogger.GetAll(endpointLookup) where exception.HasAppTitle(appLookup) && (routine == null || (exception.execOptions?.MatchRoutine(routine) ?? false)) orderby exception.created.Ticks descending select new { id = exception.sId, exception.created, message = exception.message.Left(200, true), // limit exception message length to something reasonable exception.procedure, exception.appTitle, exception.appVersion, relatedCount = exception.related?.Count ?? 0 } ; return(ApiResponse.Payload(new { Results = ret.Take(Math.Min(top.Value, ret.Count())), TotalExceptionCnt = ExceptionLogger.TotalCnt })); } catch (Exception ex) { SessionLog.Exception(ex); return(ApiResponse.Exception(ex)); } }
public BackgroundWorker InstallOrm() { var missing = CheckForMissingOrmPreRequisitesOnDatabase(); if (string.IsNullOrEmpty(missing)) { return(null); } var sqlScriptPath = Path.GetFullPath("./resources/install-orm.sql"); var installSqlScript = File.ReadAllText(sqlScriptPath, System.Text.Encoding.UTF8); //https://stackoverflow.com/a/18597052 var statements = Regex.Split(installSqlScript, @"^[\s]*GO[\s]*\d*[\s]*(?:--.*)?$", RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase); var statementsToExec = statements.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim(' ', '\r', '\n')); using (var con = new SqlConnection()) { con.ConnectionString = this.MetadataConnection.ConnectionStringDecrypted; con.Open(); var trans = con.BeginTransaction(); try { foreach (var st in statementsToExec) { var cmd = new SqlCommand(); cmd.Connection = con; cmd.Transaction = trans; cmd.CommandType = System.Data.CommandType.Text; cmd.CommandText = st; cmd.CommandTimeout = 80; cmd.ExecuteNonQuery(); } trans.Commit(); } catch (Exception ex) { if (trans != null) { trans.Rollback(); } SessionLog.Exception(ex); } con.Close(); BackgroundWorker backgroundWorker = null; backgroundWorker = BackgroundTask.Queue($"{GetBgTaskKey()}.ORM_INIT", $"{Application.Project.Name}/{Application.Name}/{this.Name} ORM initilisation", () => { // try // { using (var conInit = new SqlConnection()) { con.FireInfoMessageEventOnUserErrors = true; conInit.ConnectionString = this.MetadataConnection.ConnectionStringDecrypted; conInit.Open(); var cmdInit = new SqlCommand(); cmdInit.Connection = conInit; cmdInit.CommandText = "ormv2.Init"; cmdInit.CommandTimeout = 600; conInit.InfoMessage += (sender, e) => { if (!backgroundWorker.IsDone && double.TryParse(e.Message, out var p)) { backgroundWorker.Progress = p; Hubs.BackgroundTaskMonitor.Instance.NotifyOfChange(backgroundWorker); } }; cmdInit.ExecuteScalar(); WorkSpawner.HandleOrmInstalled(this); SettingsInstance.SaveSettingsToFile(); return(true); } // } // catch (Exception ex) // { // return ex; // //return ex; // } }); return(backgroundWorker); } }
public IActionResult GetFile([FromQuery] string project, [FromQuery] string app, [FromQuery] string endpoint, [FromQuery] string file, [FromQuery] long v = 0, [FromQuery] bool min = false, [FromQuery] bool tsd = false) { try { if (SettingsInstance.Instance.ProjectList == null) { return(NotFound()); } if (!ControllerHelper.GetProjectAndAppAndEndpoint(project, app, endpoint, out var proj, out var application, out var ep, out var resp)) { return(NotFound()); } var jsFile = application.GetJsFile(file); if (jsFile == null) { return(NotFound()); } var jsFileDescriptor = $"{project}/{app}/{endpoint}/{file}"; if (tsd) { return(ServeTypescriptDefinition(ep, jsFile)); } var path = min ? ep.MinifiedOutputFilePath(jsFile) : ep.OutputFilePath(jsFile); if (!System.IO.File.Exists(path)) { Log.Warning($"412: {jsFileDescriptor}"); return(StatusCode(StatusCodes.Status412PreconditionFailed, $"The requested file ({jsFileDescriptor}) is not valid or has not been generated yet")); } byte[] jsFileData; using (var fs = System.IO.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read)) { jsFileData = new byte[fs.Length]; fs.Read(jsFileData, 0, jsFileData.Length); } var etagForLatestFile = ComputeETag(jsFileData); var etagFromRequest = this.Request.Headers["If-None-Match"]; // // worker-state // { // string workerStateHeaderValue = null; // var worker = WorkSpawner.GetWorkerByEndpoint(ep); // if (worker != null) // { // if (worker.IsRunning) // { // workerStateHeaderValue = "running - " + worker.Status; // } // else // { // workerStateHeaderValue = "stopped - " + worker.Status; // } // } // else // { // workerStateHeaderValue = "no-worker"; // } // this.Response.Headers.Add("w-state", workerStateHeaderValue); // } if (!string.IsNullOrWhiteSpace(etagFromRequest) && !string.IsNullOrWhiteSpace(etagForLatestFile)) { if (etagForLatestFile == etagFromRequest) { return(StatusCode(StatusCodes.Status304NotModified)); } } var ret = File(jsFileData, "text/javascript"); ret.EntityTag = new Microsoft.Net.Http.Headers.EntityTagHeaderValue(etagForLatestFile); this.Response.Headers.Add("jsfver", jsFile.Version.ToString()); string filterJson = null; if (this.Request.Headers.ContainsKey("changes-filter")) { filterJson = this.Request.Headers["changes-filter"]; } var changeCnt = JsFileChangesTracker.Instance.CountChanges(ep, jsFile, (int)v, jsFile.Version, filterJson); this.Response.Headers.Add("change-cnt", changeCnt.ToString()); return(ret); } catch (Exception ex) { SessionLog.Exception(ex); return(BadRequest(ex.Message)); } }
public async Task <IActionResult> WatchSubscription([FromQuery] string project, [FromQuery] string app, [FromQuery] string endpoint, [FromQuery] string file) { try { if (jsdal_server_core.Program.IsShuttingDown) { // await Task.Delay(1800); return(Ok(new { Worker = new { Running = false, Status = "jsDAL Server shutting down" }, HasJsChanges = false, HasSMChanges = false })); } Hubs.MainStats.IncreaseSubWatchers(); if (SettingsInstance.Instance.ProjectList == null) { return(NotFound()); } if (!ControllerHelper.GetProjectAndAppAndEndpoint(project, app, endpoint, out var proj, out var application, out var ep, out var resp)) { return(NotFound()); } var jsFile = application.GetJsFile(file); if (jsFile == null) { return(NotFound()); } dynamic workerState = null; Worker worker = null; // worker-state { worker = WorkSpawner.GetWorkerByEndpoint(ep); if (worker != null) { workerState = new { Running = worker.IsRunning, Status = worker.Status }; if (!worker.IsRunning) { return(Ok(new { Worker = workerState, HasJsChanges = false, HasSMChanges = false })); } } else { return(Ok(new { Worker = new { Running = false, Status = "No worker thread" }, HasJsChanges = false, HasSMChanges = false })); } } string json; string currentJsEtag = null; string currentServerMethodEtag = null; using (var sr = new System.IO.StreamReader(this.Request.Body)) { json = sr.ReadToEnd(); var watch = JsonConvert.DeserializeObject <dynamic>(json); if (watch["JsEtag"] != null) { currentJsEtag = watch["JsEtag"].Value; } if (watch["SMEtag"] != null) { currentServerMethodEtag = watch["SMEtag"].Value; } } bool hasJsChanges = false; bool hasSMChanges = false; int watchForSeconds = 12; int tickCountEnd = Environment.TickCount + (watchForSeconds * 1000); while (!jsdal_server_core.Program.IsShuttingDown && !hasJsChanges && !hasSMChanges && Environment.TickCount <= tickCountEnd) { if (!worker.IsRunning) { workerState = new { Running = worker.IsRunning, Status = worker.Status }; break; } hasJsChanges = jsFile.ETag != currentJsEtag; //hasSMChanges = jsFile.ETag != jsEtag; await Task.Delay(200); } return(Ok(new { Worker = workerState, HasJsChanges = hasJsChanges, HasSMChanges = hasSMChanges })); } catch (Exception ex) { SessionLog.Exception(ex); return(BadRequest(ex.Message)); } finally { Hubs.MainStats.DecreaseSubWatchers(); } }
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); }