static void CacheRetention_NeverRetain() { Console.WriteLine(); Console.WriteLine("--------------------------------------------------------"); Console.WriteLine("--- CacheRetention_NeverRetain()"); Console.WriteLine("--------------------------------------------------------"); // Ensure RuleApplication cache is empty RuleSession.RuleApplicationCache.Clear(); Console.WriteLine("1) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Expecting 0 // Usage #1 Attempt to explicitly add a RuleApplication to the cache with CacheRetention.NeverRetain via RuleApplicationCache.Add() - RuleApp is compiled, but not reusable RuleSession.RuleApplicationCache.Add("NewRuleApplication.ruleappx", CacheRetention.NeverRetain); Console.WriteLine("2) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Expecting 0 // Usage #2 Attempt to explicitly add a RuleApplication to the cache with CacheRetention.NeverRetain via RuleApplicationReference.Compile() - RuleApp is compiled, but not reusable RuleApplicationReference ruleAppReference = "NewRuleApplication.ruleappx"; // Note: RuleApplicationReference supports implicit casting from file path string, or RuleApplicationDef instance ruleAppReference.Compile(CacheRetention.NeverRetain); Console.WriteLine("3) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Expecting 0 // Usage #3 Attempt to implicitly add a RuleApplication to the cache with CacheRetention.NeverRetain via RuleSession() - RuleApp is compiled, but not reusable outside of RuleSession using (RuleSession session = new RuleSession("NewRuleApplication.ruleappx", CacheRetention.NeverRetain)) { session.CreateEntity("Entity1"); } Console.WriteLine("4) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Expecting 0 }
static void ExplicitCache() { Console.WriteLine(); Console.WriteLine("--------------------------------------------------------"); Console.WriteLine("--- ExplicitCache()"); Console.WriteLine("--------------------------------------------------------"); // Ensure RuleApplication cache is empty RuleSession.RuleApplicationCache.Clear(); Console.WriteLine("1) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Expecting 0 // Create in-memory RuleApplications RuleApplicationDef ruleAppDef1 = new RuleApplicationDef("MyApp1"); ruleAppDef1.Entities.Add(new EntityDef("Entity1")); RuleApplicationDef ruleAppDef2 = new RuleApplicationDef("MyApp2"); ruleAppDef2.Entities.Add(new EntityDef("Entity2")); // Explicit Cache Usage #1: Explicitly cache MyApp1 via RuleApplicationCache RuleApplicationReference ruleAppReference1 = RuleSession.RuleApplicationCache.Add(ruleAppDef1); Console.WriteLine("2) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Expecting 1 // Explicit Cache Usage #2: Explicitly cache MyApp2 via RuleApplicationReference.Compile() RuleApplicationReference ruleAppReference2 = new InMemoryRuleApplicationReference(ruleAppDef2); ruleAppReference2.Compile(); Console.WriteLine("3) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Expecting 2 // Consumption Usage #1: Create RuleSession with source RuleApplicationDef using (RuleSession session = new RuleSession(ruleAppDef1)) { session.CreateEntity("Entity1"); } using (RuleSession session = new RuleSession(ruleAppDef2)) { session.CreateEntity("Entity2"); } Console.WriteLine("4) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Still only expecting 2 // Consumption Usage #2: Create RuleSession with RuleApplicationReference using (RuleSession session = new RuleSession(ruleAppReference1)) { session.CreateEntity("Entity1"); } using (RuleSession session = new RuleSession(ruleAppReference2)) { session.CreateEntity("Entity2"); } Console.WriteLine("5) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Still only expecting 2 }
// This policy does not have a maximum depth and does not use the CacheRetention.Weight - It only checks the property MyCacheRetention.Name public bool AllowCacheEntry(RuleApplicationReference candidate, IEnumerable <RuleApplicationReference> cachedItems, out IEnumerable <RuleApplicationReference> itemsToExpire) { // If cache retention is not our own MyCacheRetention, don't cache MyCacheRetention retention = candidate.CacheRetention as MyCacheRetention; if (retention == null) { itemsToExpire = null; return(false); } // Do not cache specific retention names if (retention.Name == "NOCACHE" || retention.Name == "INVALID") { itemsToExpire = null; return(false); } // Identify cached items to expire - Expire any RuleApplication whose MyCacheRetention has duplicate name as candidate itemsToExpire = cachedItems.Where(item => ((MyCacheRetention)item.CacheRetention).Name == retention.Name); return(true); }
private static async Task <bool> RetrieveAndWriteIrJSFromDistributionService(RuleApplicationReference ruleRef, string distroKey, string outputPath) { Console.WriteLine(); Console.WriteLine("Requesting compiled JS library from Distribution Service..."); var js = await CallDistributionServiceAsync(ruleRef, "https://api.distribution.inrule.com/", distroKey); if (!string.IsNullOrEmpty(js)) { Console.WriteLine("Received compiled library, writing out to " + outputPath); try { File.WriteAllText(outputPath, js); Console.WriteLine("Compiled and wrote out Javascript Rule App"); Console.WriteLine(); return(true); } catch (Exception ex) { Console.WriteLine("Error writing out compiled JavaScript file: " + ex.Message); } } return(false); }
public static async Task <string> CallDistributionServiceAsync(RuleApplicationReference ruleApplicationRef, string serviceUri, string subscriptionKey) { using (var client = new HttpClient()) using (var requestContent = new MultipartFormDataContent()) { HttpResponseMessage result = null; try { client.BaseAddress = new Uri(serviceUri); // Build up our request by reading in the rule application var ruleApplication = ruleApplicationRef.GetRuleApplicationDef(); var httpContent = new ByteArrayContent(Encoding.UTF8.GetBytes(ruleApplication.GetXml())); requestContent.Add(httpContent, "ruleApplication", ruleApplication.Name + ".ruleapp"); // Tell the server we are sending form data client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("multipart/form-data")); client.DefaultRequestHeaders.Add("subscription-key", subscriptionKey); // Post the rule application to the irDistribution service API, // enabling Execution and State Change logging, Display Name metadata, and the developer example. var distributionUrl = "package?logOption=Execution&logOption=StateChanges&subscriptionkey=" + subscriptionKey; result = await client.PostAsync(distributionUrl, requestContent).ConfigureAwait(false); // Get the return package from the result dynamic returnPackage = JObject.Parse(await result.Content.ReadAsStringAsync()); var errors = new StringBuilder(); if (returnPackage.Status.ToString() == "Fail") { foreach (var error in returnPackage.Errors) { // Handle errors errors.AppendLine("* " + error.Description.ToString()); } foreach (var unsupportedError in returnPackage.UnsupportedFeatures) { // Handle errors errors.AppendLine("* " + unsupportedError.Feature.ToString()); } // Still need to stop processing return(errors.ToString()); } // Build the download url of the file var downloadUrl = returnPackage.PackagedApplicationDownloadUrl.ToString(); // Get the contents HttpResponseMessage resultDownload = await client.GetAsync(downloadUrl); if (!resultDownload.IsSuccessStatusCode) { // Handle errors errors.AppendLine(await resultDownload.Content.ReadAsStringAsync()); return(errors.ToString()); } return(await resultDownload.Content.ReadAsStringAsync()); } catch (InRuleCatalogException icex) { Console.WriteLine("Error retrieving Rule Application to compile: " + icex.Message); return(null); } catch (JsonReaderException) { if (result != null) { Console.WriteLine("Error requesting compiled Rule Application: " + await result.Content.ReadAsStringAsync()); } else { Console.WriteLine("Error requesting compiled Rule Application."); } return(null); } catch (Exception ex) { Console.WriteLine("Error requesting compiled Rule Application."); Console.WriteLine(ex.ToString()); return(null); } } }
static async Task <int> Main(string[] args) { //Required Parameters bool showHelp = false; string irDistributionKey = null; string OutputFilePath = null; //Option 1 string RuleAppFilePath = null; //Option 2 string CatalogUri = null; string CatalogUsername = null; string CatalogPassword = null; string CatalogRuleAppName = null; string CatalogRuleAppLabel = "LIVE"; var clParams = new OptionSet { { "h|help", "Display Help.", k => showHelp = true }, { "k|DistributionKey=", "The irDistributionKey for your account.", k => irDistributionKey = k }, { "o|OutputPath=", "Desired Path for the compiled output library.", p => OutputFilePath = p }, //Option 1 { "r|RuleAppPath=", "Path to the Rule Application to be compiled.", p => RuleAppFilePath = p }, //Option 2 { "c|CatUri=", "Web URI for the IrCatalog Service endpoint.", p => CatalogUri = p }, { "u|CatUsername="******"IrCatalog Username for authentication.", p => CatalogUsername = p }, { "p|CatPassword="******"IrCatalog Password for authentication.", p => CatalogPassword = p }, { "n|CatRuleAppName=", "Name of the Rule Application.", p => CatalogRuleAppName = p }, { "l|CatLabel=", "Label of the Rule Application to retrieve (LIVE).", p => CatalogRuleAppLabel = p }, }; try { clParams.Parse(args); } catch (OptionException e) { Console.Write("Failed parsing execution parameters: " + e.Message); showHelp = true; } RuleApplicationReference ruleApp = null; if (showHelp) { ShowHelp(clParams); return(1); } else if (string.IsNullOrEmpty(irDistributionKey)) { Console.WriteLine("Error: Missing required parameter DistributionKey."); return(1); } else if (string.IsNullOrEmpty(OutputFilePath)) { Console.WriteLine("Error: Missing required parameter OutputPath."); return(1); } if (!string.IsNullOrEmpty(RuleAppFilePath)) { try { ruleApp = new FileSystemRuleApplicationReference(RuleAppFilePath); } catch (IntegrationException ie) { Console.WriteLine("Error creating reference to file-based Rule App: " + ie.Message); //Rule App file not found } } if (!string.IsNullOrEmpty(CatalogUri) && !string.IsNullOrEmpty(CatalogUsername) && !string.IsNullOrEmpty(CatalogPassword) && !string.IsNullOrEmpty(CatalogRuleAppName)) { if (ruleApp != null) { Console.WriteLine("Error: Parameters were provided for both File- and Catalog-based Rule App; only one may be specified."); return(1); } else { ruleApp = new CatalogRuleApplicationReference(CatalogUri, CatalogRuleAppName, CatalogUsername, CatalogPassword, CatalogRuleAppLabel); } } if (ruleApp == null) { Console.WriteLine("You must provide either RuleAppPath or all of CatUri, CatUsername, CatPassword, and CatRuleAppName (with optional CatLabel)"); return(1); } else { var success = await RetrieveAndWriteIrJSFromDistributionService(ruleApp, irDistributionKey, OutputFilePath); if (success) { return(0); } else { return(1); } } }
static void PreCompileExecutableFunctions() { Console.WriteLine(); Console.WriteLine("--------------------------------------------------------"); Console.WriteLine("--- PreCompileExecutableFunctions()"); Console.WriteLine("--------------------------------------------------------"); // Ensure RuleApplication cache is empty RuleSession.RuleApplicationCache.Clear(); Console.WriteLine("1) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Expecting 0 // Create 4 in-memory RuleApplications RuleApplicationDef ra1 = new RuleApplicationDef("ra1"); ra1.Entities.Add(new EntityDef("Entity1")).Fields.Add(new FieldDef("Calculation1", "1 + 2", DataType.Integer)); RuleApplicationDef ra2 = new RuleApplicationDef("ra2"); ra2.Entities.Add(new EntityDef("Entity1")).Fields.Add(new FieldDef("Calculation1", "1 + 2", DataType.Integer)); RuleApplicationDef ra3 = new RuleApplicationDef("ra3"); ra3.Entities.Add(new EntityDef("Entity1")).Fields.Add(new FieldDef("Calculation1", "1 + 2", DataType.Integer)); RuleApplicationDef ra4 = new RuleApplicationDef("ra4"); ra4.Entities.Add(new EntityDef("Entity1")).Fields.Add(new FieldDef("Calculation1", "1 + 2", DataType.Integer)); // Create 4 RuleApplicationReferences - Note the implicit casting RuleApplicationReference raRef1 = ra1; RuleApplicationReference raRef2 = ra2; RuleApplicationReference raRef3 = ra3; RuleApplicationReference raRef4 = ra4; // Usage #1: Pre-compile RuleApplications via RuleApplicationCache.Add() - Note EngineLogOptions are compiled into the executable functions raRef1.Compile(CompileSettings.Create(EngineLogOptions.Execution | EngineLogOptions.SummaryStatistics)); raRef2.Compile(); raRef3.Compile(CompileSettings.Create(EngineLogOptions.SummaryStatistics)); raRef4.Compile(CompileSettings.Default); Console.WriteLine("2) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Expecting 4 // Usage #2: Pre-compile RuleApplications via RuleApplicationReference.Compile() RuleSession.RuleApplicationCache.Add(ra1, CompileSettings.Create(EngineLogOptions.Execution | EngineLogOptions.SummaryStatistics)); RuleSession.RuleApplicationCache.Add(ra2); RuleSession.RuleApplicationCache.Add(ra3, CompileSettings.Create(EngineLogOptions.SummaryStatistics)); RuleSession.RuleApplicationCache.Add(ra4, CompileSettings.Default); Console.WriteLine("3) Cached RuleApplications: " + RuleSession.RuleApplicationCache.Count); // Expecting same 4 // Test ra1 - Metadata + Functions pre-compiled Console.WriteLine("--------------------------------------------------------"); Console.WriteLine("4) RuleApplication '{0}' Metadata Compile timestamp: {1}", ra1.Name, raRef1.LastMetadataCompile); Console.WriteLine("5) RuleApplication '{0}' Function Compile timestamp: {1}", ra1.Name, raRef1.GetLastFunctionCompile(CompileSettings.Create(EngineLogOptions.Execution | EngineLogOptions.SummaryStatistics))); using (RuleSession session = new RuleSession(raRef1)) { session.Settings.LogOptions = EngineLogOptions.Execution | EngineLogOptions.SummaryStatistics; session.CreateEntity("Entity1"); session.ApplyRules(); Console.WriteLine("6) RuleApplication '{0}' Dynamic Function Compile Count during rule execution: {1}", ra1.Name, session.Statistics.FunctionCompileTime.SampleCount); // Expecting 0 due to function pre-compile } // Test ra2 - Only Metadata pre-compiled Console.WriteLine("--------------------------------------------------------"); Console.WriteLine("7) RuleApplication '{0}' Metadata Compile timestamp: {1}", ra2.Name, raRef2.LastMetadataCompile); Console.WriteLine("8) RuleApplication '{0}' Function Compile timestamp: {1}", ra2.Name, raRef2.GetLastFunctionCompile(CompileSettings.Create(EngineLogOptions.Execution | EngineLogOptions.SummaryStatistics))); using (RuleSession session = new RuleSession(raRef2)) { session.Settings.LogOptions = EngineLogOptions.Execution | EngineLogOptions.SummaryStatistics; session.CreateEntity("Entity1"); session.ApplyRules(); Console.WriteLine("9) RuleApplication '{0}' Dynamic Function Compile Count during rule execution: {1}", ra2.Name, session.Statistics.FunctionCompileTime.SampleCount); // Expecting 1 due to functions not pre-compile } // Test ra3 - Metadata + Functions pre-compiled Console.WriteLine("--------------------------------------------------------"); Console.WriteLine("10) RuleApplication '{0}' Metadata Compile timestamp: {1}", ra3.Name, raRef3.LastMetadataCompile); Console.WriteLine("11) RuleApplication '{0}' Function Compile timestamp: {1}", ra3.Name, raRef3.GetLastFunctionCompile(CompileSettings.Create(EngineLogOptions.SummaryStatistics))); using (RuleSession session = new RuleSession(raRef3)) { session.Settings.LogOptions = EngineLogOptions.SummaryStatistics; session.CreateEntity("Entity1"); session.ApplyRules(); Console.WriteLine("12) RuleApplication '{0}' Dynamic Function Compile Count during rule execution: {1}", ra3.Name, session.Statistics.FunctionCompileTime.SampleCount); // Expecting 0 due to function pre-copile } // Test ra4 - Metadata + Functions pre-compiled Console.WriteLine("--------------------------------------------------------"); Console.WriteLine("13) RuleApplication '{0}' Metadata Compile timestamp: {1}", ra4.Name, raRef4.LastMetadataCompile); Console.WriteLine("14) RuleApplication '{0}' Function Compile timestamp (Default): {1}", ra4.Name, raRef4.GetLastFunctionCompile(CompileSettings.Default)); // Note: RuleSession Statistics requires EngineLogOptions.SummaryStatistics to be enabled; CompileSettings.Default does not enable SummaryStatistics unless Info logging is enabled in the .config file. // Test ra4 Function Compile timestamp for different type of CompileSettings Console.WriteLine("15) RuleApplication '{0}' Function Compile timestamp (EngineLogOptions.Execution): {1}", ra4.Name, raRef4.GetLastFunctionCompile(CompileSettings.Create(EngineLogOptions.Execution))); // Should be missing because we only checked compiled functions for the Default options }
private static int RunTestSuite(RuleApplicationReference ruleApp, string testSuiteFilePath) { RuleApplicationDef ruleAppDef = null; TestSuiteDef suite = null; try { ruleAppDef = ruleApp.GetRuleApplicationDef(); } catch (Exception ex) { Console.WriteLine("ERROR: Unable to load Rule App: " + ex.Message); return(2); } try { if (File.Exists(testSuiteFilePath)) { Console.WriteLine("Using Test Suite " + testSuiteFilePath); } else { Console.WriteLine("ERROR: Test Suite file not found at " + testSuiteFilePath); throw new FileNotFoundException("ERROR: Test Suite file not found at " + testSuiteFilePath); } suite = TestSuiteDef.LoadFrom(new ZipFileTestSuitePersistenceProvider(testSuiteFilePath)); suite.ActiveRuleApplicationDef = ruleAppDef; } catch (Exception ex) { Console.WriteLine("ERROR: Unable to load Test Suite: " + ex.Message); return(2); } try { TestResultCollection results; using (TestingSessionManager manager = new TestingSessionManager(new InProcessConnectionFactory())) { var session = new RegressionTestingSession(manager, suite); results = session.ExecuteAllTests(); } bool hadFailures = false; foreach (var result in results) { if (result.RuntimeErrorMessage != null) { Console.WriteLine($"ERROR: Failed to execute test {result.TestDef.DisplayName}: {result.RuntimeErrorMessage}"); hadFailures = true; } else if (result.Passed) { Console.WriteLine($"PASS: {result.TestDef.DisplayName}"); } else { hadFailures = true; Console.WriteLine($"FAIL: {result.TestDef.DisplayName}"); foreach (var failedAssertionResult in result.AssertionResults.Where(ar => ar.Passed == false)) { Console.WriteLine($" {failedAssertionResult.Target} was {failedAssertionResult.ActualValue}, expected value {failedAssertionResult.ExpectedValue}"); } } } if (hadFailures) { return(1); } else { return(0); } } catch (Exception ex) { Console.WriteLine("ERROR: Failed to execute test suite: " + ex.Message); return(2); } }