Fix chat manager issues hopefully

This commit is contained in:
Jordan Brown
2021-10-09 10:43:47 -04:00
parent 89960c61f0
commit c3dfec1034
3 changed files with 46 additions and 52 deletions
@@ -190,9 +190,16 @@ namespace Tgstation.Server.Host.Components.Chat
throw new ArgumentNullException(nameof(newChannels));
logger.LogTrace("ChangeChannels {0}...", connectionId);
var provider = await RemoveProvider(connectionId, false, cancellationToken).ConfigureAwait(false);
var provider = await RemoveProviderChannels(connectionId, false, cancellationToken).ConfigureAwait(false);
if (provider == null)
return;
if (!provider.Connected)
{
logger.LogDebug("Cannot map channels, provider {providerId} disconnected!", connectionId);
return;
}
var results = await provider.MapChannels(newChannels, cancellationToken).ConfigureAwait(false);
lock (activeChatBots)
{
@@ -260,29 +267,14 @@ namespace Tgstation.Server.Host.Components.Chat
throw new ArgumentNullException(nameof(newSettings));
logger.LogTrace("ChangeSettings...");
IProvider provider;
async Task DisconnectProvider(IProvider p)
{
try
{
await p.Disconnect(cancellationToken).ConfigureAwait(false);
}
finally
{
await p.DisposeAsync().ConfigureAwait(false);
}
}
Task disconnectTask;
IProvider provider = null;
lock (providers)
{
// raw settings changes forces a rebuild of the provider
if (providers.TryGetValue(newSettings.Id.Value, out provider))
{
providers.Remove(newSettings.Id.Value);
disconnectTask = DisconnectProvider(provider);
}
if (providers.ContainsKey(newSettings.Id.Value))
disconnectTask = DeleteConnection(newSettings.Id.Value, cancellationToken);
else
disconnectTask = Task.CompletedTask;
if (newSettings.Enabled.Value)
@@ -430,7 +422,6 @@ namespace Tgstation.Server.Host.Components.Chat
builtinCommands.Add(tgsCommand.Name.ToUpperInvariant(), tgsCommand);
var initialChatBots = activeChatBots.ToList();
await Task.WhenAll(initialChatBots.Select(x => ChangeSettings(x, cancellationToken))).ConfigureAwait(false);
await Task.WhenAll(initialChatBots.Select(x => ChangeChannels(x.Id.Value, x.Channels, cancellationToken))).ConfigureAwait(false);
initialProviderConnectionsTask = InitialConnection();
chatHandler = MonitorMessages(handlerCts.Token);
}
@@ -441,7 +432,7 @@ namespace Tgstation.Server.Host.Components.Chat
handlerCts.Cancel();
if (chatHandler != null)
await chatHandler.ConfigureAwait(false);
await Task.WhenAll(providers.Select(x => x.Value).Select(x => x.Disconnect(cancellationToken))).ConfigureAwait(false);
await Task.WhenAll(providers.Select(x => x.Key).Select(x => DeleteConnection(x, cancellationToken))).ConfigureAwait(false);
await messageSendTask.ConfigureAwait(false);
}
@@ -480,7 +471,7 @@ namespace Tgstation.Server.Host.Components.Chat
/// <inheritdoc />
public async Task DeleteConnection(long connectionId, CancellationToken cancellationToken)
{
var provider = await RemoveProvider(connectionId, true, cancellationToken).ConfigureAwait(false);
var provider = await RemoveProviderChannels(connectionId, true, cancellationToken).ConfigureAwait(false);
if (provider != null)
try
{
@@ -510,23 +501,28 @@ namespace Tgstation.Server.Host.Components.Chat
}
/// <summary>
/// Remove a <see cref="IProvider"/> from <see cref="providers"/> and <see cref="mappedChannels"/> optionally updating the <see cref="trackingContexts"/> as well.
/// Remove a <see cref="IProvider"/> from <see cref="mappedChannels"/> optionally removing the provider itself from <see cref="providers"/> and updating the <see cref="trackingContexts"/> as well.
/// </summary>
/// <param name="connectionId">The <see cref="Api.Models.EntityId.Id"/> of the <see cref="IProvider"/> to delete.</param>
/// <param name="updateTrackings">If <see cref="trackingContexts"/> should be update.</param>
/// <param name="removeProvider">If the provider should be removed from <see cref="providers"/> and <see cref="trackingContexts"/> should be update.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IProvider"/> being removed if it exists, <see langword="null"/> otherwise.</returns>
async Task<IProvider> RemoveProvider(long connectionId, bool updateTrackings, CancellationToken cancellationToken)
async Task<IProvider> RemoveProviderChannels(long connectionId, bool removeProvider, CancellationToken cancellationToken)
{
logger.LogTrace("RemoveProvider {0}...", connectionId);
logger.LogTrace("RemoveProviderChannels {0}...", connectionId);
IProvider provider;
lock (providers)
{
if (!providers.TryGetValue(connectionId, out provider))
{
logger.LogTrace("Aborted, no such provider!");
return null;
}
if (removeProvider)
providers.Remove(connectionId);
}
Task trackingContextsUpdateTask;
lock (mappedChannels)
{
@@ -535,7 +531,7 @@ namespace Tgstation.Server.Host.Components.Chat
var newMappedChannels = mappedChannels.Select(y => y.Value.Channel).ToList();
if (updateTrackings)
if (removeProvider)
lock (trackingContexts)
trackingContextsUpdateTask = Task.WhenAll(trackingContexts.Select(x => x.UpdateChannels(newMappedChannels, cancellationToken)));
else
@@ -607,6 +603,7 @@ namespace Tgstation.Server.Host.Components.Chat
.First();
mappedChannel = mappedChannels
.Where(x => x.Value.ProviderId == providerId && x.Value.ProviderChannelId == providerChannelId)
.Select(x => (KeyValuePair<ulong, ChannelMapping>?)x)
.FirstOrDefault();
}
@@ -652,12 +649,11 @@ namespace Tgstation.Server.Host.Components.Chat
return;
}
var mappingNonNullableKvp = mappedChannel.Value;
var mapping = mappingNonNullableKvp.Value;
var mappingChannelRepresentation = mappedChannel.Value.Value.Channel;
message.User.Channel.Id = mapping.Channel.Id;
message.User.Channel.Tag = mapping.Channel.Tag;
message.User.Channel.IsAdminChannel = mapping.Channel.IsAdminChannel;
message.User.Channel.Id = mappingChannelRepresentation.Id;
message.User.Channel.Tag = mappingChannelRepresentation.Tag;
message.User.Channel.IsAdminChannel = mappingChannelRepresentation.IsAdminChannel;
}
var splits = new List<string>(message.Content.Trim().Split(' '));
@@ -93,6 +93,11 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// </summary>
Snowflake currentUserId;
/// <summary>
/// The bot's username at the time of connection.
/// </summary>
string initialUserName;
/// <summary>
/// Normalize a discord mention string.
/// </summary>
@@ -194,20 +199,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
if (channels == null)
throw new ArgumentNullException(nameof(channels));
if (!Connected)
{
Logger.LogWarning("Cannot map channels, provider disconnected!");
return Array.Empty<ChannelRepresentation>();
}
var usersClient = serviceProvider.GetRequiredService<IDiscordRestUserAPI>();
var currentUserResponse = await usersClient.GetCurrentUserAsync(cancellationToken).ConfigureAwait(false);
if (!currentUserResponse.IsSuccess)
{
Logger.LogWarning("Error retrieving current Discord user: {0}", currentUserResponse.Error.Message);
return Array.Empty<ChannelRepresentation>();
}
bool remapRequired = false;
async Task<ChannelRepresentation> GetModelChannelFromDBChannel(Api.Models.ChatChannel channelFromDB)
{
@@ -215,14 +207,12 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
throw new InvalidOperationException("ChatChannel missing DiscordChannelId!");
var channelId = channelFromDB.DiscordChannelId.Value;
ulong discordChannelId;
string connectionName;
string friendlyName;
if (channelId == 0)
{
connectionName = currentUserResponse.Entity.Username;
connectionName = initialUserName;
friendlyName = "(Unmapped accessible channels)";
discordChannelId = 0;
}
else
{
@@ -231,6 +221,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
if (!discordChannelResponse.IsSuccess)
{
Logger.LogWarning("Error retrieving discord channel {0}: {1}", channelId, discordChannelResponse.Error.Message);
remapRequired = true;
return null;
}
@@ -240,7 +231,6 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
return null;
}
discordChannelId = discordChannelResponse.Entity.ID.Value;
friendlyName = discordChannelResponse.Entity.Name.Value;
var guildsClient = serviceProvider.GetRequiredService<IDiscordRestGuildAPI>();
@@ -254,6 +244,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
"Error retrieving discord guild {0}: {1}",
discordChannelResponse.Entity.GuildID.Value,
discordChannelResponse.Error.Message);
remapRequired = true;
return null;
}
@@ -262,7 +253,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
var channelModel = new ChannelRepresentation
{
RealId = discordChannelId,
RealId = channelId,
IsAdminChannel = channelFromDB.IsAdminChannel == true,
ConnectionName = connectionName,
FriendlyName = friendlyName,
@@ -276,13 +267,13 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
var tasks = channels
.Select(x => GetModelChannelFromDBChannel(x))
.Where(x => x != null)
.ToList();
await Task.WhenAll(tasks);
var enumerator = tasks
.Select(x => x.Result)
.Where(x => x != null)
.ToList();
lock (mappedChannels)
@@ -291,6 +282,9 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
mappedChannels.AddRange(enumerator.Select(x => x.RealId));
}
if (remapRequired)
EnqueueMessage(null);
return enumerator;
}
@@ -634,6 +628,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
}
currentUserId = currentUserResult.Entity.ID;
initialUserName = currentUserResult.Entity.Username;
}
finally
{
@@ -183,6 +183,9 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// <param name="message">The <see cref="Message"/> to queue.</param>
protected void EnqueueMessage(Message message)
{
if (message == null)
Logger.LogTrace("Requesting channel remap...");
lock (messageQueue)
{
messageQueue.Enqueue(message);