refactor(app): 优化后台任务退出与外部 IMAP 认证

- 统一用 `WaitGroup` 管理后台 worker,关闭时等待任务结束后再释放数据库连接。
- 将外部 IMAP 的 OAuth 认证切换为 `XOAUTH2` 客户端实现,并补充对应格式测试。
- 调整发送队列的故障恢复逻辑,超时中断后恢复为排队状态以便重新投递。
This commit is contained in:
LanQin
2026-06-25 21:36:59 +08:00
parent 081cfad02d
commit efcdc691de
4 changed files with 66 additions and 9 deletions
+16 -5
View File
@@ -15,6 +15,7 @@ import (
"os"
"path/filepath"
"strings"
"sync"
"time"
"golang.org/x/crypto/bcrypt"
@@ -28,6 +29,7 @@ type App struct {
now func() time.Time
policy *HTMLPolicy
workerCancel context.CancelFunc
workerWG sync.WaitGroup
maildirHealth *maildirSyncHealthTracker
externalIMAP externalIMAPClientFactory
}
@@ -73,16 +75,24 @@ func New(cfg Config, logger *slog.Logger) (*App, error) {
}
workerCtx, cancel := context.WithCancel(context.Background())
a.workerCancel = cancel
go a.scheduledSendWorker(workerCtx)
a.startWorker(func() { a.scheduledSendWorker(workerCtx) })
if strings.TrimSpace(a.cfg.MaildirRoot) != "" {
go a.maildirWorker(workerCtx)
a.startWorker(func() { a.maildirWorker(workerCtx) })
}
go a.sendQueueWorker(workerCtx)
go a.externalIMAPWorker(workerCtx)
go a.smtpEventsCleanupWorker(workerCtx)
a.startWorker(func() { a.sendQueueWorker(workerCtx) })
a.startWorker(func() { a.externalIMAPWorker(workerCtx) })
a.startWorker(func() { a.smtpEventsCleanupWorker(workerCtx) })
return a, nil
}
func (a *App) startWorker(fn func()) {
a.workerWG.Add(1)
go func() {
defer a.workerWG.Done()
fn()
}()
}
func (a *App) Close() error {
if a == nil || a.db == nil {
return nil
@@ -90,6 +100,7 @@ func (a *App) Close() error {
if a.workerCancel != nil {
a.workerCancel()
}
a.workerWG.Wait()
return a.db.Close()
}