This commit is contained in:
2020-01-27 23:03:01 +00:00
parent 5ee6c90586
commit 021b7e4b7b
6 changed files with 67 additions and 77 deletions

View File

@@ -21,6 +21,7 @@ TODO: REFACTOR GetNoLogAsync function is used in many places redundantly when th
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: Seeder create widget is creating a new widgetbiz each loop iteration but create user is not, try both ways and performance test
TODO: License.cs using httpclient directly albeit trying to do it right`
- Change to use httpclientfactory injected service:

View File

@@ -423,12 +423,12 @@ namespace AyaNova
{
_newLog.LogWarning("BOOT: AYANOVA_PERMANENTLY_ERASE_DATABASE is true, dropping and recreating database");
Util.DbUtil.DropAndRecreateDbAsync(_newLog);
AySchema.CheckAndUpdate(dbContext, _newLog);
AySchema.CheckAndUpdateAsync(dbContext, _newLog);
}
//Check schema
_newLog.LogDebug("BOOT: db schema check");
AySchema.CheckAndUpdate(dbContext, _newLog);
AySchema.CheckAndUpdateAsync(dbContext, _newLog);
//Check database integrity
_newLog.LogDebug("BOOT: db integrity check");

View File

@@ -1,5 +1,5 @@
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using AyaNova.Models;
@@ -52,7 +52,7 @@ namespace AyaNova.Util
//check and update schema
public static void CheckAndUpdate(AyContext context, ILogger logger)
public static async Task CheckAndUpdateAsync(AyContext context, ILogger logger)
{
ct = context;
log = logger;
@@ -63,14 +63,14 @@ namespace AyaNova.Util
using (var command = ct.Database.GetDbConnection().CreateCommand())
{
command.CommandText = "SELECT * FROM information_schema.tables WHERE table_name = 'aschemaversion'";
ct.Database.OpenConnection();
using (var result = command.ExecuteReader())
await ct.Database.OpenConnectionAsync();
using (var result = await command.ExecuteReaderAsync())
{
if (result.HasRows)
{
aySchemaVersionExists = true;
}
ct.Database.CloseConnection();
await ct.Database.CloseConnectionAsync();
}
}
@@ -82,14 +82,14 @@ namespace AyaNova.Util
//nope, no schema table, add it now and set to v1
using (var cm = ct.Database.GetDbConnection().CreateCommand())
{
ct.Database.OpenConnection();
await ct.Database.OpenConnectionAsync();
cm.CommandText = "CREATE TABLE aschemaversion (schema INTEGER NOT NULL);";
cm.ExecuteNonQuery();
await cm.ExecuteNonQueryAsync();
cm.CommandText = "insert into aschemaversion (schema) values (1);";
cm.ExecuteNonQuery();
await cm.ExecuteNonQueryAsync();
ct.Database.CloseConnection();
await ct.Database.CloseConnectionAsync();
startingSchema = 1;
currentSchema = 1;
}
@@ -101,19 +101,19 @@ namespace AyaNova.Util
{
log.LogDebug("Fetching current schema version");
cm.CommandText = "SELECT schema FROM aschemaversion;";
ct.Database.OpenConnection();
using (var result = cm.ExecuteReader())
await ct.Database.OpenConnectionAsync();
using (var result = await cm.ExecuteReaderAsync())
{
if (result.HasRows)
{
result.Read();
await result.ReadAsync();
currentSchema = startingSchema = result.GetInt32(0);
ct.Database.CloseConnection();
await ct.Database.CloseConnectionAsync();
log.LogDebug("AyaNova schema version is " + currentSchema.ToString());
}
else
{
ct.Database.CloseConnection();
await ct.Database.CloseConnectionAsync();
throw new System.Exception("AyaNova->AySchema->CheckAndUpdate: Error reading schema version");
}
}
@@ -139,51 +139,51 @@ namespace AyaNova.Util
LogUpdateMessage(log);
//create aevent biz event log table
exec("CREATE TABLE aevent (id BIGSERIAL PRIMARY KEY, created timestamp not null, userid bigint not null," +
await ExecQueryAsync("CREATE TABLE aevent (id BIGSERIAL PRIMARY KEY, created timestamp not null, userid bigint not null," +
"ayid bigint not null, aytype integer not null, ayevent integer not null, textra varchar(255))");
//SEARCH TABLES
exec("CREATE TABLE asearchdictionary (id BIGSERIAL PRIMARY KEY, word varchar(255) not null)");
await ExecQueryAsync("CREATE TABLE asearchdictionary (id BIGSERIAL PRIMARY KEY, word varchar(255) not null)");
//Search dictionary words must be unique
exec("CREATE UNIQUE INDEX asearchdictionary_word_idx ON asearchdictionary (word);");
await ExecQueryAsync("CREATE UNIQUE INDEX asearchdictionary_word_idx ON asearchdictionary (word);");
exec("CREATE TABLE asearchkey (id BIGSERIAL PRIMARY KEY, wordid bigint not null REFERENCES asearchdictionary (id), objectid bigint not null, objecttype integer not null, inname bool not null)");
await ExecQueryAsync("CREATE TABLE asearchkey (id BIGSERIAL PRIMARY KEY, wordid bigint not null REFERENCES asearchdictionary (id), objectid bigint not null, objecttype integer not null, inname bool not null)");
//create locale text tables
exec("CREATE TABLE alocale (id BIGSERIAL PRIMARY KEY, name varchar(255) not null, stock bool, cjkindex bool default false)");
await ExecQueryAsync("CREATE TABLE alocale (id BIGSERIAL PRIMARY KEY, name varchar(255) not null, stock bool, cjkindex bool default false)");
//LOOKAT: I don't think this is doing anything:
//exec("CREATE UNIQUE INDEX alocale_name_idx ON alocale (name)");
exec("CREATE TABLE alocaleitem (id BIGSERIAL PRIMARY KEY, localeid bigint not null REFERENCES alocale (id), key text not null, display text not null)");
await ExecQueryAsync("CREATE TABLE alocaleitem (id BIGSERIAL PRIMARY KEY, localeid bigint not null REFERENCES alocale (id), key text not null, display text not null)");
//LOOKAT: this is for what exactly??
// exec("CREATE INDEX alocaleitem_localeid_key_idx ON alocaleitem (localeid,key)");
//This seems more appropriate
exec("CREATE INDEX alocaleitem_localeid_key_display_idx ON alocaleitem (localeid,key, display)");
await ExecQueryAsync("CREATE INDEX alocaleitem_localeid_key_display_idx ON alocaleitem (localeid,key, display)");
//Load the default LOCALES
AyaNova.Biz.PrimeData.PrimeLocales();
await AyaNova.Biz.PrimeData.PrimeLocales();
//Add user table
exec("CREATE TABLE auser (id BIGSERIAL PRIMARY KEY, active bool not null, name varchar(255) not null, " +
await ExecQueryAsync("CREATE TABLE auser (id BIGSERIAL PRIMARY KEY, active bool not null, name varchar(255) not null, " +
"login text not null, password text not null, salt text not null, roles integer not null, localeid bigint not null REFERENCES alocale (id), " +
"dlkey text, dlkeyexpire timestamp, usertype integer not null, employeenumber varchar(255), notes text, customerid bigint, " +
"headofficeid bigint, subvendorid bigint, customfields text, tags varchar(255) ARRAY)");
//Index for name fetching
exec("CREATE UNIQUE INDEX auser_name_id_idx ON auser (id, name);");
await ExecQueryAsync("CREATE UNIQUE INDEX auser_name_id_idx ON auser (id, name);");
//Add user options table
exec("CREATE TABLE auseroptions (id BIGSERIAL PRIMARY KEY, " +
await ExecQueryAsync("CREATE TABLE auseroptions (id BIGSERIAL PRIMARY KEY, " +
"userid bigint not null, timezoneoffset decimal(19,5) not null default 0, emailaddress text, uicolor int not null default 0)");
//Prime the db with the default MANAGER account
AyaNova.Biz.PrimeData.PrimeManagerAccount(ct);
await AyaNova.Biz.PrimeData.PrimeManagerAccount(ct);
setSchemaLevel(++currentSchema);
await SetSchemaLevelAsync(++currentSchema);
}
@@ -194,9 +194,9 @@ namespace AyaNova.Util
LogUpdateMessage(log);
//Add user table
exec("CREATE TABLE alicense (id BIGSERIAL PRIMARY KEY, dbid uuid, key text not null)");
await ExecQueryAsync("CREATE TABLE alicense (id BIGSERIAL PRIMARY KEY, dbid uuid, key text not null)");
setSchemaLevel(++currentSchema);
await SetSchemaLevelAsync(++currentSchema);
}
@@ -208,7 +208,7 @@ namespace AyaNova.Util
//Add widget table
//id, text, longtext, boolean, currency,
exec("CREATE TABLE awidget (id BIGSERIAL PRIMARY KEY, name varchar(255) not null, serial bigint not null," +
await ExecQueryAsync("CREATE TABLE awidget (id BIGSERIAL PRIMARY KEY, name varchar(255) not null, serial bigint not null," +
"startdate timestamp, enddate timestamp, dollaramount decimal(19,5), active bool, roles int4, count integer," +
"notes text, userid bigint null, customfields text, tags varchar(255) ARRAY)");
@@ -217,12 +217,12 @@ namespace AyaNova.Util
//Compound index for name fetching
exec("CREATE UNIQUE INDEX awidget_name_id_idx ON awidget (id, name);");
await ExecQueryAsync("CREATE UNIQUE INDEX awidget_name_id_idx ON awidget (id, name);");
//Index for tags
exec("CREATE INDEX awidget_tags ON AWIDGET using GIN(tags)");
await ExecQueryAsync("CREATE INDEX awidget_tags ON AWIDGET using GIN(tags)");
setSchemaLevel(++currentSchema);
await SetSchemaLevelAsync(++currentSchema);
}
@@ -232,15 +232,15 @@ namespace AyaNova.Util
{
LogUpdateMessage(log);
exec("CREATE TABLE afileattachment (id BIGSERIAL PRIMARY KEY, " +
await ExecQueryAsync("CREATE TABLE afileattachment (id BIGSERIAL PRIMARY KEY, " +
"attachtoobjectid bigint not null, attachtoobjecttype integer not null, " +
"storedfilename text not null, displayfilename text not null, contenttype text, notes text)");
//index required for ops that need to check if file already in db (delete, count refs etc)
//LOOKAT: isn't this useless without the ID as well or is that not fetched?
exec("CREATE INDEX afileattachment_storedfilename_idx ON afileattachment (storedfilename);");
await ExecQueryAsync("CREATE INDEX afileattachment_storedfilename_idx ON afileattachment (storedfilename);");
setSchemaLevel(++currentSchema);
await SetSchemaLevelAsync(++currentSchema);
}
@@ -252,11 +252,11 @@ namespace AyaNova.Util
{
LogUpdateMessage(log);
exec("CREATE TABLE aopsjob (gid uuid PRIMARY KEY, name text not null, created timestamp not null, exclusive bool not null, " +
await ExecQueryAsync("CREATE TABLE aopsjob (gid uuid PRIMARY KEY, name text not null, created timestamp not null, exclusive bool not null, " +
"startafter timestamp not null, jobtype integer not null, objectid bigint null, objecttype integer null, jobstatus integer not null, jobinfo text null)");
exec("CREATE TABLE aopsjoblog (gid uuid PRIMARY KEY, jobid uuid not null REFERENCES aopsjob (gid), created timestamp not null, statustext text not null)");
await ExecQueryAsync("CREATE TABLE aopsjoblog (gid uuid PRIMARY KEY, jobid uuid not null REFERENCES aopsjob (gid), created timestamp not null, statustext text not null)");
setSchemaLevel(++currentSchema);
await SetSchemaLevelAsync(++currentSchema);
}
@@ -266,11 +266,11 @@ namespace AyaNova.Util
{
LogUpdateMessage(log);
exec("CREATE TABLE adatalistfilter (id BIGSERIAL PRIMARY KEY, userId bigint not null, name varchar(255) not null, public bool not null," +
await ExecQueryAsync("CREATE TABLE adatalistfilter (id BIGSERIAL PRIMARY KEY, userId bigint not null, name varchar(255) not null, public bool not null," +
"listkey varchar(255) not null, filter text, sort text, UNIQUE(name))");
exec("CREATE TABLE adatalisttemplate (id BIGSERIAL PRIMARY KEY, datalistkey text not null, template text, UNIQUE(datalistkey))");
setSchemaLevel(++currentSchema);
await ExecQueryAsync("CREATE TABLE adatalisttemplate (id BIGSERIAL PRIMARY KEY, datalistkey text not null, template text, UNIQUE(datalistkey))");
await SetSchemaLevelAsync(++currentSchema);
}
@@ -279,8 +279,8 @@ namespace AyaNova.Util
if (currentSchema < 8)
{
LogUpdateMessage(log);
exec("CREATE TABLE atag (id BIGSERIAL PRIMARY KEY, name varchar(255) not null, refcount bigint not null, UNIQUE(name))");
setSchemaLevel(++currentSchema);
await ExecQueryAsync("CREATE TABLE atag (id BIGSERIAL PRIMARY KEY, name varchar(255) not null, refcount bigint not null, UNIQUE(name))");
await SetSchemaLevelAsync(++currentSchema);
}
@@ -291,9 +291,9 @@ namespace AyaNova.Util
{
LogUpdateMessage(log);
exec("CREATE TABLE aformcustom (id BIGSERIAL PRIMARY KEY, " +
await ExecQueryAsync("CREATE TABLE aformcustom (id BIGSERIAL PRIMARY KEY, " +
"formkey varchar(255) not null, template text, UNIQUE(formkey))");
setSchemaLevel(++currentSchema);
await SetSchemaLevelAsync(++currentSchema);
}
@@ -329,20 +329,20 @@ namespace AyaNova.Util
private static void setSchemaLevel(int nCurrentSchema)
private static async Task SetSchemaLevelAsync(int nCurrentSchema)
{
exec("UPDATE aschemaversion SET schema=" + nCurrentSchema.ToString());
await ExecQueryAsync("UPDATE aschemaversion SET schema=" + nCurrentSchema.ToString());
}
//execute command query
private static void exec(string q)
private static async Task ExecQueryAsync(string q)
{
using (var cm = ct.Database.GetDbConnection().CreateCommand())
{
ct.Database.OpenConnection();
await ct.Database.OpenConnectionAsync();
cm.CommandText = q;
cm.ExecuteNonQuery();
ct.Database.CloseConnection();
await cm.ExecuteNonQueryAsync();
await ct.Database.CloseConnectionAsync();
}
}

View File

@@ -1,21 +1,9 @@
using System;
using Microsoft.Extensions.Logging;
using AyaNova.Models;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.JsonPatch;
using EnumsNET;
using AyaNova.Util;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Models;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
namespace AyaNova.Util
{

View File

@@ -519,7 +519,7 @@ namespace AyaNova.Core
}
//Can't install a trial into a non-empty db
if (ParsedNewKey.TrialLicense && ! DbUtil.DBIsEmptyAsync(ct, log))
if (ParsedNewKey.TrialLicense && ! await DbUtil.DBIsEmptyAsync(ct, log))
{
throw new ApplicationException("E1020 - Can't install a trial key into a non empty AyaNova database. Erase the database first.");
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using AyaNova.Models;
using AyaNova.Biz;
@@ -165,7 +166,7 @@ namespace AyaNova.Util
watch = new Stopwatch();
watch.Start();
//await GenSeedWidgetAsync(log, 100);
GenSeedWidget(log, 100);
GenSeedWidgetAsync(log, 100);
//PERF
watch.Stop();
LogStatus(JobId, LogJob, log, $"100 Widgets seeded in {watch.ElapsedMilliseconds} ms");
@@ -227,7 +228,7 @@ namespace AyaNova.Util
watch.Start();
//await GenSeedWidgetAsync(log, 500);
GenSeedWidget(log, 500);
GenSeedWidgetAsync(log, 500);
//PERF
watch.Stop();
LogStatus(JobId, LogJob, log, $"500 Widgets seeded in {watch.ElapsedMilliseconds} ms");
@@ -303,7 +304,7 @@ namespace AyaNova.Util
watch = new Stopwatch();
watch.Start();
//await GenSeedWidgetAsync(log, 5000);
GenSeedWidget(log, 5000);
GenSeedWidgetAsync(log, 5000);
//PERF
watch.Stop();
@@ -380,7 +381,7 @@ namespace AyaNova.Util
watch = new Stopwatch();
watch.Start();
//await GenSeedWidgetAsync(log, 20000);
GenSeedWidget(log, 20000);
GenSeedWidgetAsync(log, 20000);
watch.Stop();
LogStatus(JobId, LogJob, log, $"20k Widgets seeded in {watch.ElapsedMilliseconds} ms");
#endregion genhuge
@@ -509,15 +510,15 @@ namespace AyaNova.Util
public static void GenSeedUser(ILogger log, int count, AuthorizationRoles roles, UserType userType, decimal timeZoneOffset,
public static async Task GenSeedUser(ILogger log, int count, AuthorizationRoles roles, UserType userType, decimal timeZoneOffset,
bool active = true, string login = null, string password = null, long localeId = 0)
{
if (localeId == 0)
localeId = ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID;
using (var cct = ServiceProviderProvider.DBContext)
using (var ct = ServiceProviderProvider.DBContext)
{
UserBiz Biz = UserBiz.GetBizInternal(cct);
UserBiz Biz = UserBiz.GetBizInternal(ct);
//allow creation of not entirely ready users (missing client id or subcontractor vendor id etc)
Biz.SeedOrImportRelaxedRulesMode = true;
@@ -555,7 +556,7 @@ namespace AyaNova.Util
u.UserOptions.EmailAddress = p.Email.Replace("gmail.com", "helloayanova.com").Replace("hotmail.com", "helloayanova.com").Replace("yahoo.com", "helloayanova.com");
u.UserOptions.TimeZoneOffset = timeZoneOffset;
var NewObject = Biz.Create(cct, u);
var NewObject = await Biz.CreateAsync(u);
if (NewObject == null)
{
log.LogError($"Seeder::GenSeedUser error creating user {u.Name}\r\n" + Biz.GetErrorsAsString());
@@ -570,7 +571,7 @@ namespace AyaNova.Util
//////////////////////////////////////////////////////
//Seed widget for testing
//
public static void GenSeedWidget(ILogger log, int count)
public static async Task GenSeedWidgetAsync(ILogger log, int count)
{
var f = new Bogus.Faker();
@@ -610,7 +611,7 @@ namespace AyaNova.Util
//var NewObject = Cached_WidgetBiz.CreateAsync(o).Result;
//test without cached widgetbiz
WidgetBiz biz = WidgetBiz.GetBizInternal(ServiceProviderProvider.DBContext);
var NewObject = biz.Create(o);
var NewObject = await biz.CreateAsync(o);
if (NewObject == null)
{
log.LogError($"Seeder::GenSeedWidget error creating widget {o.Name}\r\n" + biz.GetErrorsAsString());