Added checks for non-user foreign keys in stores. Load/Saving stores' order is now based on table dependencies. Added ability to use chat message when using redemption.

This commit is contained in:
Tom
2025-01-28 19:12:14 +00:00
parent 6d955f245a
commit 3e717522c2
18 changed files with 146 additions and 102 deletions

View File

@@ -1,8 +1,8 @@
using System.Collections.Concurrent;
using HermesSocketLibrary.db;
using HermesSocketLibrary.Requests.Messages;
using HermesSocketServer.Models;
using HermesSocketServer.Store;
using HermesSocketServer.Validators;
namespace HermesSocketServer.Services
{
@@ -10,15 +10,17 @@ namespace HermesSocketServer.Services
{
private readonly IStore<string, User> _users;
private readonly Database _database;
private readonly IStore<string, TTSVoice> _voices;
private readonly ServerConfiguration _configuration;
private readonly Serilog.ILogger _logger;
private readonly IDictionary<string, Channel> _channels;
private readonly object _lock;
public ChannelManager(IStore<string, User> users, Database database, ServerConfiguration configuration, Serilog.ILogger logger)
public ChannelManager(IStore<string, User> users, Database database, IStore<string, TTSVoice> voices, ServerConfiguration configuration, Serilog.ILogger logger)
{
_users = users;
_database = database;
_voices = voices;
_configuration = configuration;
_logger = logger;
_channels = new ConcurrentDictionary<string, Channel>();
@@ -26,68 +28,74 @@ namespace HermesSocketServer.Services
}
public Task<Channel?> Add(string userId)
public async Task<Channel?> Add(string userId)
{
var user = _users.Get(userId);
if (user == null)
return Task.FromResult<Channel?>(null);
return null;
lock (_lock)
return await Task.Run(() =>
{
if (_channels.ContainsKey(userId))
return Task.FromResult<Channel?>(null);
var actionTable = _configuration.Database.Tables["Action"];
var chatterTable = _configuration.Database.Tables["Chatter"];
var connectionTable = _configuration.Database.Tables["Connection"];
//var chatterGroupTable = _configuration.Database.Tables["ChatterGroup"];
var groupTable = _configuration.Database.Tables["Group"];
var groupPermissionTable = _configuration.Database.Tables["GroupPermission"];
var policyTable = _configuration.Database.Tables["Policy"];
var redemptionTable = _configuration.Database.Tables["Redemption"];
var ttsFilterTable = _configuration.Database.Tables["TtsFilter"];
var ttsVoiceStateTable = _configuration.Database.Tables["VoiceState"];
var chatters = new ChatterStore(userId, chatterTable, _database, _logger);
var connections = new ConnectionStore(userId, connectionTable, _database, _logger);
var groups = new GroupStore(userId, groupTable, _database, _configuration, _logger);
var groupPermissions = new GroupPermissionStore(userId, groupPermissionTable, _database, _logger);
var policies = new PolicyStore(userId, policyTable, _database, _logger);
var filters = new TTSFilterStore(userId, ttsFilterTable, _database, _logger);
var actions = new ActionStore(userId, actionTable, _database, _logger);
var redemptions = new RedemptionStore(userId, redemptionTable, _database, _logger);
var voiceStates = new VoiceStateStore(userId, new VoiceIdValidator(), ttsVoiceStateTable, _database, _logger);
Task.WaitAll([
chatters.Load(),
connections.Load(),
groups.Load(),
groupPermissions.Load(),
policies.Load(),
filters.Load(),
actions.Load(),
redemptions.Load(),
voiceStates.Save(),
]);
var channel = new Channel()
lock (_lock)
{
Id = userId,
User = user,
Chatters = chatters,
Connections = connections,
Groups = groups,
GroupPermissions = groupPermissions,
Policies = policies,
Filters = filters,
Actions = actions,
Redemptions = redemptions,
VoiceStates = voiceStates,
};
if (_channels.ContainsKey(userId))
return Task.FromResult<Channel?>(null);
_channels.Add(userId, channel);
return Task.FromResult<Channel?>(channel);
}
var actionTable = _configuration.Database.Tables["Action"];
var chatterTable = _configuration.Database.Tables["Chatter"];
var connectionTable = _configuration.Database.Tables["Connection"];
//var chatterGroupTable = _configuration.Database.Tables["ChatterGroup"];
var groupTable = _configuration.Database.Tables["Group"];
var groupPermissionTable = _configuration.Database.Tables["GroupPermission"];
var policyTable = _configuration.Database.Tables["Policy"];
var redemptionTable = _configuration.Database.Tables["Redemption"];
var ttsFilterTable = _configuration.Database.Tables["TtsFilter"];
var ttsVoiceStateTable = _configuration.Database.Tables["VoiceState"];
var chatters = new ChatterStore(userId, chatterTable, _database, _logger);
var connections = new ConnectionStore(userId, connectionTable, _database, _logger);
var groups = new GroupStore(userId, groupTable, _database, _configuration, _logger);
var groupPermissions = new GroupPermissionStore(userId, groupPermissionTable, groups, _database, _logger);
var policies = new PolicyStore(userId, policyTable, groups, _database, _logger);
var filters = new TTSFilterStore(userId, ttsFilterTable, _database, _logger);
var actions = new ActionStore(userId, actionTable, _database, _logger);
var redemptions = new RedemptionStore(userId, redemptionTable, actions, _database, _logger);
var voiceStates = new VoiceStateStore(userId, ttsVoiceStateTable, _voices, _database, _logger);
var channel = new Channel()
{
Id = userId,
User = user,
Chatters = chatters,
Connections = connections,
Groups = groups,
GroupPermissions = groupPermissions,
Policies = policies,
Filters = filters,
Actions = actions,
Redemptions = redemptions,
VoiceStates = voiceStates,
};
Task.WaitAll([
channel.Actions.Load(),
channel.Chatters.Load(),
channel.Connections.Load(),
channel.Groups.Load(),
channel.Filters.Load(),
channel.VoiceStates.Load(),
]);
Task.WaitAll([
channel.GroupPermissions.Load(),
channel.Policies.Load(),
channel.Redemptions.Load(),
]);
_channels.Add(userId, channel);
return Task.FromResult<Channel?>(channel);
}
});
}
public Channel? Get(string channelId)
@@ -121,17 +129,25 @@ namespace HermesSocketServer.Services
foreach (var channel in _channels.Values)
{
_logger.Debug($"Saving channel data to database [channel id: {channel.Id}][channel name: {channel.User.Name}]");
await Task.WhenAll([
var genericTablesTask = Task.WhenAll([
channel.Chatters.Save(),
channel.Connections.Save(),
channel.Filters.Save(),
channel.VoiceStates.Save(),
]).ConfigureAwait(false);
await Task.WhenAll([
channel.Actions.Save(),
channel.Groups.Save(),
]).ConfigureAwait(false);
await Task.WhenAll([
channel.GroupPermissions.Save(),
channel.Policies.Save(),
channel.Filters.Save(),
channel.Actions.Save(),
channel.Redemptions.Save(),
channel.VoiceStates.Save(),
]);
]).ConfigureAwait(false);
await genericTablesTask;
}
}
}

View File

@@ -1,4 +1,3 @@
using HermesSocketLibrary.db;
using HermesSocketLibrary.Requests.Messages;
using HermesSocketServer.Models;
using HermesSocketServer.Store;
@@ -24,10 +23,10 @@ namespace HermesSocketServer.Services
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
_logger.Information("Loading TTS voices...");
await _voices.Load();
_logger.Information("Loading users...");
await _users.Load();
_logger.Information("Loading TTS voices...");
await _voices.Load();
await Task.Run(async () =>
{
@@ -35,11 +34,10 @@ namespace HermesSocketServer.Services
while (true)
{
await Task.WhenAll([
_voices.Save(),
_users.Save(),
_channels.Save(),
]);
await _users.Save();
await _voices.Save();
await _channels.Save();
await Task.Delay(TimeSpan.FromSeconds(_configuration.Database.SaveDelayInSeconds));
}
});