isTaskComplete checks is_sent=3, which nothing writes; ProcessTask discards its error (742fa834)
Found while evaluating dev commits for a downstream fork. Two issues in 742fa834 ("Fix campaigns stuck in Processing state"), both in core/internal/service/batch_mail/task_executor.go.
1. is_sent = 3 is never written, so the isTaskComplete change is dead logic
The commit changes the completion query to:
Fields("COUNT(1) as total_count, SUM(CASE WHEN is_sent IN (1, 3) THEN 1 ELSE 0 END) as sent_count")with the stated rationale "isTaskComplete counts failed recipients (is_sent=3) as done".
Nothing in the tree writes 3. The writers are:
0—batch_mail.go:234,batch_mail.go:2822—task_executor.go:692(claimed for sending)1—task_executor.go:934(success) andtask_executor.go:971(failure)
The schema documents only three states (database_initialization/batch_mail.go:104):
is_sent SMALLINT DEFAULT 0, -- 0: Pending processing 2: Extracted and ready for transmission 1: Transmission completedFailures are already recorded as 1, deliberately — task_executor.go:967 carries the comment // 失败的也更新 is_sent 和 sent_time 避免卡住发送状态.
So IN (1, 3) is currently a no-op superset of = 1. It is harmless today, but it encodes an assumption the schema contradicts: if a migration later introduces 3 with different semantics, task completion changes silently.
Either 3 should be introduced as a real failed state (and the schema comment updated), or the clause should stay = 1.
2. ProcessTask now discards the processing error
if err := e.processTaskRecipients(ctx, task, emailContent); err != nil {
g.Log().Error(ctx, "failed to process task: %v", err)
if errors.Is(err, context.Canceled) {
return nil
}
// Don't return — fall through to check completion
}err is scoped to the if statement, so after logging it is dropped. Callers — task_executor.go:130 and controller/batch_mail/batch_mail_v1_resume_task.go:69 — can no longer distinguish a partially failed run from a clean one.
Falling through to the completion check is reasonable and does fix the stuck-in-Processing symptom (partial failure leaves rows at 0, so the task correctly stays incomplete). The concern is only that the error is swallowed rather than propagated after the completion check.
Source: Billionmail/BillionMail