using System.Collections.Concurrent; using HermesSocketLibrary.db; using HermesSocketLibrary.Requests.Messages; using HermesSocketServer.Models; using HermesSocketServer.Store; namespace HermesSocketServer.Services { public class ChannelManager { private readonly IStore _users; private readonly Database _database; private readonly IStore _voices; private readonly ServerConfiguration _configuration; private readonly Serilog.ILogger _logger; private readonly IDictionary _channels; private readonly object _lock; public ChannelManager(IStore users, Database database, IStore voices, ServerConfiguration configuration, Serilog.ILogger logger) { _users = users; _database = database; _voices = voices; _configuration = configuration; _logger = logger; _channels = new ConcurrentDictionary(); _lock = new object(); } public async Task Add(string userId) { var user = _users.Get(userId); if (user == null) return null; return await Task.Run(() => { lock (_lock) { if (_channels.TryGetValue(userId, out var channel)) return Task.FromResult(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); 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); } }); } public Channel? Get(string channelId) { if (_channels.TryGetValue(channelId, out var channel)) return channel; return null; } public async Task Save(string userId) { if (!_channels.TryGetValue(userId, out var channel)) return; _logger.Debug($"Saving channel data to database [channel id: {channel.Id}][channel name: {channel.User.Name}]"); await Task.WhenAll([ channel.Chatters.Save(), channel.Connections.Save(), channel.Groups.Save(), channel.GroupPermissions.Save(), channel.Policies.Save(), channel.Filters.Save(), channel.Actions.Save(), channel.Redemptions.Save(), channel.VoiceStates.Save(), ]); } public async Task Save() { foreach (var channel in _channels.Values) { _logger.Debug($"Saving channel data to database [channel id: {channel.Id}][channel name: {channel.User.Name}]"); 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.Redemptions.Save(), ]).ConfigureAwait(false); await genericTablesTask; } } } }