diff --git a/devdocs/todo.txt b/devdocs/todo.txt index 28d72fd7..9466408d 100644 --- a/devdocs/todo.txt +++ b/devdocs/todo.txt @@ -3,7 +3,8 @@ {"login": "OpsAdminLimited","password": "OpsAdminLimited"} - +todo: FAKER, is there a leak, do I need to dispose of it somehow, am I using it right? + (it appeared high in objects in allocated memory when investigating memory consumption) diff --git a/server/AyaNova/Controllers/ServerMetricsController.cs b/server/AyaNova/Controllers/ServerMetricsController.cs index 880f103d..c23c2dcf 100644 --- a/server/AyaNova/Controllers/ServerMetricsController.cs +++ b/server/AyaNova/Controllers/ServerMetricsController.cs @@ -69,7 +69,7 @@ namespace AyaNova.Api.Controllers // //test allocation and cleanup // for (int x = 0; x < 100000; x++) // { -// AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext; +// using (AyContext ct = ServiceProviderProvider.DBContext) // var v=await ct.Widget.Where(z=>z.Serial<100).ToListAsync(); // // int i = await ct.Database.ExecuteSqlRawAsync($"select * from aglobalbizsettings"); // } diff --git a/server/AyaNova/generator/CoreJobSweeper.cs b/server/AyaNova/generator/CoreJobSweeper.cs index 54439db6..7c84f63a 100644 --- a/server/AyaNova/generator/CoreJobSweeper.cs +++ b/server/AyaNova/generator/CoreJobSweeper.cs @@ -36,7 +36,6 @@ namespace AyaNova.Biz log.LogTrace("Sweep starting"); using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext) { - //SWEEP SUCCESSFUL JOBS //calculate cutoff to delete DateTime dtDeleteCutoff = DateTime.UtcNow - SUCCEEDED_JOBS_DELETE_AFTER_THIS_TIMESPAN; @@ -64,7 +63,6 @@ namespace AyaNova.Biz private static async Task sweepAsync(AyContext ct, DateTime dtDeleteCutoff, JobStatus jobStatus) { - // AyContext ct = ServiceProviderProvider.DBContext; //Get the deleteable succeeded jobs list var jobs = await ct.OpsJob .AsNoTracking() @@ -96,8 +94,6 @@ namespace AyaNova.Biz /// private static async Task killStuckJobsAsync(AyContext ct, DateTime dtRunningDeadline) { - - // AyContext ct = ServiceProviderProvider.DBContext; //Get the deleteable succeeded jobs list var jobs = await ct.OpsJob .AsNoTracking() @@ -118,8 +114,7 @@ namespace AyaNova.Biz private static async Task SweepInternalJobsLogsAsync(AyContext ct, DateTime dtDeleteCutoff) - { - // AyContext ct = ServiceProviderProvider.DBContext; + { //Get the deleteable list (this is for reporting, could easily just do it in one go) var logs = await ct.OpsJobLog .AsNoTracking() diff --git a/server/AyaNova/util/Seeder.cs b/server/AyaNova/util/Seeder.cs index 737d234b..3c56ea5c 100644 --- a/server/AyaNova/util/Seeder.cs +++ b/server/AyaNova/util/Seeder.cs @@ -87,9 +87,6 @@ namespace AyaNova.Util apiServerState.SetOpsOnly("Seeding database with sample data"); - - - //WIDGET sample form customization { @@ -140,15 +137,12 @@ namespace AyaNova.Util }; //Create and save to db - using (var cct = ServiceProviderProvider.DBContext) - { - await FormCustomBiz.GetBiz(cct).CreateAsync(fc); - } + using (var ct = ServiceProviderProvider.DBContext) + await FormCustomBiz.GetBiz(ct).CreateAsync(fc); } //Create a couple of DataListView's for development and testing { - var dlv = new DataListView() { Name = "Name starts with generic", @@ -156,14 +150,11 @@ namespace AyaNova.Util ListKey = "TestWidgetDataList", Public = true, ListView = @"[{""fld"": ""widgetname"",""filter"": {""any"":false,""items"": [{""op"": ""%-"",""value"": ""Generic""}]}}]" - }; //Create and save to db - using (var cct = ServiceProviderProvider.DBContext) - { - await DataListViewBiz.GetBiz(cct).CreateAsync(dlv); - } + using (var ct = ServiceProviderProvider.DBContext) + await DataListViewBiz.GetBiz(ct).CreateAsync(dlv); dlv = new DataListView() { @@ -172,14 +163,11 @@ namespace AyaNova.Util ListKey = "TestWidgetDataList", Public = true, ListView = @"[{""fld"": ""widgetname"",""filter"": {""any"":false,""items"": [{""op"": ""%-"",""value"": ""Awesome""}]}},{""fld"":""widgetserial""},{""fld"":""widgetdollaramount""},{""fld"":""widgetusertype""},{""fld"":""widgetstartdate""},{""fld"":""widgetactive""},{""fld"":""username""},{""fld"":""widgettags""},{""fld"":""widgetcustom1""},{""fld"":""widgetcustom2""}]" - }; //Create and save to db - using (var cct = ServiceProviderProvider.DBContext) - { - await DataListViewBiz.GetBiz(cct).CreateAsync(dlv); - } + using (var ct = ServiceProviderProvider.DBContext) + await DataListViewBiz.GetBiz(ct).CreateAsync(dlv); } @@ -560,13 +548,6 @@ namespace AyaNova.Util if (translationId == 0) translationId = ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID; - //Don't do the following commented out, it's slower - // using (var ct = ServiceProviderProvider.DBContext) - // { - // UserBiz Biz = UserBiz.GetBiz(ct); - - - Faker Fake = new Faker(); for (int x = 0; x < count; x++) @@ -592,7 +573,7 @@ namespace AyaNova.Util u.UserType = userType; u.EmployeeNumber = "A-" + (454 + SeededUserCount).ToString() + "-Y"; - u.Notes = Fake.Lorem.Sentence(null,5);//Fake.Lorem.Paragraph(2); + u.Notes = Fake.Lorem.Sentence(null, 5);//Fake.Lorem.Paragraph(2); //TODO: After have USER and HEADOFFICE and VENDOR, if usertype is subcontractor or client or headoffice it needs to set a corresponding user's parent org record id to go with it //use provided tags or generate them if (tags == null) @@ -607,143 +588,143 @@ namespace AyaNova.Util u.UserOptions.CurrencyName = "USD"; u.UserOptions.UiColor = Fake.Internet.Color(); -// u.Wiki = @" + // u.Wiki = @" -// # Markdown quick reference for Wiki pages -// *** -// *** -//
+ // # Markdown quick reference for Wiki pages + // *** + // *** + //
-// ## Markdown and Wiki documents -// Wiki's are formatted using **[Markdown](https://en.wikipedia.org/wiki/Markdown)** a plain text formatting language. -// This document is a quick reference guide and at the bottom is a link to a more comprehensive guide online. -// You can also use the formatting toolbar above to perform the same tasks. + // ## Markdown and Wiki documents + // Wiki's are formatted using **[Markdown](https://en.wikipedia.org/wiki/Markdown)** a plain text formatting language. + // This document is a quick reference guide and at the bottom is a link to a more comprehensive guide online. + // You can also use the formatting toolbar above to perform the same tasks. -// # Headings -// # Heading 1st level -// ## Heading 2nd level -// ### Heading 3rd level -// #### Heading 4th level -// ##### Heading 5th level -// ###### Heading 6th level -// *** -// # Emphasis text styles -// *Italic* -// **Bold** -// ~~Strike-through~~ -// ***Bold And Italic*** + // # Headings + // # Heading 1st level + // ## Heading 2nd level + // ### Heading 3rd level + // #### Heading 4th level + // ##### Heading 5th level + // ###### Heading 6th level + // *** + // # Emphasis text styles + // *Italic* + // **Bold** + // ~~Strike-through~~ + // ***Bold And Italic*** -// # Quote blocks -// > ""Morbi eget dapibus felis. Vivamus venenatis porttitor tortor sit amet rutrum. -// Pellentesque aliquet quam enim, eu volutpat urna rutrum a. Nam vehicula nunc -// > -// > mauris, a ultricies libero efficitur sed. *Class aptent* taciti sociosqu ad -// litora torquent per conubia nostra, per inceptos himenaeos. Sed molestie -// imperdiet consectetur."" + // # Quote blocks + // > ""Morbi eget dapibus felis. Vivamus venenatis porttitor tortor sit amet rutrum. + // Pellentesque aliquet quam enim, eu volutpat urna rutrum a. Nam vehicula nunc + // > + // > mauris, a ultricies libero efficitur sed. *Class aptent* taciti sociosqu ad + // litora torquent per conubia nostra, per inceptos himenaeos. Sed molestie + // imperdiet consectetur."" -// # Lists -// ### Unordered list -// * List -// * List -// * List + // # Lists + // ### Unordered list + // * List + // * List + // * List -// ### Ordered list -// 1. One -// 2. Two -// 3. Three + // ### Ordered list + // 1. One + // 2. Two + // 3. Three -// ### Auto number ordered list -// Ordered lists don't need the numbers to be in order, just that they start with 1: -// 1. Item -// 1. another item -// 1. more item + // ### Auto number ordered list + // Ordered lists don't need the numbers to be in order, just that they start with 1: + // 1. Item + // 1. another item + // 1. more item -// ### Nested lists -// * First -// * subitem One -// * subitem Two -// * Second -// 1. sub one -// 2. sub two + // ### Nested lists + // * First + // * subitem One + // * subitem Two + // * Second + // 1. sub one + // 2. sub two -// # Blank lines -// You can force extra blank lines by entering `
` here are two blank ... -//
-//
-// ...lines. + // # Blank lines + // You can force extra blank lines by entering `
` here are two blank ... + //
+ //
+ // ...lines. -// # Horizontal rules + // # Horizontal rules -// *** + // *** -// # Blocks -// `Inline block` with backticks + // # Blocks + // `Inline block` with backticks -// ``` -// Multi-line block -// print '3 backticks or' -// print 'indent 4 spaces' -// ``` + // ``` + // Multi-line block + // print '3 backticks or' + // print 'indent 4 spaces' + // ``` -// # Task lists + // # Task lists -// - [ ] task one -// - [x] task two (completed) + // - [ ] task one + // - [x] task two (completed) -// # TABLES + // # TABLES -// | First | Last | Year | -// | -------- | -------- | -------- | -// | John | Doe | 2000 | -// | Mary | Smith | 2001 | -// | T. | Persson | 2010 | + // | First | Last | Year | + // | -------- | -------- | -------- | + // | John | Doe | 2000 | + // | Mary | Smith | 2001 | + // | T. | Persson | 2010 | -// # Hyperlinks -// Inline text link and and optional tooltip: -// Link to [our website](https://ayanova.com ""Hover text tooltip"") example + // # Hyperlinks + // Inline text link and and optional tooltip: + // Link to [our website](https://ayanova.com ""Hover text tooltip"") example -// If you don't need an inline link you can simply enter it in angle brackets: -// -// Even email links work: -// -//
-// You can also use emphasis characters with links: -// Link to **[our website](https://ayanova.com)** example + // If you don't need an inline link you can simply enter it in angle brackets: + // + // Even email links work: + // + //
+ // You can also use emphasis characters with links: + // Link to **[our website](https://ayanova.com)** example -// # Image -// This is how you insert an image into a wiki -// ![Image](https://www.ayanova.com/images/AyaNovaIcon256.png) + // # Image + // This is how you insert an image into a wiki + // ![Image](https://www.ayanova.com/images/AyaNovaIcon256.png) -// # Emojis -// As with all areas of AyaNova where you can enter text, you can also use emoji characters: -// # 😀⚽🏒🍕🚗☀❤😎 -//
+ // # Emojis + // As with all areas of AyaNova where you can enter text, you can also use emoji characters: + // # 😀⚽🏒🍕🚗☀❤😎 + //
-// # Markdown guide -// A more detailed markdown guide is available here: -// + // # Markdown guide + // A more detailed markdown guide is available here: + // -// *** -// "; + // *** + // "; - //this seems wrong but is actually faster!? - UserBiz Biz = UserBiz.GetBiz(ServiceProviderProvider.DBContext); - //allow creation of not entirely ready users (missing client id or subcontractor vendor id etc) - Biz.SeedOrImportRelaxedRulesMode = true; - - - var NewObject = await Biz.CreateAsync(u); - if (NewObject == null) + //this seems wrong to get a new context inside a loop but in testing is actually faster!? + using (AyContext ct = ServiceProviderProvider.DBContext) { - log.LogError($"Seeder::GenSeedUser error creating user {u.Name}\r\n" + Biz.GetErrorsAsString()); - throw new System.Exception("Seeder::GenSeedUser error creating user\r\n" + Biz.GetErrorsAsString()); + UserBiz Biz = UserBiz.GetBiz(ct); + //allow creation of not entirely ready users (missing client id or subcontractor vendor id etc) + Biz.SeedOrImportRelaxedRulesMode = true; + var NewObject = await Biz.CreateAsync(u); + if (NewObject == null) + { + log.LogError($"Seeder::GenSeedUser error creating user {u.Name}\r\n" + Biz.GetErrorsAsString()); + throw new System.Exception("Seeder::GenSeedUser error creating user\r\n" + Biz.GetErrorsAsString()); + } } - //} } SeededUserCount += count; @@ -756,9 +737,9 @@ namespace AyaNova.Util { //this is 4 times slower than doing it inside the loop below //seems counterintuitive but maybe it's to do with the db context not being refreshed? - // WidgetBiz biz = WidgetBiz.GetBiz(ServiceProviderProvider.DBContext); - var f = new Bogus.Faker(); + + var f = new Bogus.Faker();//todo: this *can't* be right, I'm seeding 20k widgets in some cases //RANDOM ROLES @@ -771,44 +752,38 @@ namespace AyaNova.Util { Widget o = new Widget(); o.Name = Uniquify(f.Commerce.ProductName()); - o.Active = true; - // o.StartDate = f.Date.Between(DateTime.Now, DateTime.Now.AddMinutes(60)).ToUniversalTime(); - // o.EndDate = f.Date.Between(DateTime.Now.AddMinutes(90), DateTime.Now.AddHours(5)).ToUniversalTime(); - - // o.StartDate = DateTime.Now.ToUniversalTime(); - // o.EndDate = DateTime.Now.AddMinutes(60).ToUniversalTime(); + o.Active = true; DateTime dtSeed = f.Date.Between(seedStartWindow, seedEndWindow).ToUniversalTime(); o.StartDate = dtSeed; o.EndDate = dtSeed.AddMinutes(60).ToUniversalTime(); o.DollarAmount = Convert.ToDecimal(f.Commerce.Price()); + //Random but valid enum UserType randomUserType = (UserType)values.GetValue(random.Next(values.Length)); o.UserType = randomUserType; - - o.Notes = f.Lorem.Sentence(null,5); - + o.Notes = f.Lorem.Sentence(null, 5); o.Tags = RandomTags(f); - o.UserId = f.Random.Int(1, SeededUserCount); //RANDOM CUSTOM FIELD DATA var c1 = DateUtil.UniversalISO8661Format(f.Date.Between(DateTime.Now.AddYears(-1), DateTime.Now.AddYears(1))); - var c2 = f.Lorem.Sentence(null,5); + var c2 = f.Lorem.Sentence(null, 5); var c3 = f.Random.Int(1, 99999999); var c4 = f.Random.Bool().ToString().ToLowerInvariant(); var c5 = f.Random.Decimal(); - o.CustomFields = $@"{{c1:""{c1}"",c2:""{c2}"",c3:{c3},c4:{c4},c5:{c5}}}"; //This seems wrong to do in a loop but is 4 times faster this way ?!? - WidgetBiz biz = WidgetBiz.GetBiz(ServiceProviderProvider.DBContext); - var NewObject = await biz.CreateAsync(o); - if (NewObject == null) + using (AyContext ct = ServiceProviderProvider.DBContext) { - log.LogError($"Seeder::GenSeedWidget error creating widget {o.Name}\r\n" + biz.GetErrorsAsString()); - throw new System.Exception("Seeder::GenSeedWidget error creating widget\r\n" + biz.GetErrorsAsString()); + WidgetBiz biz = WidgetBiz.GetBiz(ct); + var NewObject = await biz.CreateAsync(o); + if (NewObject == null) + { + log.LogError($"Seeder::GenSeedWidget error creating widget {o.Name}\r\n" + biz.GetErrorsAsString()); + throw new System.Exception("Seeder::GenSeedWidget error creating widget\r\n" + biz.GetErrorsAsString()); + } } - } }