feat: block running commands / proxying when system is being deleted
Large systems take way too long to delete, which causes any insert for that system to block a connection, which exhausts the connection pool
This commit is contained in:
		@@ -10,4 +10,6 @@ public record MessageRequest
 | 
			
		||||
    public AllowedMentions? AllowedMentions { get; set; }
 | 
			
		||||
    public Embed[]? Embeds { get; set; }
 | 
			
		||||
    public MessageComponent[]? Components { get; set; }
 | 
			
		||||
    public Message.Reference? MessageReference { get; set; }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -120,6 +120,17 @@ public class MessageCreated: IEventHandler<MessageCreateEvent>
 | 
			
		||||
        if (!HasCommandPrefix(content, ourUserId, out var cmdStart) || cmdStart == content.Length)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (ctx.IsDeleting)
 | 
			
		||||
        {
 | 
			
		||||
            await _rest.CreateMessage(evt.ChannelId, new()
 | 
			
		||||
            {
 | 
			
		||||
                Content = $"{Emojis.Error} Your system is currently being deleted."
 | 
			
		||||
                    + " Due to database issues, it is not possible to use commands while a system is being deleted. Please wait a few minutes and try again.",
 | 
			
		||||
                MessageReference = new(guild?.Id, channel.Id, evt.Id)
 | 
			
		||||
            });
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Trim leading whitespace from command without actually modifying the string
 | 
			
		||||
        // This just moves the argPos pointer by however much whitespace is at the start of the post-argPos string
 | 
			
		||||
        var trimStartLengthDiff =
 | 
			
		||||
@@ -164,6 +175,8 @@ public class MessageCreated: IEventHandler<MessageCreateEvent>
 | 
			
		||||
    private async ValueTask<bool> TryHandleProxy(MessageCreateEvent evt, Guild guild, Channel channel,
 | 
			
		||||
                                                 MessageContext ctx)
 | 
			
		||||
    {
 | 
			
		||||
        if (ctx.IsDeleting) return false;
 | 
			
		||||
 | 
			
		||||
        var botPermissions = await _cache.PermissionsIn(channel.Id);
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,11 @@ namespace PluralKit.Core;
 | 
			
		||||
public class MessageContext
 | 
			
		||||
{
 | 
			
		||||
    public SystemId? SystemId { get; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Whether a system is being deleted (no actions should be taken, or commands ran)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool IsDeleting { get; }
 | 
			
		||||
    public ulong? LogChannel { get; }
 | 
			
		||||
    public bool InBlacklist { get; }
 | 
			
		||||
    public bool InLogBlacklist { get; }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
create function message_context(account_id bigint, guild_id bigint, channel_id bigint)
 | 
			
		||||
    returns table (
 | 
			
		||||
        system_id int,
 | 
			
		||||
        is_deleting bool,
 | 
			
		||||
        log_channel bigint,
 | 
			
		||||
        in_blacklist bool,
 | 
			
		||||
        in_log_blacklist bool,
 | 
			
		||||
@@ -27,6 +28,7 @@ as $$
 | 
			
		||||
        guild as (select * from servers where id = guild_id)
 | 
			
		||||
    select
 | 
			
		||||
        system.id as system_id,
 | 
			
		||||
        system.is_deleting,
 | 
			
		||||
        guild.log_channel,
 | 
			
		||||
        (channel_id = any(guild.blacklist)) as in_blacklist,
 | 
			
		||||
        (channel_id = any(guild.log_blacklist)) as in_log_blacklist,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								PluralKit.Core/Database/Migrations/29.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								PluralKit.Core/Database/Migrations/29.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
-- schema version 29
 | 
			
		||||
 | 
			
		||||
alter table systems add column is_deleting bool default false;
 | 
			
		||||
 | 
			
		||||
update info set schema_version = 29;
 | 
			
		||||
@@ -142,10 +142,11 @@ public partial class ModelRepository
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Task DeleteSystem(SystemId id)
 | 
			
		||||
    public async Task DeleteSystem(SystemId id)
 | 
			
		||||
    {
 | 
			
		||||
        await _db.Execute(c => c.QueryAsync("update systems set is_deleting = true where id = @id", new { id = id }));
 | 
			
		||||
        var query = new Query("systems").AsDelete().Where("id", id);
 | 
			
		||||
        await _db.ExecuteQuery(query);
 | 
			
		||||
        _logger.Information("Deleted {SystemId}", id);
 | 
			
		||||
        return _db.ExecuteQuery(query);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -9,7 +9,7 @@ namespace PluralKit.Core;
 | 
			
		||||
internal class DatabaseMigrator
 | 
			
		||||
{
 | 
			
		||||
    private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files
 | 
			
		||||
    private const int TargetSchemaVersion = 28;
 | 
			
		||||
    private const int TargetSchemaVersion = 29;
 | 
			
		||||
    private readonly ILogger _logger;
 | 
			
		||||
 | 
			
		||||
    public DatabaseMigrator(ILogger logger)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user