Repository navigation
test(go): 邮件用例等作业的失败记进库再拨时钟,邮件按主题挑(Closes #200) - #201
Merged
Merged
Conversation
TestUnsentEmailChangeMailIsCancelledByPasswordReset 在放开发信并拨时钟之前,没等「口令已更改」通知作业的失败写进库。 失败的 run_at 取写入时刻的时钟加退避:写入落在拨钟之后(-race 的慢机器上发信返回到写库之间被拉长), run_at 就又后推 30 秒,没人再拨,通知永远等不到。 现在找回口令之前先等确认邮件的作业失败过一次(它若在找回之后才第一次执行,会发现改邮箱已作废、丢掉发件箱的行并完成, 从头到尾没失败过),找回之后再等通知作业也失败一次并记下(last_error 落库),然后才 FailNext(0) 并拨时钟; 等不到时把全部 mail.send 作业的状态列进失败信息。末尾等全部 mail.send 作业处理完再断言新地址没有信。 noMail / noMail2 与新设备提醒用例的「睡 300ms 再断言没有」同样改为等作业处理完。等邮件的上限与 eventuallyDB 一致放到 60 秒 (条件成立即返回)。剩下的 waitMails(...)[0] 全部改为 waitSubject,按主题挑信。
Owlbay
force-pushed
the
fix/flaky-mail-test-200
branch
from
November 2, 2026 23:21
0ac8583 to
12edc74
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
变更摘要 / Summary
只改测试
go/internal/cloud/server/mail_test.go,不动生产代码。根因:
TestUnsentEmailChangeMailIsCancelledByPasswordReset在FailNext(0)并clock.Advance(31s)之前,没等「口令已更改」通知作业的失败写进库。作业失败时run_at = 写入时刻的时钟 + 30 秒退避;发信返回与写库之间在-race的慢机器上被拉长时,写入落在拨钟之后,run_at又被推后 30 秒,测试里没人再拨时钟,通知永远等不到(mail_test.go:752,现有 1 封)。生产里时钟是真实时间,不受影响。已在mail.send失败路径临时加 400ms 延迟复现同一行失败,修复后同样延迟下通过(延迟补丁未提交)。改动:
last_error落库、无未尝试的 open 作业),然后才放开发信、拨时钟;等不到时失败信息里列出全部mail.send作业的状态;mail.send作业处理完再断言新地址没有信;noMail、noMail2与新设备提醒用例里「睡 300ms 再断言没有」同样改为等作业处理完(mailJobsSettled);eventuallyDB一致放到 60 秒(条件成立即返回);找回口令防枚举用例里自带的 10 秒轮询改用eventuallyDB;waitMails(...)[0]全部改为waitSubject,按主题挑信,不按下标取。Test-only change in
go/internal/cloud/server/mail_test.go; no production code is touched.Root cause: before calling
FailNext(0)andclock.Advance(31s),TestUnsentEmailChangeMailIsCancelledByPasswordResetdid not wait for the failure of the "password changed" notification job to be written to the database. A failing job getsrun_at = clock at write time + 30 s backoff; when the gap between the send returning and the write is stretched on a slow-racemachine, the write lands after the clock was advanced,run_atmoves another 30 s out, nobody advances the clock again, and the notification never arrives (mail_test.go:752, 1 mail present). Production uses the real clock and is not affected. Reproduced the same failure line by temporarily adding a 400 ms delay on themail.sendfailure path; with the fix the test passes under the same delay (the delay patch is not committed).Changes:
last_error, no open job without an attempt), and only then enable the sender and advance the clock; on timeout the failure message lists everymail.sendjob's state;mail.sendjobs are processed before asserting that the new address got nothing;noMail,noMail2and the new-device reminder test no longer sleep 300 ms before asserting absence (mailJobsSettled);eventuallyDB(returns as soon as the condition holds); the local 10 s poll in the reset-does-not-enumerate test now useseventuallyDB;waitMails(...)[0]picks in the file now usewaitSubject, so mails are picked by subject rather than by index.关联 issue / Related issues
Closes #200
改动范围 / Scope
go/,仅测试 / tests only)契约与协议变化 / Contract and protocol changes
数据库迁移 / Database migrations
migrations.lock: 无 / None测试 / Testing
pnpm go:check通过(含go test -race ./...,一次性 PostgreSQL 17 与 Redis 8 容器)/ passespnpm check通过 / passes(pnpm repo:test无关,未跑 / unrelated, not run)go test -race -count=20 -run 'Mail|Email' ./internal/cloud/server:12 个 CPU 忙循环负载下全过 / passes under 12 busy-loop CPU load(221s)检查清单 / Checklist
需要维护者提供的外部条件 / External prerequisites
无 / None