perf(message): unlog bulk message delete batches (#2126)

This commit is contained in:
Hampus
2026-08-30 22:15:19 +02:00
committed by GitHub
parent 74f22e89ce
commit 8aa3415d73
2 changed files with 32 additions and 4 deletions
@@ -19,6 +19,7 @@ import {
import type {MessageDataRepository} from './MessageDataRepository';
const BULK_DELETE_BATCH_SIZE = 100;
const BULK_DELETE_BATCH_QUERY_LIMIT = 30;
const POST_DELETE_BUCKET_CHECK_LIMIT = 25;
const HAS_ANY_MESSAGE_IN_BUCKET = Messages.select({
columns: ['message_id'],
@@ -230,7 +231,7 @@ export class MessageDeletionRepository {
affectedBuckets.add(bucket);
this.addMessageDeletionBatchQueries(batch, channelId, messageId, bucket, message);
}
await batch.execute();
await batch.executeChunked(BULK_DELETE_BATCH_QUERY_LIMIT, false);
await this.postDeleteMaintenance(channelId, affectedBuckets, chunk);
}
}
@@ -264,7 +265,7 @@ export class MessageDeletionRepository {
message.pinnedTimestamp || undefined,
);
}
await batch.execute();
await batch.executeChunked(BULK_DELETE_BATCH_QUERY_LIMIT, false);
}
if (messages.length < 100) {
hasMore = false;
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {afterAll, beforeAll, beforeEach, describe, it} from 'vitest';
import type {MessageResponse} from '@fluxer/schema/src/domains/message/MessageResponseSchemas';
import {afterAll, beforeAll, beforeEach, describe, expect, it} from 'vitest';
import {createTestAccount} from '../../auth/tests/AuthTestUtils';
import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness';
import {createBuilder} from '../../test/TestRequestBuilder';
import {createGuild} from './ChannelTestUtils';
import {createGuild, sendChannelMessage} from './ChannelTestUtils';
describe('Bulk Delete Messages', () => {
let harness: ApiTestHarness;
@@ -78,6 +79,32 @@ describe('Bulk Delete Messages', () => {
.expect(204)
.execute();
});
it('removes every message when the bulk delete spans more than one batch chunk', async () => {
const owner = await createTestAccount(harness);
const guild = await createGuild(harness, owner.token, 'Bulk Delete Chunk Test Guild');
if (!guild.system_channel_id) {
throw new Error('Guild should have a system channel');
}
const deletedIds: Array<string> = [];
for (let i = 0; i < 16; i++) {
const message = await sendChannelMessage(harness, owner.token, guild.system_channel_id, `chunk target ${i}`);
deletedIds.push(message.id);
}
const survivor = await sendChannelMessage(harness, owner.token, guild.system_channel_id, 'chunk survivor');
await createBuilder(harness, owner.token)
.post(`/channels/${guild.system_channel_id}/messages/bulk-delete`)
.body({message_ids: deletedIds})
.expect(204)
.execute();
const messages = await createBuilder<Array<MessageResponse>>(harness, owner.token)
.get(`/channels/${guild.system_channel_id}/messages`)
.execute();
const remainingIds = messages.map((message) => message.id);
for (const deletedId of deletedIds) {
expect(remainingIds).not.toContain(deletedId);
}
expect(remainingIds).toContain(survivor.id);
});
it('accepts bulk delete request with the compat messages alias', async () => {
const owner = await createTestAccount(harness);
const guild = await createGuild(harness, owner.token, 'Bulk Delete Alias Test Guild');