feat(Sentiment): update sentiment service

This commit is contained in:
2026-08-09 21:01:42 +02:00
parent aff831cf58
commit 05d55a324c
15 changed files with 1772 additions and 0 deletions
@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FinlyticSentiment.Database;
using FinlyticSentiment.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace FinlyticSentiment.Services;
/// <summary>
/// Interface for reading and persisting FinlyticSentiment runtime configuration settings in PostgreSQL.
/// </summary>
public interface ISettingsDbService
{
/// <summary>
/// Retrieves current sentiment settings from PostgreSQL database, seeding defaults if empty.
/// </summary>
Task<SentimentSettingsEntity> GetSettingsAsync();
/// <summary>
/// Persists updated settings entity to PostgreSQL.
/// </summary>
Task<SentimentSettingsEntity> SaveSettingsAsync(SentimentSettingsEntity settings);
/// <summary>
/// Updates settings from a key-value dictionary received via Admin Panel MQTT events.
/// </summary>
Task UpdateSettingsFromDictionaryAsync(Dictionary<string, string> dictionary);
}
/// <summary>
/// EF Core PostgreSQL implementation of <see cref="ISettingsDbService"/>.
/// </summary>
public class SettingsDbService : ISettingsDbService
{
private readonly SentimentDbContext _context;
private readonly ILogger<SettingsDbService> _logger;
/// <summary>
/// Initializes a new instance of the <see cref="SettingsDbService"/> class.
/// </summary>
public SettingsDbService(SentimentDbContext context, ILogger<SettingsDbService> logger)
{
_context = context;
_logger = logger;
}
/// <summary>
/// Retrieves current sentiment settings from PostgreSQL database.
/// </summary>
public async Task<SentimentSettingsEntity> GetSettingsAsync()
{
var settings = await _context.Settings.AsNoTracking().FirstOrDefaultAsync();
if (settings == null)
{
settings = new SentimentSettingsEntity { Id = Guid.NewGuid() };
_context.Settings.Add(settings);
await _context.SaveChangesAsync();
_context.ChangeTracker.Clear();
}
return settings;
}
/// <summary>
/// Persists updated settings entity to PostgreSQL.
/// </summary>
public async Task<SentimentSettingsEntity> SaveSettingsAsync(SentimentSettingsEntity settings)
{
var existing = await _context.Settings.FirstOrDefaultAsync();
if (existing == null)
{
if (settings.Id == Guid.Empty) settings.Id = Guid.NewGuid();
_context.Settings.Add(settings);
}
else
{
existing.MinConfidenceScore = settings.MinConfidenceScore;
existing.MaxBatchSize = settings.MaxBatchSize;
existing.SweepIntervalMinutes = settings.SweepIntervalMinutes;
existing.GermanWebhookUrl = settings.GermanWebhookUrl;
existing.EnglishWebhookUrl = settings.EnglishWebhookUrl;
existing.UpdatedAt = settings.UpdatedAt;
_context.Settings.Update(existing);
}
await _context.SaveChangesAsync();
return settings;
}
/// <summary>
/// Updates settings from a key-value dictionary.
/// </summary>
public async Task UpdateSettingsFromDictionaryAsync(Dictionary<string, string> dictionary)
{
var settings = await GetSettingsAsync();
foreach (var (key, value) in dictionary)
{
if (string.Equals(key, "MinConfidenceScore", StringComparison.OrdinalIgnoreCase) && double.TryParse(value, out var mcs))
settings.MinConfidenceScore = mcs;
else if (string.Equals(key, "MaxBatchSize", StringComparison.OrdinalIgnoreCase) && int.TryParse(value, out var mbs))
settings.MaxBatchSize = mbs;
else if (string.Equals(key, "SweepIntervalMinutes", StringComparison.OrdinalIgnoreCase) && int.TryParse(value, out var sim))
settings.SweepIntervalMinutes = sim;
else if (string.Equals(key, "GermanWebhookUrl", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(value))
settings.GermanWebhookUrl = value.Trim();
else if (string.Equals(key, "EnglishWebhookUrl", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(value))
settings.EnglishWebhookUrl = value.Trim();
}
settings.UpdatedAt = DateTime.UtcNow;
await SaveSettingsAsync(settings);
_logger.LogInformation("[{Channel}] Successfully updated {Count} sentiment settings in PostgreSQL database.", "SentimentChannel", dictionary.Count);
}
}