public static GrasshopperDefinition GetCachedDefinition(string key) { if (string.IsNullOrWhiteSpace(key)) { return(null); } var def = System.Runtime.Caching.MemoryCache.Default.Get(key) as CachedDefinition; if (def == null) { string filename = DefinitionCacheFileName(key); if (filename != null && System.IO.File.Exists(filename)) { try { string data = System.IO.File.ReadAllText(filename); return(GrasshopperDefinition.FromBase64String(data, true)); } catch (Exception ex) { Serilog.Log.Error($"Unable to read cache file: {filename}"); Serilog.Log.Error(ex, "File error exception"); } } return(null); } if (def.Definition.IsLocalFileDefinition) { if (def.WatchedFileRuntimeSerialNumber != GrasshopperDefinition.WatchedFileRuntimeSerialNumber) { System.Runtime.Caching.MemoryCache.Default.Remove(key); return(null); } } return(def.Definition); }
static Response Grasshopper(NancyContext ctx) { var stopwatch = System.Diagnostics.Stopwatch.StartNew(); string body = ctx.Request.Body.AsString(); if (body.StartsWith("[") && body.EndsWith("]")) { body = body.Substring(1, body.Length - 2); } Schema input = JsonConvert.DeserializeObject <Schema>(body); if (input.CacheSolve) { // look in the cache to see if this has already been solved string cachedReturnJson = DataCache.GetCachedSolveResults(body); if (!string.IsNullOrWhiteSpace(cachedReturnJson)) { Response cachedResponse = cachedReturnJson; cachedResponse.ContentType = "application/json"; return(cachedResponse); } } // 5 Feb 2021 S. Baer // Throw a lock around the entire solve process for now. I can easily // repeat multi-threaded issues by creating a catenary component with Hops // that has one point for A and multiple points for B. // We can narrow down this lock over time. As it stands, launching many // compute instances on one computer is going to be a better solution anyway // to deal with solving many times simultaniously. lock (_ghsolvelock) { // load grasshopper file GrasshopperDefinition definition = GrasshopperDefinition.FromUrl(input.Pointer, true); if (definition == null) { definition = GrasshopperDefinition.FromBase64String(input.Algo, true); } if (definition == null) { throw new Exception("Unable to load grasshopper definition"); } definition.SetInputs(input.Values); long decodeTime = stopwatch.ElapsedMilliseconds; stopwatch.Restart(); var output = definition.Solve(); output.Pointer = definition.CacheKey; long solveTime = stopwatch.ElapsedMilliseconds; stopwatch.Restart(); string returnJson = JsonConvert.SerializeObject(output, GeometryResolver.Settings); long encodeTime = stopwatch.ElapsedMilliseconds; Response res = returnJson; res.ContentType = "application/json"; res = res.WithHeader("Server-Timing", $"decode;dur={decodeTime}, solve;dur={solveTime}, encode;dur={encodeTime}"); if (definition.HasErrors) { res.StatusCode = Nancy.HttpStatusCode.InternalServerError; } else { if (input.CacheSolve) { DataCache.SetCachedSolveResults(body, returnJson, definition); } } return(res); } }
static Response Grasshopper(NancyContext ctx) { var stopwatch = System.Diagnostics.Stopwatch.StartNew(); string body = ctx.Request.Body.AsString(); if (body.StartsWith("[") && body.EndsWith("]")) { body = body.Substring(1, body.Length - 2); } Schema input = JsonConvert.DeserializeObject <Schema>(body); if (input.CacheSolve) { // look in the cache to see if this has already been solved string cachedReturnJson = DataCache.GetCachedSolveResults(body); if (!string.IsNullOrWhiteSpace(cachedReturnJson)) { Response cachedResponse = cachedReturnJson; cachedResponse.ContentType = "application/json"; return(cachedResponse); } } // load grasshopper file GrasshopperDefinition definition = GrasshopperDefinition.FromUrl(input.Pointer, true); if (definition == null) { definition = GrasshopperDefinition.FromBase64String(input.Algo); } if (definition == null) { throw new Exception("Unable to load grasshopper definition"); } definition.SetInputs(input.Values); long decodeTime = stopwatch.ElapsedMilliseconds; stopwatch.Restart(); var output = definition.Solve(); long solveTime = stopwatch.ElapsedMilliseconds; stopwatch.Restart(); string returnJson = JsonConvert.SerializeObject(output, GeometryResolver.Settings); long encodeTime = stopwatch.ElapsedMilliseconds; Response res = returnJson; res.ContentType = "application/json"; res = res.WithHeader("Server-Timing", $"decode;dur={decodeTime}, solve;dur={solveTime}, encode;dur={encodeTime}"); if (definition.HasErrors) { res.StatusCode = Nancy.HttpStatusCode.InternalServerError; } else { if (input.CacheSolve) { DataCache.SetCachedSolveResults(body, returnJson); } } return(res); }