95 lines
3.3 KiB
C#
95 lines
3.3 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using Npgsql;
|
|
using StellaOps.AdvisoryAI.KnowledgeSearch;
|
|
|
|
namespace StellaOps.AdvisoryAI.UnifiedSearch;
|
|
|
|
internal sealed class EntityAliasService : IEntityAliasService
|
|
{
|
|
private readonly KnowledgeSearchOptions _options;
|
|
private readonly ILogger<EntityAliasService> _logger;
|
|
private readonly Lazy<NpgsqlDataSource?> _dataSource;
|
|
|
|
public EntityAliasService(
|
|
IOptions<KnowledgeSearchOptions> options,
|
|
ILogger<EntityAliasService> logger)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(options);
|
|
_options = options.Value ?? new KnowledgeSearchOptions();
|
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
_dataSource = new Lazy<NpgsqlDataSource?>(() =>
|
|
{
|
|
if (!_options.Enabled || string.IsNullOrWhiteSpace(_options.ConnectionString))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new NpgsqlDataSourceBuilder(_options.ConnectionString).Build();
|
|
}, isThreadSafe: true);
|
|
}
|
|
|
|
public async Task<IReadOnlyList<(string EntityKey, string EntityType)>> ResolveAliasesAsync(
|
|
string alias,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(alias) || _dataSource.Value is null)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
const string sql = """
|
|
SELECT entity_key, entity_type
|
|
FROM advisoryai.entity_alias
|
|
WHERE lower(alias) = lower(@alias)
|
|
ORDER BY entity_key, entity_type;
|
|
""";
|
|
|
|
await using var command = _dataSource.Value.CreateCommand(sql);
|
|
command.CommandTimeout = 10;
|
|
command.Parameters.AddWithValue("alias", alias.Trim());
|
|
|
|
var results = new List<(string, string)>();
|
|
await using var reader = await command.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false);
|
|
while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
|
|
{
|
|
results.Add((reader.GetString(0), reader.GetString(1)));
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
public async Task RegisterAliasAsync(
|
|
string entityKey,
|
|
string entityType,
|
|
string alias,
|
|
string source,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(entityKey) ||
|
|
string.IsNullOrWhiteSpace(entityType) ||
|
|
string.IsNullOrWhiteSpace(alias) ||
|
|
_dataSource.Value is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const string sql = """
|
|
INSERT INTO advisoryai.entity_alias (alias, entity_key, entity_type, source, created_at)
|
|
VALUES (@alias, @entity_key, @entity_type, @source, NOW())
|
|
ON CONFLICT (alias, entity_key) DO UPDATE SET
|
|
entity_type = EXCLUDED.entity_type,
|
|
source = EXCLUDED.source;
|
|
""";
|
|
|
|
await using var command = _dataSource.Value.CreateCommand(sql);
|
|
command.CommandTimeout = 10;
|
|
command.Parameters.AddWithValue("alias", alias.Trim());
|
|
command.Parameters.AddWithValue("entity_key", entityKey.Trim());
|
|
command.Parameters.AddWithValue("entity_type", entityType.Trim());
|
|
command.Parameters.AddWithValue("source", source.Trim());
|
|
|
|
await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
|
|
}
|
|
}
|