This commit is contained in:
2020-01-27 17:54:51 +00:00
parent 2d0a8e711d
commit 629cc300e4
19 changed files with 106 additions and 151 deletions

View File

@@ -4,28 +4,23 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNTcxODU5OTU0IiwiZXhwIjoiMTU3MjQ
## IMMEDIATE ITEMS ## 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
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
UPDATE SPEC DOCS with new format and names etc or at least remove nonsense as necessary
UPDATE MANUAL API REGARDING LISTS
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 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 - 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") - 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 - 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 UPDATE SPEC DOCS with new format and names etc or at least remove nonsense as necessary
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 MANUAL API REGARDING LISTS
TODO: DataFilter how to distinguish between filtering on specific ID value or on value column 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? - Might need to add a filter on ID type of thing maybe?

View File

@@ -230,7 +230,7 @@ namespace AyaNova.Api.Controllers
}); });
//EVENT LOG //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 INDEXING
// Search.ProcessNewObjectKeywords( UserLocaleIdFromContext.Id(HttpContext.Items), v.Id, AyaType.FileAttachment, v.DisplayFileName, v.DisplayFileName, v.Notes, v.StoredFileName); // 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); FileUtil.deleteFileAttachment(dbObj, ct);
//Event log process delete //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 //Delete search index
Search.ProcessDeletedObjectKeywords(dbObj.Id, AyaType.FileAttachment); Search.ProcessDeletedObjectKeywords(dbObj.Id, AyaType.FileAttachment);
@@ -385,7 +385,7 @@ namespace AyaNova.Api.Controllers
} }
//Log //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); return PhysicalFile(filePath, mimetype, dbObj.DisplayFileName);

View File

@@ -121,7 +121,7 @@ namespace AyaNova.Api.Controllers
} }
var ret = AyaNova.Core.License.LicenseInfoAsJson; var ret = AyaNova.Core.License.LicenseInfoAsJson;
//Log //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)); return Ok(ApiOkResponse.Response(ret, true));
} }
@@ -169,7 +169,7 @@ namespace AyaNova.Api.Controllers
var ret = Core.License.RequestTrial(requestData.EmailAddress, requestData.RegisteredTo, log); var ret = Core.License.RequestTrial(requestData.EmailAddress, requestData.RegisteredTo, log);
//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)); return Ok(ApiOkResponse.Response(ret, true));
} }

View File

@@ -360,7 +360,7 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(biz.Errors)); return BadRequest(new ApiErrorResponse(biz.Errors));
} }
//Log //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(); await ct.SaveChangesAsync();
//Delete children / attached objects //Delete children / attached objects

View File

@@ -66,7 +66,7 @@ namespace AyaNova.Api.Controllers
string sResult = await GetTheMetrics("plain"); string sResult = await GetTheMetrics("plain");
//Log //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); return Content(sResult);
} }
@@ -94,7 +94,7 @@ namespace AyaNova.Api.Controllers
JObject json = JObject.Parse(sResult); JObject json = JObject.Parse(sResult);
//Log //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)); return Ok(ApiOkResponse.Response(json, true));
} }

View File

@@ -88,7 +88,7 @@ namespace AyaNova.Api.Controllers
serverState.SetState(desiredState, state.Reason); serverState.SetState(desiredState, state.Reason);
//Log //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(); return NoContent();
} }

View File

@@ -54,7 +54,7 @@ namespace AyaNova.Api.Controllers
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason)); 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 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));
} }

View File

@@ -104,7 +104,7 @@ namespace AyaNova.Api.Controllers
JobsBiz.AddJob(j, ct); JobsBiz.AddJob(j, ct);
//Log //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 return Accepted(new { JobId = j.GId });//202 accepted
} }

View File

@@ -65,7 +65,7 @@ namespace AyaNova.Biz
//Handle child and associated items: //Handle child and associated items:
//EVENT LOG //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 INDEXING
// Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name); // Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name);
@@ -95,7 +95,7 @@ namespace AyaNova.Biz
//Handle child and associated items: //Handle child and associated items:
//EVENT LOG //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 INDEXING
// Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name); // Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name);
@@ -116,7 +116,7 @@ namespace AyaNova.Biz
if (ret != null) if (ret != null)
{ {
//Log //Log
EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct); EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
} }
return ret; return ret;
} }
@@ -175,7 +175,7 @@ namespace AyaNova.Biz
return false; return false;
//Log modification and save context //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 //Update keywords
// Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.Name); // Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.Name);
@@ -201,7 +201,7 @@ namespace AyaNova.Biz
//Delete sibling objects //Delete sibling objects
//Event log process delete //Event log process delete
EventLogProcessor.DeleteObject(UserId, BizType, dbObj.Id, dbObj.Name, ct); EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct);
ct.SaveChanges(); ct.SaveChanges();
//Delete search index //Delete search index

View File

@@ -56,7 +56,7 @@ namespace AyaNova.Biz
if (log) if (log)
{ {
//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; return ret;
} }
@@ -85,7 +85,7 @@ namespace AyaNova.Biz
return false; return false;
//Log modification and save context //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; return true;
} }
@@ -100,7 +100,7 @@ namespace AyaNova.Biz
ct.DataListTemplate.Remove(dbObj); ct.DataListTemplate.Remove(dbObj);
ct.SaveChanges(); ct.SaveChanges();
//Event log process delete //Event log process delete
EventLogProcessor.DeleteObject(UserId, BizType, dbObj.Id, dbObj.DataListKey, ct); EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.DataListKey, ct);
ct.SaveChanges(); ct.SaveChanges();
return true; return true;
} }

View File

@@ -1,12 +1,7 @@
using System;
using System.Text;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyaNova.Models; using AyaNova.Models;
using AyaNova.Util;
namespace AyaNova.Biz namespace AyaNova.Biz
@@ -21,10 +16,10 @@ namespace AyaNova.Biz
/// <param name="newEvent"></param> /// <param name="newEvent"></param>
/// <param name="ct"></param> /// <param name="ct"></param>
/// <returns></returns> /// <returns></returns>
internal static void LogEventToDatabaseAndSaveEntireContext(Event newEvent, AyContext ct) internal static async Task LogEventToDatabaseAsync(Event newEvent, AyContext ct)
{ {
ct.Event.Add(newEvent); await ct.Event.AddAsync(newEvent);
ct.SaveChanges(); await ct.SaveChangesAsync();
} }
@@ -38,10 +33,11 @@ namespace AyaNova.Biz
/// <param name="ayId"></param> /// <param name="ayId"></param>
/// <param name="textra"></param> /// <param name="textra"></param>
/// <param name="ct"></param> /// <param name="ct"></param>
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}"); await ct.Database.ExecuteSqlInterpolatedAsync($"delete from aevent where aytype = {ayType} and ayid={ayId}");
ct.Event.Add(new Event(userId, ayId, ayType, AyaEvent.Deleted, textra)); await ct.Event.AddAsync(new Event(userId, ayId, ayType, AyaEvent.Deleted, textra));
await ct.SaveChangesAsync();
} }
/// <summary> /// <summary>
@@ -53,7 +49,7 @@ namespace AyaNova.Biz
//This is also an example of conditional where statements //This is also an example of conditional where statements
//Set up the query //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); q = q.Where(m => m.AyId == opt.AyId);

View File

@@ -71,7 +71,7 @@ namespace AyaNova.Biz
//Handle child and associated items: //Handle child and associated items:
//EVENT LOG //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 INDEXING
// Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name); // Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name);
@@ -141,7 +141,7 @@ namespace AyaNova.Biz
dbObj.Template = JsonUtil.CompactJson(dbObj.Template); dbObj.Template = JsonUtil.CompactJson(dbObj.Template);
//Log modification and save context //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 //Update keywords
// Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.Name); // Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.Name);

View File

@@ -349,9 +349,9 @@ namespace AyaNova.Biz
//handle EventLog entries for users now that we have the user's created //handle EventLog entries for users now that we have the user's created
//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 //MODIFIED
EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(Modifier, RavenId, ayaType, AyaEvent.Modified, Modified), ct); EventLogProcessor.LogEventToDatabaseAsync(new Event(Modifier, RavenId, ayaType, AyaEvent.Modified, Modified), ct);
} }

View File

@@ -77,7 +77,7 @@ namespace AyaNova.Biz
ct.Locale.Add(NewLocale); ct.Locale.Add(NewLocale);
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Log //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; return NewLocale;
} }
@@ -242,7 +242,7 @@ namespace AyaNova.Biz
ct.SaveChanges(); ct.SaveChanges();
//Log //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; return true;
} }
@@ -269,7 +269,7 @@ namespace AyaNova.Biz
ct.SaveChanges(); ct.SaveChanges();
//Log //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; return true;
} }
@@ -611,7 +611,7 @@ namespace AyaNova.Biz
ct.SaveChanges(); 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 //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; break;

View File

@@ -4,6 +4,7 @@ using AyaNova.Util;
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using AyaNova.Models; using AyaNova.Models;
using System.Threading.Tasks;
namespace AyaNova.Biz namespace AyaNova.Biz
{ {
@@ -42,7 +43,7 @@ namespace AyaNova.Biz
public static void ProcessDeleteTagsInRepository(AyContext ct, List<string> deleteTags) public static async Task ProcessDeleteTagsInRepositoryAsync(AyContext ct, List<string> deleteTags)
{ {
if (deleteTags.Count == 0) return; if (deleteTags.Count == 0) return;
foreach (string s in deleteTags) foreach (string s in deleteTags)
@@ -55,7 +56,7 @@ namespace AyaNova.Biz
do do
{ {
//START: Get tag word and concurrency token and count //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 not present, then nothing to do
if (ExistingTag != null) if (ExistingTag != null)
{ {
@@ -73,7 +74,7 @@ namespace AyaNova.Biz
try try
{ {
ct.SaveChanges(); await ct.SaveChangesAsync();
bDone = true; bDone = true;
} }
catch (Exception ex) when (ex is DbUpdateConcurrencyException)//allow for possible other types 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<string> newTags, List<string> originalTags = null) public static async Task ProcessUpdateTagsInRepositoryAsync(AyContext ct, List<string> newTags, List<string> originalTags = null)
{ {
//just in case no new tags are present which could mean a user removed all tags from a record so this //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 //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 do
{ {
//START: Get tag word and concurrency token and count //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 not present, then add it with a count of 0
if (ExistingTag == null) if (ExistingTag == null)
{ {
ct.Tag.Add(new Tag() { Name = s, RefCount = 1 }); await ct.Tag.AddAsync(new Tag() { Name = s, RefCount = 1 });
} }
else else
{ {
@@ -137,7 +138,7 @@ namespace AyaNova.Biz
} }
try try
{ {
ct.SaveChanges(); await ct.SaveChangesAsync();
bDone = true; bDone = true;
} }
catch (Exception ex) when (ex is DbUpdateConcurrencyException)//this allows for other types catch (Exception ex) when (ex is DbUpdateConcurrencyException)//this allows for other types
@@ -149,43 +150,57 @@ namespace AyaNova.Biz
} }
//DELETE TAGS //DELETE TAGS
ProcessDeleteTagsInRepository(ct, deleteTags); await ProcessDeleteTagsInRepositoryAsync(ct, deleteTags);
} }
//Pick list for driving pick list route //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 //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<string> PickListFiltered(AyContext ct, string q) public static async Task<List<string>> PickListFilteredAsync(AyContext ct, string q)
{ {
//This path is intended for internal use and accepts that there may not be a filter specified //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 //however the client will always require a filter to display a tag list for choosing from
if (string.IsNullOrWhiteSpace(q)) 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 else
{ {
q = NormalizeTag(q); 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 //Cloud list
public static List<TagCloudItem> CloudListFiltered(AyContext ct, string q) public static async Task<List<TagCloudItem>> CloudListFilteredAsync(AyContext ct, string q)
{ {
//This path is intended for internal use and accepts that there may not be a filter specified //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 //however the client will always require a filter to display a tag list for choosing from
if (string.IsNullOrWhiteSpace(q)) 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 else
{ {
q = NormalizeTag(q); q = NormalizeTag(q);
//TODO: Use the EF CORE TAKE method to restrict the results to a maximum limit //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) //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();
} }
} }

View File

@@ -81,13 +81,13 @@ namespace AyaNova.Biz
//Handle child and associated items //Handle child and associated items
//Log event //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 //SEARCH INDEXING
SearchIndex(inObj, true); SearchIndex(inObj, true);
//TAGS //TAGS
TagUtil.ProcessUpdateTagsInRepository(ct, inObj.Tags, null); TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, inObj.Tags, null);
return inObj; return inObj;
@@ -123,13 +123,13 @@ namespace AyaNova.Biz
//Handle child and associated items //Handle child and associated items
//Log event //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 //SEARCH INDEXING
SearchIndex(inObj, true); SearchIndex(inObj, true);
//TAGS //TAGS
TagUtil.ProcessUpdateTagsInRepository(TempContext, inObj.Tags, null); TagUtil.ProcessUpdateTagsInRepositoryAsync(TempContext, inObj.Tags, null);
return inObj; return inObj;
@@ -147,7 +147,7 @@ namespace AyaNova.Biz
if (ret != null) if (ret != null)
{ {
//Log //Log
EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct); EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
} }
return ret; return ret;
} }
@@ -302,11 +302,11 @@ namespace AyaNova.Biz
//Log modification and save context //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); SearchIndex(dbObj, false);
TagUtil.ProcessUpdateTagsInRepository(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags); TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
return true; return true;
} }
@@ -339,10 +339,10 @@ namespace AyaNova.Biz
return false; return false;
//Log modification and save context //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); SearchIndex(dbObj, false);
TagUtil.ProcessUpdateTagsInRepository(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags); TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
return true; return true;
} }
@@ -379,10 +379,10 @@ namespace AyaNova.Biz
ct.Database.ExecuteSqlInterpolated($"delete from auseroptions where userid={dbObj.Id}"); 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(); ct.SaveChanges();
Search.ProcessDeletedObjectKeywords(dbObj.Id, BizType); Search.ProcessDeletedObjectKeywords(dbObj.Id, BizType);
TagUtil.ProcessDeleteTagsInRepository(ct, dbObj.Tags); TagUtil.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags);
return true; return true;
} }

View File

@@ -59,7 +59,7 @@ namespace AyaNova.Biz
ct.SaveChanges(); ct.SaveChanges();
//Log //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; return true;
} }
@@ -79,7 +79,7 @@ namespace AyaNova.Biz
ct.SaveChanges(); ct.SaveChanges();
//Log //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; return true;
} }

View File

@@ -56,7 +56,7 @@ namespace AyaNova.Biz
if (log && ret != null) if (log && ret != null)
{ {
//Log //Log
EventLogProcessor.LogEventToDatabaseAndSaveEntireContext(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct); EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
} }
return ret; return ret;
} }
@@ -66,7 +66,7 @@ namespace AyaNova.Biz
//CREATE //CREATE
//Called from route and also seeder //Called from route and also seeder
internal Widget Create(Widget inObj) internal async Task<Widget> CreateAsync(Widget inObj)
{ {
Validate(inObj, null); Validate(inObj, null);
if (HasErrors) if (HasErrors)
@@ -81,56 +81,19 @@ namespace AyaNova.Biz
outObj.Tags = TagUtil.NormalizeTags(outObj.Tags); outObj.Tags = TagUtil.NormalizeTags(outObj.Tags);
outObj.CustomFields = JsonUtil.CompactJson(outObj.CustomFields); outObj.CustomFields = JsonUtil.CompactJson(outObj.CustomFields);
//Save to db //Save to db
await ct.Widget.AddAsync(outObj);
//add syncronously and don't save but let the log save await ct.SaveChangesAsync();
//THIS SAVED 1 SECOND OUT OF 22 for seeding 500 widgets
ct.Widget.Add(outObj);
//Handle child and associated items: //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);
//This takes 16 seconds out of 22 when seeding 500 widgets
SearchIndex(outObj, true); SearchIndex(outObj, true);
TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
//This takes 2 seconds out of 22 when seeding 500 widgets
TagUtil.ProcessUpdateTagsInRepository(ct, outObj.Tags, null);
return outObj; 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;
// }
// }
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
@@ -153,9 +116,9 @@ namespace AyaNova.Biz
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Handle child and associated items: //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); SearchIndex(outObj, true);
TagUtil.ProcessUpdateTagsInRepository(ct, outObj.Tags, null); TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
return outObj; return outObj;
} }
@@ -188,9 +151,9 @@ namespace AyaNova.Biz
return false; return false;
//Log event and save context //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); SearchIndex(dbObj, false);
TagUtil.ProcessUpdateTagsInRepository(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags); TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
return true; return true;
} }
@@ -218,10 +181,10 @@ namespace AyaNova.Biz
return false; return false;
//Log event and save context //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); SearchIndex(dbObj, false);
TagUtil.ProcessUpdateTagsInRepository(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags); TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
return true; return true;
} }
@@ -256,10 +219,10 @@ namespace AyaNova.Biz
ct.SaveChanges(); ct.SaveChanges();
//Log event and save context //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(); ct.SaveChanges();
Search.ProcessDeletedObjectKeywords(dbObj.Id, BizType); Search.ProcessDeletedObjectKeywords(dbObj.Id, BizType);
TagUtil.ProcessDeleteTagsInRepository(ct, dbObj.Tags); TagUtil.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags);
return true; return true;
} }

View File

@@ -399,6 +399,8 @@ namespace AyaNova.Util
} }
finally 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()}"); log.LogInformation($"Seeder: setting server state back to {wasServerState.ToString()}");
apiServerState.SetState(wasServerState, wasReason); apiServerState.SetState(wasServerState, wasReason);
} }
@@ -570,22 +572,6 @@ namespace AyaNova.Util
// //
public static void GenSeedWidget(ILogger log, int count) 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(); var f = new Bogus.Faker();