diff --git a/devdocs/todo.txt b/devdocs/todo.txt
index 694f756d..2a2c83f2 100644
--- a/devdocs/todo.txt
+++ b/devdocs/todo.txt
@@ -4,28 +4,23 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNTcxODU5OTU0IiwiZXhwIjoiMTU3MjQ
## IMMEDIATE ITEMS
+TODO: Ensure scaleability by checking for performance issues now before replicating code (particularly in widget etc)
+ - As per this document https://docs.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-3.1
+ - For scaleability go back to async only for any db calls functions like creating widgets etc
+
-
-
-
-
-
-UPDATE SPEC DOCS with new format and names etc or at least remove nonsense as necessary
-
-UPDATE MANUAL API REGARDING LISTS
-
-
+TODO: REFACTOR GetNoLogAsync function is used in many places redundantly when the logging version could do the same thing but not log it with an optional bool switch so refactor that shit
+TODO: REFACTOR biz objects have two creates, an async and sync one, WTF is that about? See if can make it just one async version.
+ - https://docs.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-3.1
TODO: Need route to gather all object role rights in a format useful to display in UI so that a biz manager can see at a glance the rights for different roles to objects
- This way it's dynamic and picked up from the code itself which is always the source of truth so no need to put in the manual
- Would likely want to display multiple ways: for a specific object or role or selected user maybe too in the user info form ("effective roles")
- Move this over to client once the backend supports it
-TODO: REFACTOR GetNoLogAsync function is used in many places redundantly when the logging version could do the same thing but not log it with an optional bool switch so refactor that shit
-TODO: REFACTOR biz objects have two creates, an async and sync one, WTF is that about? See if can make it just one async version.
-
-
+UPDATE SPEC DOCS with new format and names etc or at least remove nonsense as necessary
+UPDATE MANUAL API REGARDING LISTS
TODO: DataFilter how to distinguish between filtering on specific ID value or on value column
- Might need to add a filter on ID type of thing maybe?
diff --git a/server/AyaNova/Controllers/AttachmentController.cs b/server/AyaNova/Controllers/AttachmentController.cs
index 40fb699d..531e8287 100644
--- a/server/AyaNova/Controllers/AttachmentController.cs
+++ b/server/AyaNova/Controllers/AttachmentController.cs
@@ -230,7 +230,7 @@ namespace AyaNova.Api.Controllers
});
//EVENT LOG
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, attachToObject.ObjectId, attachToObject.ObjectType, AyaEvent.AttachmentCreate, v.DisplayFileName), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, attachToObject.ObjectId, attachToObject.ObjectType, AyaEvent.AttachmentCreate, v.DisplayFileName), ct);
//SEARCH INDEXING
// Search.ProcessNewObjectKeywords( UserLocaleIdFromContext.Id(HttpContext.Items), v.Id, AyaType.FileAttachment, v.DisplayFileName, v.DisplayFileName, v.Notes, v.StoredFileName);
@@ -303,7 +303,7 @@ namespace AyaNova.Api.Controllers
FileUtil.deleteFileAttachment(dbObj, ct);
//Event log process delete
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDelete, dbObj.DisplayFileName), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDelete, dbObj.DisplayFileName), ct);
//Delete search index
Search.ProcessDeletedObjectKeywords(dbObj.Id, AyaType.FileAttachment);
@@ -385,7 +385,7 @@ namespace AyaNova.Api.Controllers
}
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDownload, dbObj.DisplayFileName), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDownload, dbObj.DisplayFileName), ct);
return PhysicalFile(filePath, mimetype, dbObj.DisplayFileName);
diff --git a/server/AyaNova/Controllers/LicenseController.cs b/server/AyaNova/Controllers/LicenseController.cs
index bd2d061e..df33edd0 100644
--- a/server/AyaNova/Controllers/LicenseController.cs
+++ b/server/AyaNova/Controllers/LicenseController.cs
@@ -121,7 +121,7 @@ namespace AyaNova.Api.Controllers
}
var ret = AyaNova.Core.License.LicenseInfoAsJson;
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseFetch), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseFetch), ct);
return Ok(ApiOkResponse.Response(ret, true));
}
@@ -169,7 +169,7 @@ namespace AyaNova.Api.Controllers
var ret = Core.License.RequestTrial(requestData.EmailAddress, requestData.RegisteredTo, log);
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseTrialRequest), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseTrialRequest), ct);
return Ok(ApiOkResponse.Response(ret, true));
}
diff --git a/server/AyaNova/Controllers/LocaleController.cs b/server/AyaNova/Controllers/LocaleController.cs
index 34a9e808..c861a8b1 100644
--- a/server/AyaNova/Controllers/LocaleController.cs
+++ b/server/AyaNova/Controllers/LocaleController.cs
@@ -360,7 +360,7 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(biz.Errors));
}
//Log
- EventLogProcessor.DeleteObject(biz.UserId, AyaType.Locale, dbObj.Id, dbObj.Name, ct);
+ EventLogProcessor.DeleteObjectLogAsync(biz.UserId, AyaType.Locale, dbObj.Id, dbObj.Name, ct);
await ct.SaveChangesAsync();
//Delete children / attached objects
diff --git a/server/AyaNova/Controllers/MetricsController.cs b/server/AyaNova/Controllers/MetricsController.cs
index a0bae851..809b11f6 100644
--- a/server/AyaNova/Controllers/MetricsController.cs
+++ b/server/AyaNova/Controllers/MetricsController.cs
@@ -66,7 +66,7 @@ namespace AyaNova.Api.Controllers
string sResult = await GetTheMetrics("plain");
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct);
return Content(sResult);
}
@@ -94,7 +94,7 @@ namespace AyaNova.Api.Controllers
JObject json = JObject.Parse(sResult);
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct);
return Ok(ApiOkResponse.Response(json, true));
}
diff --git a/server/AyaNova/Controllers/ServerStateController.cs b/server/AyaNova/Controllers/ServerStateController.cs
index 76221602..ee4aee00 100644
--- a/server/AyaNova/Controllers/ServerStateController.cs
+++ b/server/AyaNova/Controllers/ServerStateController.cs
@@ -88,7 +88,7 @@ namespace AyaNova.Api.Controllers
serverState.SetState(desiredState, state.Reason);
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.ServerState, AyaEvent.ServerStateChange, $"{state.ServerState}-{state.Reason}"), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.ServerState, AyaEvent.ServerStateChange, $"{state.ServerState}-{state.Reason}"), ct);
return NoContent();
}
diff --git a/server/AyaNova/Controllers/TagListController.cs b/server/AyaNova/Controllers/TagListController.cs
index bbd44305..4153c9ef 100644
--- a/server/AyaNova/Controllers/TagListController.cs
+++ b/server/AyaNova/Controllers/TagListController.cs
@@ -54,7 +54,7 @@ namespace AyaNova.Api.Controllers
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
}
- return Ok(ApiOkResponse.Response(TagUtil.PickListFiltered(ct, query),true));
+ return Ok(ApiOkResponse.Response(TagUtil.PickListFilteredAsync(ct, query),true));
}
@@ -72,7 +72,7 @@ namespace AyaNova.Api.Controllers
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
}
- return Ok(ApiOkResponse.Response(TagUtil.CloudListFiltered(ct, query), true));
+ return Ok(ApiOkResponse.Response(TagUtil.CloudListFilteredAsync(ct, query), true));
}
diff --git a/server/AyaNova/Controllers/TrialController.cs b/server/AyaNova/Controllers/TrialController.cs
index f2968534..110b6e6e 100644
--- a/server/AyaNova/Controllers/TrialController.cs
+++ b/server/AyaNova/Controllers/TrialController.cs
@@ -104,7 +104,7 @@ namespace AyaNova.Api.Controllers
JobsBiz.AddJob(j, ct);
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.TrialSeeder, AyaEvent.Created, size), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.TrialSeeder, AyaEvent.Created, size), ct);
return Accepted(new { JobId = j.GId });//202 accepted
}
diff --git a/server/AyaNova/biz/DataListFilterBiz.cs b/server/AyaNova/biz/DataListFilterBiz.cs
index 91936cfc..489ba7f9 100644
--- a/server/AyaNova/biz/DataListFilterBiz.cs
+++ b/server/AyaNova/biz/DataListFilterBiz.cs
@@ -65,7 +65,7 @@ namespace AyaNova.Biz
//Handle child and associated items:
//EVENT LOG
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
//SEARCH INDEXING
// Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name);
@@ -95,7 +95,7 @@ namespace AyaNova.Biz
//Handle child and associated items:
//EVENT LOG
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), TempContext);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), TempContext);
//SEARCH INDEXING
// Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name);
@@ -116,7 +116,7 @@ namespace AyaNova.Biz
if (ret != null)
{
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
}
return ret;
}
@@ -175,7 +175,7 @@ namespace AyaNova.Biz
return false;
//Log modification and save context
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
//Update keywords
// Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.Name);
@@ -201,7 +201,7 @@ namespace AyaNova.Biz
//Delete sibling objects
//Event log process delete
- EventLogProcessor.DeleteObject(UserId, BizType, dbObj.Id, dbObj.Name, ct);
+ EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct);
ct.SaveChanges();
//Delete search index
diff --git a/server/AyaNova/biz/DataListTemplateBiz.cs b/server/AyaNova/biz/DataListTemplateBiz.cs
index a14df33f..d30b9f67 100644
--- a/server/AyaNova/biz/DataListTemplateBiz.cs
+++ b/server/AyaNova/biz/DataListTemplateBiz.cs
@@ -56,7 +56,7 @@ namespace AyaNova.Biz
if (log)
{
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, ret.Id, BizType, AyaEvent.Retrieved), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, ret.Id, BizType, AyaEvent.Retrieved), ct);
}
return ret;
}
@@ -85,7 +85,7 @@ namespace AyaNova.Biz
return false;
//Log modification and save context
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
return true;
}
@@ -100,7 +100,7 @@ namespace AyaNova.Biz
ct.DataListTemplate.Remove(dbObj);
ct.SaveChanges();
//Event log process delete
- EventLogProcessor.DeleteObject(UserId, BizType, dbObj.Id, dbObj.DataListKey, ct);
+ EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.DataListKey, ct);
ct.SaveChanges();
return true;
}
diff --git a/server/AyaNova/biz/EventLogProcessor.cs b/server/AyaNova/biz/EventLogProcessor.cs
index c30b4cf7..a2ad8637 100644
--- a/server/AyaNova/biz/EventLogProcessor.cs
+++ b/server/AyaNova/biz/EventLogProcessor.cs
@@ -1,12 +1,7 @@
-using System;
-using System.Text;
using System.Linq;
using System.Threading.Tasks;
-using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Logging;
using AyaNova.Models;
-using AyaNova.Util;
namespace AyaNova.Biz
@@ -21,10 +16,10 @@ namespace AyaNova.Biz
///
///
///
- internal static void LogEventToDatabaseAndSaveEntireContext(Event newEvent, AyContext ct)
+ internal static async Task LogEventToDatabaseAsync(Event newEvent, AyContext ct)
{
- ct.Event.Add(newEvent);
- ct.SaveChanges();
+ await ct.Event.AddAsync(newEvent);
+ await ct.SaveChangesAsync();
}
@@ -38,10 +33,11 @@ namespace AyaNova.Biz
///
///
///
- internal static void DeleteObject(long userId, AyaType ayType, long ayId, string textra, AyContext ct)
+ internal static async Task DeleteObjectLogAsync(long userId, AyaType ayType, long ayId, string textra, AyContext ct)
{
- ct.Database.ExecuteSqlInterpolated($"delete from aevent where aytype = {ayType} and ayid={ayId}");
- ct.Event.Add(new Event(userId, ayId, ayType, AyaEvent.Deleted, textra));
+ await ct.Database.ExecuteSqlInterpolatedAsync($"delete from aevent where aytype = {ayType} and ayid={ayId}");
+ await ct.Event.AddAsync(new Event(userId, ayId, ayType, AyaEvent.Deleted, textra));
+ await ct.SaveChangesAsync();
}
///
@@ -53,7 +49,7 @@ namespace AyaNova.Biz
//This is also an example of conditional where statements
//Set up the query
- var q = ct.Event.Select(m => m);
+ var q = ct.Event.Select(m => m).AsNoTracking();
q = q.Where(m => m.AyId == opt.AyId);
diff --git a/server/AyaNova/biz/FormCustomBiz.cs b/server/AyaNova/biz/FormCustomBiz.cs
index cae604e5..c65229b4 100644
--- a/server/AyaNova/biz/FormCustomBiz.cs
+++ b/server/AyaNova/biz/FormCustomBiz.cs
@@ -71,7 +71,7 @@ namespace AyaNova.Biz
//Handle child and associated items:
//EVENT LOG
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
//SEARCH INDEXING
// Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name);
@@ -141,7 +141,7 @@ namespace AyaNova.Biz
dbObj.Template = JsonUtil.CompactJson(dbObj.Template);
//Log modification and save context
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
//Update keywords
// Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.Name);
diff --git a/server/AyaNova/biz/ImportAyaNova7Biz.cs b/server/AyaNova/biz/ImportAyaNova7Biz.cs
index 5113cc70..115b04f9 100644
--- a/server/AyaNova/biz/ImportAyaNova7Biz.cs
+++ b/server/AyaNova/biz/ImportAyaNova7Biz.cs
@@ -349,9 +349,9 @@ namespace AyaNova.Biz
//handle EventLog entries for users now that we have the user's created
//Created
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(Creator, RavenId, ayaType, AyaEvent.Created, Created), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(Creator, RavenId, ayaType, AyaEvent.Created, Created), ct);
//MODIFIED
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(Modifier, RavenId, ayaType, AyaEvent.Modified, Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(Modifier, RavenId, ayaType, AyaEvent.Modified, Modified), ct);
}
diff --git a/server/AyaNova/biz/LocaleBiz.cs b/server/AyaNova/biz/LocaleBiz.cs
index 1a2f36f8..2f8878d8 100644
--- a/server/AyaNova/biz/LocaleBiz.cs
+++ b/server/AyaNova/biz/LocaleBiz.cs
@@ -77,7 +77,7 @@ namespace AyaNova.Biz
ct.Locale.Add(NewLocale);
await ct.SaveChangesAsync();
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, NewLocale.Id, AyaType.Locale, AyaEvent.Created), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, NewLocale.Id, AyaType.Locale, AyaEvent.Created), ct);
return NewLocale;
}
@@ -242,7 +242,7 @@ namespace AyaNova.Biz
ct.SaveChanges();
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbParent.Id, AyaType.Locale, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbParent.Id, AyaType.Locale, AyaEvent.Modified), ct);
return true;
}
@@ -269,7 +269,7 @@ namespace AyaNova.Biz
ct.SaveChanges();
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.Id, AyaType.Locale, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, AyaType.Locale, AyaEvent.Modified), ct);
return true;
}
@@ -611,7 +611,7 @@ namespace AyaNova.Biz
ct.SaveChanges();
//Log now that we have the Id, note that there is no source created / modified for this so just attributing to current userId
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, l.Id, AyaType.Locale, AyaEvent.Created), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, l.Id, AyaType.Locale, AyaEvent.Created), ct);
}
break;
diff --git a/server/AyaNova/biz/TagUtil.cs b/server/AyaNova/biz/TagUtil.cs
index 0ca6e165..3703eb0e 100644
--- a/server/AyaNova/biz/TagUtil.cs
+++ b/server/AyaNova/biz/TagUtil.cs
@@ -4,6 +4,7 @@ using AyaNova.Util;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using AyaNova.Models;
+using System.Threading.Tasks;
namespace AyaNova.Biz
{
@@ -42,7 +43,7 @@ namespace AyaNova.Biz
- public static void ProcessDeleteTagsInRepository(AyContext ct, List deleteTags)
+ public static async Task ProcessDeleteTagsInRepositoryAsync(AyContext ct, List deleteTags)
{
if (deleteTags.Count == 0) return;
foreach (string s in deleteTags)
@@ -55,7 +56,7 @@ namespace AyaNova.Biz
do
{
//START: Get tag word and concurrency token and count
- var ExistingTag = ct.Tag.FirstOrDefault(x => x.Name == s);
+ var ExistingTag = await ct.Tag.FirstOrDefaultAsync(x => x.Name == s);
//if not present, then nothing to do
if (ExistingTag != null)
{
@@ -73,7 +74,7 @@ namespace AyaNova.Biz
try
{
- ct.SaveChanges();
+ await ct.SaveChangesAsync();
bDone = true;
}
catch (Exception ex) when (ex is DbUpdateConcurrencyException)//allow for possible other types
@@ -86,7 +87,7 @@ namespace AyaNova.Biz
}
}
- public static void ProcessUpdateTagsInRepository(AyContext ct, List newTags, List originalTags = null)
+ public static async Task ProcessUpdateTagsInRepositoryAsync(AyContext ct, List newTags, List originalTags = null)
{
//just in case no new tags are present which could mean a user removed all tags from a record so this
//needs to proceed with the code below even if newTags is null as long as originalTags isn't also null
@@ -124,11 +125,11 @@ namespace AyaNova.Biz
do
{
//START: Get tag word and concurrency token and count
- var ExistingTag = ct.Tag.FirstOrDefault(x => x.Name == s);
+ var ExistingTag = await ct.Tag.FirstOrDefaultAsync(x => x.Name == s);
//if not present, then add it with a count of 0
if (ExistingTag == null)
{
- ct.Tag.Add(new Tag() { Name = s, RefCount = 1 });
+ await ct.Tag.AddAsync(new Tag() { Name = s, RefCount = 1 });
}
else
{
@@ -137,7 +138,7 @@ namespace AyaNova.Biz
}
try
{
- ct.SaveChanges();
+ await ct.SaveChangesAsync();
bDone = true;
}
catch (Exception ex) when (ex is DbUpdateConcurrencyException)//this allows for other types
@@ -149,43 +150,57 @@ namespace AyaNova.Biz
}
//DELETE TAGS
- ProcessDeleteTagsInRepository(ct, deleteTags);
+ await ProcessDeleteTagsInRepositoryAsync(ct, deleteTags);
}
//Pick list for driving pick list route
//going with contains for now as I think it's more useful in the long run and still captures startswith intent by user
- public static List PickListFiltered(AyContext ct, string q)
+ public static async Task> PickListFilteredAsync(AyContext ct, string q)
{
//This path is intended for internal use and accepts that there may not be a filter specified
//however the client will always require a filter to display a tag list for choosing from
if (string.IsNullOrWhiteSpace(q))
{
- return ct.Tag.OrderBy(x => x.Name).Select(x => x.Name).ToList();
+ return await ct.Tag.OrderBy(x => x.Name)
+ .Select(x => x.Name)
+ .AsNoTracking()
+ .ToListAsync();
}
else
{
q = NormalizeTag(q);
- return ct.Tag.Where(x => x.Name.Contains(q)).OrderBy(x => x.Name).Select(x => x.Name).Take(25).ToList();
+ return await ct.Tag
+ .Where(x => x.Name.Contains(q))
+ .OrderBy(x => x.Name)
+ .Select(x => x.Name)
+ .Take(25)
+ .AsNoTracking()
+ .ToListAsync();
}
}
//Cloud list
- public static List CloudListFiltered(AyContext ct, string q)
+ public static async Task> CloudListFilteredAsync(AyContext ct, string q)
{
//This path is intended for internal use and accepts that there may not be a filter specified
//however the client will always require a filter to display a tag list for choosing from
if (string.IsNullOrWhiteSpace(q))
{
- return ct.Tag.OrderByDescending(x => x.RefCount).Select(x => new TagCloudItem() { Name = x.Name, RefCount = x.RefCount }).ToList();
+ return await ct.Tag.OrderByDescending(x => x.RefCount).Select(x => new TagCloudItem() { Name = x.Name, RefCount = x.RefCount }).AsNoTracking().ToListAsync();
}
else
{
q = NormalizeTag(q);
//TODO: Use the EF CORE TAKE method to restrict the results to a maximum limit
//however need to ensure it doesn't balk when the limit is higher than the number of results (probably not but test that)
- return ct.Tag.Where(x => x.Name.Contains(q)).OrderByDescending(x => x.RefCount).Select(x => new TagCloudItem() { Name = x.Name, RefCount = x.RefCount }).ToList();
+ return await ct.Tag
+ .Where(x => x.Name.Contains(q))
+ .OrderByDescending(x => x.RefCount)
+ .Select(x => new TagCloudItem() { Name = x.Name, RefCount = x.RefCount })
+ .AsNoTracking()
+ .ToListAsync();
}
}
diff --git a/server/AyaNova/biz/UserBiz.cs b/server/AyaNova/biz/UserBiz.cs
index d82e66a9..c14f066d 100644
--- a/server/AyaNova/biz/UserBiz.cs
+++ b/server/AyaNova/biz/UserBiz.cs
@@ -81,13 +81,13 @@ namespace AyaNova.Biz
//Handle child and associated items
//Log event
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, inObj.Id, BizType, AyaEvent.Created), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, inObj.Id, BizType, AyaEvent.Created), ct);
//SEARCH INDEXING
SearchIndex(inObj, true);
//TAGS
- TagUtil.ProcessUpdateTagsInRepository(ct, inObj.Tags, null);
+ TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, inObj.Tags, null);
return inObj;
@@ -123,13 +123,13 @@ namespace AyaNova.Biz
//Handle child and associated items
//Log event
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, inObj.Id, BizType, AyaEvent.Created), TempContext);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, inObj.Id, BizType, AyaEvent.Created), TempContext);
//SEARCH INDEXING
SearchIndex(inObj, true);
//TAGS
- TagUtil.ProcessUpdateTagsInRepository(TempContext, inObj.Tags, null);
+ TagUtil.ProcessUpdateTagsInRepositoryAsync(TempContext, inObj.Tags, null);
return inObj;
@@ -147,7 +147,7 @@ namespace AyaNova.Biz
if (ret != null)
{
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
}
return ret;
}
@@ -302,11 +302,11 @@ namespace AyaNova.Biz
//Log modification and save context
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
SearchIndex(dbObj, false);
- TagUtil.ProcessUpdateTagsInRepository(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
+ TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
return true;
}
@@ -339,10 +339,10 @@ namespace AyaNova.Biz
return false;
//Log modification and save context
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
SearchIndex(dbObj, false);
- TagUtil.ProcessUpdateTagsInRepository(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
+ TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
return true;
}
@@ -379,10 +379,10 @@ namespace AyaNova.Biz
ct.Database.ExecuteSqlInterpolated($"delete from auseroptions where userid={dbObj.Id}");
- EventLogProcessor.DeleteObject(UserId, BizType, dbObj.Id, dbObj.Name, ct);
+ EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct);
ct.SaveChanges();
Search.ProcessDeletedObjectKeywords(dbObj.Id, BizType);
- TagUtil.ProcessDeleteTagsInRepository(ct, dbObj.Tags);
+ TagUtil.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags);
return true;
}
diff --git a/server/AyaNova/biz/UserOptionsBiz.cs b/server/AyaNova/biz/UserOptionsBiz.cs
index f85d7885..5fdd1dc5 100644
--- a/server/AyaNova/biz/UserOptionsBiz.cs
+++ b/server/AyaNova/biz/UserOptionsBiz.cs
@@ -59,7 +59,7 @@ namespace AyaNova.Biz
ct.SaveChanges();
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.Id, AyaType.UserOptions, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, AyaType.UserOptions, AyaEvent.Modified), ct);
return true;
}
@@ -79,7 +79,7 @@ namespace AyaNova.Biz
ct.SaveChanges();
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.Id, AyaType.UserOptions, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, AyaType.UserOptions, AyaEvent.Modified), ct);
return true;
}
diff --git a/server/AyaNova/biz/WidgetBiz.cs b/server/AyaNova/biz/WidgetBiz.cs
index 9ca38bc4..77bf3e3f 100644
--- a/server/AyaNova/biz/WidgetBiz.cs
+++ b/server/AyaNova/biz/WidgetBiz.cs
@@ -56,7 +56,7 @@ namespace AyaNova.Biz
if (log && ret != null)
{
//Log
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
}
return ret;
}
@@ -66,7 +66,7 @@ namespace AyaNova.Biz
//CREATE
//Called from route and also seeder
- internal Widget Create(Widget inObj)
+ internal async Task CreateAsync(Widget inObj)
{
Validate(inObj, null);
if (HasErrors)
@@ -81,57 +81,20 @@ namespace AyaNova.Biz
outObj.Tags = TagUtil.NormalizeTags(outObj.Tags);
outObj.CustomFields = JsonUtil.CompactJson(outObj.CustomFields);
-
- //Save to db
-
- //add syncronously and don't save but let the log save
- //THIS SAVED 1 SECOND OUT OF 22 for seeding 500 widgets
- ct.Widget.Add(outObj);
-
+ //Save to db
+ await ct.Widget.AddAsync(outObj);
+ await ct.SaveChangesAsync();
//Handle child and associated items:
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
-
-
- //This takes 16 seconds out of 22 when seeding 500 widgets
- SearchIndex(outObj, true);
-
-
- //This takes 2 seconds out of 22 when seeding 500 widgets
- TagUtil.ProcessUpdateTagsInRepository(ct, outObj.Tags, null);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
+ SearchIndex(outObj, true);
+ TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
return outObj;
}
}
- // //Internal version for seeding
- // internal Widget Create(AyContext TempContext, Widget inObj)
- // {
- // Validate(inObj, null);
- // if (HasErrors)
- // return null;
- // else
- // {
- // //do stuff with widget
- // Widget outObj = inObj;
-
- // //Test get serial id visible id number from generator
- // outObj.Serial = ServerBootConfig.WIDGET_SERIAL.GetNext();
- // outObj.Tags = TagUtil.NormalizeTags(outObj.Tags);
- // outObj.CustomFields = JsonUtil.CompactJson(outObj.CustomFields);
-
- // TempContext.Widget.Add(outObj);
- // TempContext.SaveChanges();
-
- // //Handle child and associated items:
- // EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), TempContext);
- // SearchIndex(outObj, true);
- // TagUtil.ProcessUpdateTagsInRepository(TempContext, outObj.Tags, null);
-
- // return outObj;
- // }
- // }
-
+
////////////////////////////////////////////////////////////////////////////////////////////////
//DUPLICATE
@@ -153,9 +116,9 @@ namespace AyaNova.Biz
await ct.SaveChangesAsync();
//Handle child and associated items:
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
SearchIndex(outObj, true);
- TagUtil.ProcessUpdateTagsInRepository(ct, outObj.Tags, null);
+ TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
return outObj;
}
@@ -188,9 +151,9 @@ namespace AyaNova.Biz
return false;
//Log event and save context
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
SearchIndex(dbObj, false);
- TagUtil.ProcessUpdateTagsInRepository(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
+ TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
return true;
}
@@ -218,10 +181,10 @@ namespace AyaNova.Biz
return false;
//Log event and save context
- EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
+ EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
SearchIndex(dbObj, false);
- TagUtil.ProcessUpdateTagsInRepository(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
+ TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
return true;
}
@@ -256,10 +219,10 @@ namespace AyaNova.Biz
ct.SaveChanges();
//Log event and save context
- EventLogProcessor.DeleteObject(UserId, BizType, dbObj.Id, dbObj.Name, ct);
+ EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct);
ct.SaveChanges();
Search.ProcessDeletedObjectKeywords(dbObj.Id, BizType);
- TagUtil.ProcessDeleteTagsInRepository(ct, dbObj.Tags);
+ TagUtil.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags);
return true;
}
diff --git a/server/AyaNova/util/Seeder.cs b/server/AyaNova/util/Seeder.cs
index 05236357..aa14c047 100644
--- a/server/AyaNova/util/Seeder.cs
+++ b/server/AyaNova/util/Seeder.cs
@@ -399,6 +399,8 @@ namespace AyaNova.Util
}
finally
{
+ //TODO: fully async: watch the job and don't turn the state back until the job is done?
+
log.LogInformation($"Seeder: setting server state back to {wasServerState.ToString()}");
apiServerState.SetState(wasServerState, wasReason);
}
@@ -570,22 +572,6 @@ namespace AyaNova.Util
//
public static void GenSeedWidget(ILogger log, int count)
{
- //COMMIT BEFORE GOING NON ASYNC AGAIN TO SEE IF MEDIUM 500 WIDGETS STILL TAKES SO LONG:
- //ASYNC CACHED STUFF 2020-01-23 15:58:31.1619|INFO|Seeder|500 Widgets seeded in 54890 ms
- //NON ASYNC ORIGINAL METHOD 2020-01-23 16:19:59.9131|INFO|Seeder|500 Widgets seeded in 51442 ms
- //NON ASYNC HERE BUT CALLING ASYNC CREATE IN WIDGET: 2020-01-23 16:23:58.9478|INFO|Seeder|500 Widgets seeded in 53362 ms
- //NOT CALLING SAVE ON WIDGET BUT DOING ALL OTHER CODE: 2020-01-23 16:25:45.0293|INFO|Seeder|500 Widgets seeded in 30 ms
- //So slowness is all in the save code, let's see whats what there...
- // first tried not caching teh widgetbiz object: 2020-01-23 16:28:58.0876|INFO|Seeder|500 Widgets seeded in 53577 ms
- //so that's pointless to cache it
- //ONE LAST THING IN HERE, trying *NOT* caching the db context and create each time: 2020-01-23 16:32:13.8966|INFO|Seeder|500 Widgets seeded in 22679 ms
- // - Holy shit, that's back to where it was a few days ago, so for some reason using the same context over and over is slowing shit down drastically
- // ripping that out now.
-
- //OK, making changes in CREATE code in widgetbiz
- //First removed extra save call and async db access shaved off a second
- //the commented out the Search indexer and it dropped from 22 seconds to 4.5!!!!
- //So the search indexing code is super fucking slow 2020-01-23 16:45:20.9518|INFO|Seeder|500 Widgets seeded in 4572 ms
var f = new Bogus.Faker();