diff --git a/src/Server/Controllers/EntityController.cs b/src/Server/Controllers/EntityController.cs index 4e13c5c..12f9176 100644 --- a/src/Server/Controllers/EntityController.cs +++ b/src/Server/Controllers/EntityController.cs @@ -12,12 +12,16 @@ public class EntityController : ControllerBase private readonly ILogger _logger; private readonly IConfiguration _config; private SearchdomainManager _domainManager; + private readonly SearchdomainHelper _searchdomainHelper; + private readonly DatabaseHelper _databaseHelper; - public EntityController(ILogger logger, IConfiguration config, SearchdomainManager domainManager) + public EntityController(ILogger logger, IConfiguration config, SearchdomainManager domainManager, SearchdomainHelper searchdomainHelper, DatabaseHelper databaseHelper) { _logger = logger; _config = config; _domainManager = domainManager; + _searchdomainHelper = searchdomainHelper; + _databaseHelper = databaseHelper; } [HttpGet("Query")] @@ -46,7 +50,7 @@ public class EntityController : ControllerBase { try { - List? entities = SearchdomainHelper.EntitiesFromJSON( + List? entities = _searchdomainHelper.EntitiesFromJSON( [], _domainManager.embeddingCache, _domainManager.aIProvider, @@ -140,7 +144,7 @@ public class EntityController : ControllerBase _logger.LogError("Unable to delete the entity {entityName} in {searchdomain} - it was not found under the specified name", [entityName, searchdomain]); return Ok(new EntityDeleteResults() {Success = false}); } - DatabaseHelper.RemoveEntity([], _domainManager.helper, entityName, searchdomain); + _databaseHelper.RemoveEntity([], _domainManager.helper, entityName, searchdomain); return Ok(new EntityDeleteResults() {Success = true}); } } diff --git a/src/Server/Helper/DatabaseHelper.cs b/src/Server/Helper/DatabaseHelper.cs index 725345c..9ca2c08 100644 --- a/src/Server/Helper/DatabaseHelper.cs +++ b/src/Server/Helper/DatabaseHelper.cs @@ -3,8 +3,10 @@ using System.Text; namespace Server.Helper; -public static class DatabaseHelper +public class DatabaseHelper(ILogger logger) { + private readonly ILogger _logger = logger; + public static void DatabaseInsertEmbeddingBulk(SQLHelper helper, int id_datapoint, List<(string model, byte[] embedding)> data) { Dictionary parameters = []; @@ -80,7 +82,7 @@ public static class DatabaseHelper return helper.ExecuteSQLCommandGetInsertedID("INSERT INTO embedding (id_datapoint, model, embedding) VALUES (@id_datapoint, @model, @embedding)", parameters); } - public static int GetSearchdomainID(SQLHelper helper, string searchdomain) + public int GetSearchdomainID(SQLHelper helper, string searchdomain) { Dictionary parameters = new() { @@ -98,12 +100,13 @@ public static class DatabaseHelper } else { - throw new Exception($"Unable to retrieve searchdomain ID for {searchdomain}"); // TODO implement logging here; add logger via method injection + _logger.LogError("Unable to retrieve searchdomain ID for {searchdomain}", [searchdomain]); + throw new Exception($"Unable to retrieve searchdomain ID for {searchdomain}"); } } } - public static void RemoveEntity(List entityCache, SQLHelper helper, string name, string searchdomain) + public void RemoveEntity(List entityCache, SQLHelper helper, string name, string searchdomain) { Dictionary parameters = new() { @@ -118,7 +121,7 @@ public static class DatabaseHelper entityCache.RemoveAll(entity => entity.name == name); } - public static int RemoveAllEntities(SQLHelper helper, string searchdomain) + public int RemoveAllEntities(SQLHelper helper, string searchdomain) { Dictionary parameters = new() { @@ -131,7 +134,7 @@ public static class DatabaseHelper return helper.ExecuteSQLNonQuery("DELETE FROM entity WHERE entity.id_searchdomain = @searchdomain", parameters); } - public static bool HasEntity(SQLHelper helper, string name, string searchdomain) + public bool HasEntity(SQLHelper helper, string name, string searchdomain) { Dictionary parameters = new() { @@ -155,7 +158,7 @@ public static class DatabaseHelper } } - public static int? GetEntityID(SQLHelper helper, string name, string searchdomain) + public int? GetEntityID(SQLHelper helper, string name, string searchdomain) { Dictionary parameters = new() { diff --git a/src/Server/Helper/SearchdomainHelper.cs b/src/Server/Helper/SearchdomainHelper.cs index e34ac1e..7e2419c 100644 --- a/src/Server/Helper/SearchdomainHelper.cs +++ b/src/Server/Helper/SearchdomainHelper.cs @@ -7,8 +7,11 @@ using Shared.Models; namespace Server.Helper; -public static class SearchdomainHelper +public class SearchdomainHelper(ILogger logger, DatabaseHelper databaseHelper) { + private readonly ILogger _logger = logger; + private readonly DatabaseHelper _databaseHelper = databaseHelper; + public static byte[] BytesFromFloatArray(float[] floats) { var byteArray = new byte[floats.Length * 4]; @@ -41,7 +44,7 @@ public static class SearchdomainHelper return null; } - public static List? EntitiesFromJSON(List entityCache, Dictionary> embeddingCache, AIProvider aIProvider, SQLHelper helper, ILogger logger, string json) + public List? EntitiesFromJSON(List entityCache, Dictionary> embeddingCache, AIProvider aIProvider, SQLHelper helper, ILogger logger, string json) { List? jsonEntities = JsonSerializer.Deserialize>(json); if (jsonEntities is null) @@ -79,10 +82,10 @@ public static class SearchdomainHelper return [.. retVal]; } - public static Entity? EntityFromJSON(List entityCache, Dictionary> embeddingCache, AIProvider aIProvider, SQLHelper helper, ILogger logger, JSONEntity jsonEntity) //string json) + public Entity? EntityFromJSON(List entityCache, Dictionary> embeddingCache, AIProvider aIProvider, SQLHelper helper, ILogger logger, JSONEntity jsonEntity) //string json) { Dictionary> embeddingsLUT = []; // embeddingsLUT: hash -> model -> [embeddingValues * n] - int? preexistingEntityID = DatabaseHelper.GetEntityID(helper, jsonEntity.Name, jsonEntity.Searchdomain); + int? preexistingEntityID = _databaseHelper.GetEntityID(helper, jsonEntity.Name, jsonEntity.Searchdomain); if (preexistingEntityID is not null) { lock (helper.connection) // TODO change this to helper and do A/B tests (i.e. before/after) @@ -108,9 +111,9 @@ public static class SearchdomainHelper } reader.Close(); } - DatabaseHelper.RemoveEntity(entityCache, helper, jsonEntity.Name, jsonEntity.Searchdomain); // TODO only remove entity if there is actually a change somewhere. Perhaps create 3 datapoint lists to operate with: 1. delete, 2. update, 3. create + _databaseHelper.RemoveEntity(entityCache, helper, jsonEntity.Name, jsonEntity.Searchdomain); // TODO only remove entity if there is actually a change somewhere. Perhaps create 3 datapoint lists to operate with: 1. delete, 2. update, 3. create } - int id_entity = DatabaseHelper.DatabaseInsertEntity(helper, jsonEntity.Name, jsonEntity.Probmethod, DatabaseHelper.GetSearchdomainID(helper, jsonEntity.Searchdomain)); + int id_entity = DatabaseHelper.DatabaseInsertEntity(helper, jsonEntity.Name, jsonEntity.Probmethod, _databaseHelper.GetSearchdomainID(helper, jsonEntity.Searchdomain)); foreach (KeyValuePair attribute in jsonEntity.Attributes) { DatabaseHelper.DatabaseInsertAttribute(helper, attribute.Key, attribute.Value, id_entity); // TODO implement bulk insert to reduce number of queries diff --git a/src/Server/Program.cs b/src/Server/Program.cs index 98cf3fd..ceef92e 100644 --- a/src/Server/Program.cs +++ b/src/Server/Program.cs @@ -3,6 +3,7 @@ using ElmahCore.Mvc; using Serilog; using Server; using Server.HealthChecks; +using Server.Helper; var builder = WebApplication.CreateBuilder(args); @@ -16,6 +17,8 @@ Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) .CreateLogger(); builder.Logging.AddSerilog(); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddHealthChecks() diff --git a/src/Server/SearchdomainManager.cs b/src/Server/SearchdomainManager.cs index 7e7baf9..d5670c0 100644 --- a/src/Server/SearchdomainManager.cs +++ b/src/Server/SearchdomainManager.cs @@ -11,16 +11,18 @@ public class SearchdomainManager private readonly ILogger _logger; private readonly IConfiguration _config; public readonly AIProvider aIProvider; + private readonly DatabaseHelper _databaseHelper; private readonly string connectionString; private MySqlConnection connection; public SQLHelper helper; public Dictionary> embeddingCache; - public SearchdomainManager(ILogger logger, IConfiguration config, AIProvider aIProvider) + public SearchdomainManager(ILogger logger, IConfiguration config, AIProvider aIProvider, DatabaseHelper databaseHelper) { _logger = logger; _config = config; this.aIProvider = aIProvider; + _databaseHelper = databaseHelper; embeddingCache = []; connectionString = _config.GetSection("Embeddingsearch").GetConnectionString("SQL") ?? ""; connection = new MySqlConnection(connectionString); @@ -96,8 +98,7 @@ public class SearchdomainManager public int DeleteSearchdomain(string searchdomain) { - Searchdomain searchdomain_ = GetSearchdomain(searchdomain); - int counter = DatabaseHelper.RemoveAllEntities(helper, searchdomain); + int counter = _databaseHelper.RemoveAllEntities(helper, searchdomain); _logger.LogDebug($"Number of entities deleted as part of deleting the searchdomain \"{searchdomain}\": {counter}"); helper.ExecuteSQLNonQuery("DELETE FROM searchdomain WHERE name = @name", new() {{"name", searchdomain}}); searchdomains.Remove(searchdomain);