邮箱创建时间打标与自动删除功能设计思路
🎯 问题背景
在邮件处理系统中,收件人邮箱数量会随时间无限增长,导致内存泄漏和性能下降。需要设计一个自动管理机制来解决这个问题。
🏗️ 设计方案
核心数据结构
// 邮箱创建时间映射表
private final Map<String, Long> emailCreationTimestamps = new ConcurrentHashMap<>();
// 收件人邮箱映射表
private final Map<String, List<EmailMessage>> recipientEmailMap = new ConcurrentHashMap<>();
// 保留时间配置
private static final long EMAIL_RETENTION_TIME = 24 * 60 * 60 * 1000; // 1天
设计思路
- 创建时间打标:新邮箱首次出现时记录时间戳
- 自动清理:每次处理邮件后检查过期邮箱
- 批量删除:一次性删除所有过期邮箱
- 异步处理:服务器删除操作异步执行
🔧 核心实现
1. 邮箱创建时间打标
private void processEmailGrouping(List<EmailMessage> newEmails) {
long currentTime = System.currentTimeMillis();
recipientEmailGroupMap.forEach((recipientEmail, emails) -> {
// 检查是否是新邮箱
if (!recipientEmailMap.containsKey(recipientEmail)) {
// 记录新邮箱的创建时间
emailCreationTimestamps.put(recipientEmail, currentTime);
log.debug("新邮箱 {} 创建时间: {}", recipientEmail, new Date(currentTime));
}
recipientEmailMap.computeIfAbsent(recipientEmail, k -> new ArrayList<>())
.addAll(emails);
});
}
2. 自动删除过期邮箱
private void cleanupExpiredEmails() {
long currentTime = System.currentTimeMillis();
Set<String> expiredEmails = findExpiredEmails(currentTime);
if (!expiredEmails.isEmpty()) {
performEmailCleanup(expiredEmails);
}
}
private Set<String> findExpiredEmails(long currentTime) {
return emailCreationTimestamps.entrySet().stream()
.filter(entry -> (currentTime - entry.getValue()) > EMAIL_RETENTION_TIME)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
3. 邮箱删除机制
public boolean deleteRecipientEmail(String recipientEmail) {
try {
List<EmailMessage> emailsToDelete = recipientEmailMap.get(recipientEmail);
if (ObjectUtils.isNotEmpty(emailsToDelete)) {
// 删除邮件ID
// 取出id
Set<String> messageIds = emailsToDelete.stream()
.map(EmailMessage::getMessageId)
.collect(Collectors.toSet());
processedMessageIds.removeAll(messageIds);
// 删除内存中的邮箱
recipientEmailMap.remove(recipientEmail);
// 删除创建时间
emailCreationTimestamps.remove(recipientEmail);
// 异步删除服务器邮件
deleteEmailsFromServerAsync(recipientEmail);
}
return true;
} catch (Exception e) {
log.error("删除邮箱 {} 时发生错误", recipientEmail, e);
return false;
}
}
📊 监控统计
public Map<String, Object> getProcessingStats() {
Map<String, Object> stats = new ConcurrentHashMap<>();
int totalEmailCount = recipientEmailMap.values().stream()
.mapToInt(List::size)
.sum();
stats.put("processedMessageCount", processedMessageIds.size());
stats.put("recipientEmailCount", recipientEmailMap.size());
stats.put("totalEmailCount", totalEmailCount);
stats.put("emailCreationTimestampCount", emailCreationTimestamps.size());
return stats;
}
🚀 工作流程设计
1. 新邮箱创建流程
flowchart TD
A[开始处理邮件] --> B[邮件分组处理]
B --> C[检查是否新邮箱]
C --> D{是否为新邮箱?}
D -->|是| E[记录创建时间]
D -->|否| F[添加到映射表]
E --> F
F --> G[清理过期邮箱]
G --> H[结束]
style A fill:#e1f5fe
style E fill:#c8e6c9
style G fill:#fff3e0
style H fill:#f3e5f5
2. 自动清理流程
flowchart TD
A[开始清理检查] --> B[获取当前时间]
B --> C[查找过期邮箱]
C --> D{有过期邮箱?}
D -->|是| E[批量删除处理]
D -->|否| F[结束]
E --> G[记录清理日志]
G --> F
style A fill:#e1f5fe
style E fill:#ffcdd2
style G fill:#fff3e0
style F fill:#f3e5f5
3. 邮箱删除详细流程
flowchart TD
A[开始删除邮箱] --> B[获取邮件列表]
B --> C{邮件列表为空?}
C -->|是| D[记录日志]
C -->|否| E[删除邮件ID]
E --> F[删除内存中的邮箱]
F --> G[删除创建时间]
G --> H[异步删除服务器邮件]
H --> I[返回成功]
D --> J[返回成功]
style A fill:#e1f5fe
style E fill:#ffcdd2
style F fill:#ffcdd2
style G fill:#ffcdd2
style H fill:#fff3e0
style I fill:#c8e6c9
style J fill:#c8e6c9
4. 整体系统工作流程
flowchart TD
A[系统启动] --> B[定时任务触发]
B --> C[获取新邮件]
C --> D{有新邮件?}
D -->|否| B
D -->|是| E[邮件分组处理]
E --> F[检查新邮箱]
F --> G{发现新邮箱?}
G -->|是| H[记录创建时间]
G -->|否| I[添加到映射表]
H --> I
I --> J[自动清理检查]
J --> K{有过期邮箱?}
K -->|是| L[批量删除过期邮箱]
K -->|否| M[等待下次任务]
L --> N[异步删除服务器邮件]
N --> M
M --> B
style A fill:#e1f5fe
style H fill:#c8e6c9
style L fill:#ffcdd2
style N fill:#fff3e0
5. 数据流转关系图
graph LR
A[新邮件] --> B[邮件分组]
B --> C[邮箱映射表]
B --> D[创建时间映射表]
C --> E[过期检测]
D --> E
E --> F[过期邮箱列表]
F --> G[批量删除]
G --> H[内存清理]
G --> I[服务器删除]
style A fill:#e1f5fe
style C fill:#c8e6c9
style D fill:#c8e6c9
style F fill:#ffcdd2
style H fill:#ffcdd2
style I fill:#fff3e0
📝 使用示例
// 获取统计信息
Map<String, Object> stats = defaultEmailMonitorService.getProcessingStats();
System.out.println("邮箱数量: " + stats.get("recipientEmailCount"));
// 获取所有邮箱
List<String> allEmails = defaultEmailMonitorService.getAllRecipientEmails();
// 删除指定邮箱
boolean success = defaultEmailMonitorService.deleteRecipientEmail("user@example.com");