for last 7 days of messages remove large messages first, then by age

This commit is contained in:
holger krekel
2026-04-23 22:56:53 +02:00
parent 7f58c8b38a
commit 20f7aafcff
2 changed files with 47 additions and 1 deletions

View File

@@ -99,11 +99,29 @@ def scan_mailbox_messages(mbox):
return messages
# Within this window, large messages are deleted before small ones.
DELETE_LARGE_FIRST_DAYS = 7
def expire_to_target(mbox, target_bytes):
cutoff = time.time() - DELETE_LARGE_FIRST_DAYS * 86400
messages = scan_mailbox_messages(mbox)
def sort_key(msg):
# prio 0: Older than cutoff -> remove oldest first
if msg.mtime < cutoff:
return (0, msg.mtime)
# prio 1: more recent than cutoff, large -> remove largest first
if msg.quota_size > 200000:
return (1, -msg.quota_size, msg.mtime)
# prio 2: more recent than cutoff, small -> remove oldest first
return (2, msg.mtime)
total_size = sum(m.quota_size for m in messages)
removed = 0
for entry in sorted(messages):
for entry in sorted(messages, key=sort_key):
if total_size <= target_bytes:
break
(mbox / entry.path).unlink(missing_ok=True)

View File

@@ -1,6 +1,7 @@
import itertools
import os
import random
import shutil
import time
from datetime import datetime
from fnmatch import fnmatch
@@ -240,6 +241,33 @@ def test_expire_to_target(tmp_path):
assert len(scan_mailbox_messages(tmp_path)) == 1
def test_expire_to_target_prioritization(tmp_path):
def create_messages():
for sub in ("cur", "new"):
if (tmp_path / sub).exists():
shutil.rmtree(tmp_path / sub)
# prio 0: older than 7 days
_create_message(tmp_path, "cur", 5 * MB, days_old=10)
# prio 1: last 7 days, large (>200KB)
_create_message(tmp_path, "cur", 5 * MB, days_old=1)
# prio 2: last 7 days, small
_create_message(tmp_path, "cur", 1000, days_old=2)
# Shrink to 6MB: only the old message (prio 0) is removed.
create_messages()
assert expire_to_target(tmp_path, 6 * MB) == 1
msgs = scan_mailbox_messages(tmp_path)
assert len(msgs) == 2
assert all(m.mtime > time.time() - 7 * 86400 for m in msgs)
# Shrink to 1KB: old and recent-large removed, small survives.
create_messages()
assert expire_to_target(tmp_path, 1024) == 2
msgs = scan_mailbox_messages(tmp_path)
assert len(msgs) == 1
assert msgs[0].quota_size == 1000
def test_quota_expire_main(tmp_path, capsys):
mbox = tmp_path / "user@example.org"
_create_message(mbox, "cur", 2 * MB, days_old=5)