perf: limit indexed cleanup task batches (#1107)

Limit mail, sent-mail, and indexed address cleanup to configurable batches. Includes E2E coverage and documentation.
This commit is contained in:
Dream Hunter
2026-08-09 23:32:05 +08:00
committed by GitHub
parent a09ede8944
commit 12152fc893
9 changed files with 140 additions and 6 deletions
+24 -6
View File
@@ -494,18 +494,26 @@ export const cleanup = async (
if (!cleanType || typeof cleanDays !== 'number' || cleanDays < 0 || cleanDays > 1000) {
throw new Error(msgs.InvalidCleanupConfigMsg)
}
let cleanupBatchSize = getIntValue(c.env.CLEANUP_BATCH_SIZE, 3000);
if (!Number.isInteger(cleanupBatchSize) || cleanupBatchSize < 1 || cleanupBatchSize > 5000) {
cleanupBatchSize = 3000;
}
console.log(`Cleanup ${cleanType} before ${cleanDays} days`);
switch (cleanType) {
case "inactiveAddress":
await batchDeleteAddressWithData(
c,
`updated_at < datetime('now', '-${cleanDays} day')`
`id IN (`
+ `SELECT id FROM address WHERE updated_at < datetime('now', '-${cleanDays} day') `
+ `ORDER BY updated_at, id LIMIT ${cleanupBatchSize})`
)
break;
case "addressCreated":
await batchDeleteAddressWithData(
c,
`created_at < datetime('now', '-${cleanDays} day')`
`id IN (`
+ `SELECT id FROM address WHERE created_at < datetime('now', '-${cleanDays} day') `
+ `ORDER BY created_at, id LIMIT ${cleanupBatchSize})`
)
break;
case "unboundAddress":
@@ -516,8 +524,13 @@ export const cleanup = async (
break;
case "mails":
await c.env.DB.prepare(`
DELETE FROM raw_mails WHERE created_at < datetime('now', '-${cleanDays} day')`
).run();
DELETE FROM raw_mails WHERE id IN (
SELECT id FROM raw_mails
WHERE created_at < datetime('now', ?)
ORDER BY created_at, id
LIMIT ?
)`
).bind(`-${cleanDays} day`, cleanupBatchSize).run();
break;
case "mails_unknow":
await c.env.DB.prepare(`
@@ -527,8 +540,13 @@ export const cleanup = async (
break;
case "sendbox":
await c.env.DB.prepare(`
DELETE FROM sendbox WHERE created_at < datetime('now', '-${cleanDays} day')`
).run();
DELETE FROM sendbox WHERE id IN (
SELECT id FROM sendbox
WHERE created_at < datetime('now', ?)
ORDER BY created_at, id
LIMIT ?
)`
).bind(`-${cleanDays} day`, cleanupBatchSize).run();
break;
case "emptyAddress":
// Delete addresses that have no emails and were created more than N days ago
+1
View File
@@ -117,6 +117,7 @@ type Bindings = {
// gzip compression for raw_mails
ENABLE_MAIL_GZIP: string | boolean | undefined
CLEANUP_BATCH_SIZE: string | number | undefined
// E2E testing
E2E_TEST_MODE: string | boolean | undefined
+2
View File
@@ -17,6 +17,8 @@ keep_vars = true
# enable cron if you want set auto clean up
# [triggers]
# crons = [ "0 0 * * *" ]
# Per-run limit for mail, sent-mail, and creation/activity-based address cleanup. Defaults to 3000, maximum 5000.
# CLEANUP_BATCH_SIZE = 3000
# send_email = [
# { name = "SEND_MAIL" },