
数据库灾备【免费下载链接】databasusPostgreSQL backup tool with Point-In-Time-Recovery and restore verification项目地址https://gitcode.com/gh_mirrors/po/databasus点击查看免费下载本文围绕 Databasus 后端的一次变更任务清单展开当备份验证的自动调度被禁用时手动触发的验证任务曾会被调度器的禁用清理逻辑误取消。你将理解该缺陷的成因、修复的三条任务主线回归测试覆盖、取消选择逻辑与命名重构、最终验证流程并能直接复现仓库中的验证命令定位到 调度器、数据仓库层 与 枚举定义 的对应源码实现。变更背景手动验证不应受自动调度开关约束完整的任务定义见 tasks.md配套的需求与设计说明分别在同目录的 proposal.md 和 design.md 中。问题本质可以概括为一句话手动验证是一个按需触发的动作其生命周期不应依赖自动验证是否启用这个配置。而缺陷出在调度器的取消清理路径上用户通过 API 手动发起验证时服务层会创建一条Trigger MANUAL、Status PENDING的验证记录验证调度器每个 tick 都会执行一次禁用清理把验证配置已禁用 记录未到达终态的验证统一标记为CANCELED清理时选择数据行的 SQL没有按触发类型trigger过滤导致刚入队的手动验证在下一次 tick调度器间隔为 15 秒见 scheduler.go#L20-L23内就被取消。修复方向由 design.md 明确把取消边界下沉到数据选择本身——只有自动触发类型SCHEDULED与AFTER_BACKUP进入禁用调度的取消集合。该变更不破坏任何 API、配置字段或数据结构也不涉及前端、验证 Agent、数据库迁移或部署方式仅收敛在后端验证调度器、其数据选择及相邻测试。任务主线一回归测试覆盖Regression coveragetasks.md 的第一节定义了两条测试任务核心是确保修复前测试必须失败、修复后必须通过任务要求仓库中的落地证据1.1保留待处理手动验证被误取消的复现用例新增运行中手动验证用例并用指定go test命令确认用例在查询修复前失败复现用例在命名重构后为Test_CancelAutomaticVerificationsForDisabledSchedules_WhenManualVerificationExists_LeavesItPendingscheduler_test.go#L3841.2覆盖SCHEDULED与AFTER_BACKUP两种自动触发在两种非终态下被取消的场景包括与手动验证共存的情形并确认 API 可见状态与backup-verification规格一致对应用例..._WhenAutomaticVerificationExists_CancelsItscheduler_test.go#L469与..._WhenManualAndAutomaticVerificationsCoexist_CancelsOnlyAutomaticscheduler_test.go#L562说明tasks.md 第 1.1 条给出的过滤命令使用旧函数名前缀-run Test_SweepCanceledByDisabledConfig_WhenManualVerification这是重构前复现用例的命名重构落地后同一批用例已统一改名为Test_CancelAutomaticVerificationsForDisabledSchedules_*系列与调度器新动作名保持一致。值得强调的是测试的构造方式。design.md 在Rejected alternatives中明确否决了两个偷懒方案不等调度器 ticker 的真实触发等待 15 秒的 tick 会让测试变慢且引入时序依赖测试改为直接调用一次取消清理动作只验证选择与状态迁移这个真正的契约点只孤立测试 SQL 查询项目测试规范backend/AGENTS.md偏好以 controller 为后盾的覆盖清理后 API 可见的状态才是对外契约。因此每个用例的造数路径都来自真实入口手动验证走 API 辅助函数、定时验证走调度器创建路径、备份后验证走备份完成事件、运行中状态走 Agent 认领路径。当前 scheduler_test.go 中这组取消清理用例覆盖了五个关键组合WhenScheduledVerificationDisabled_CancelsNonTerminalRowsL341——禁用配置下非终态自动验证被取消WhenManualVerificationExists_LeavesItPendingL384——PENDING手动验证保留WhenManualVerificationIsRunning_LeavesItRunningL421——RUNNING手动验证保留WhenAutomaticVerificationExists_CancelsItL469——自动验证按旧行为继续被取消WhenManualAndAutomaticVerificationsCoexist_CancelsOnlyAutomaticL562——混合场景下只取消自动验证这是该缺陷最核心的回归断言。任务主线二取消选择逻辑与命名重构Cancellation selectiontasks.md 第二节的两个子任务本质是用命名和查询谓词把只取消自动验证这条规则显式化2.1仓库层方法FindNonTerminalForDisabledConfigs重命名为GetNonTerminalAutomaticVerificationsForDisabledSchedules不提供旧名别名并在 SQL 中加入显式的 trigger 白名单2.2调度器动作sweepCanceledByDisabledConfig重命名为cancelAutomaticVerificationsForDisabledSchedules同步更新所有调用方与测试确保 backend 内不残留旧名。数据选择层白名单谓词落在 SQL 里重构后的仓库方法实现见 repository.go#L276-L295其核心查询为SELECT v.* FROM restore_verifications v JOIN backup_verification_configs c ON c.database_id v.database_id WHERE c.is_scheduled_verification_enabled false -- 配置已禁用 AND v.trigger IN (SCHEDULED, AFTER_BACKUP) -- 仅自动触发白名单 AND v.status IN (PENDING, RUNNING); -- 仅非终态三个条件缺一不可分别对应禁用调度、自动触发、未终结三个语义维度。其中触发类型取值来自 enums.go#L13-L19 的MANUAL/SCHEDULED/AFTER_BACKUP枚举非终态即PENDING/RUNNING终态为COMPLETED/FAILED/CANCELED见 enums.go#L3-L11。design.md 记录了几个被否决的替代方案它们解释了为什么最终选择白名单 仓库层过滤在调度器里 fetch 全部非终态再跳过MANUAL会读取无关行且把选择规则拆散到仓库与调度器两处选择除MANUAL外所有触发一旦未来新增某种用户发起的触发类型会被默认取消。白名单使新触发的语义成为一个显式决策——引入新的自动触发时必须同步更新取消选择并补一条禁用调度回归用例这一风险在 design.md 的 Risks 一节中被显式声明在VerificationTrigger上加IsAutomatic()方法SQL 查询仍需要显式的触发取值谓词方法只会造成分类逻辑重复。调度器动作层按执行的迁移命名取消清理动作现位于 scheduler.go#L239-L266在每个 tick 内与创建定时验证、清理陈旧运行并列执行scheduler.go#L55-L68// Disabling a schedule is user initiated, so cancellation does not send a failure notification. func (s *VerificationScheduler) cancelAutomaticVerificationsForDisabledSchedules( ctx context.Context, logger *slog.Logger, ) error { rows, err : s.repo.GetNonTerminalAutomaticVerificationsForDisabledSchedules() // ... for _, row : range rows { s.repo.MarkTerminal(nil, row.ID, VerificationStatusCanceled, map[string]any{ fail_message: cancelMessageScheduleDisabled, }) } }这里有两个可复用的命名原则来自 tasks.md 2.2 与 design.md旧名sweepCanceledByDisabledConfig的问题sweep Canceled暗示处理已取消的行与实际执行的把行变成CANCELED这一状态迁移相反Config也无法指认是哪个配置项在控制该迁移。新名cancelAutomaticVerificationsForDisabledSchedules直接描述了对禁用调度的自动验证执行取消这一动作仓库方法用Get而非Find项目约定中仓库方法取回的是一个定义明确的集合故用Get前缀且不保留Find旧名别名。另外注意方法上方的注释禁用调度是用户主动行为因此取消不发送失败通知取消原因使用常量cancelMessageScheduleDisabledverification canceled: its verification schedule was disabled定义于 service.go#L787保持取消理由的可追溯性。任务主线三最终验证Final verificationtasks.md 第三节给出交付前的三道闸门全部为可执行的仓库命令包级测试cd backend go test ./internal/features/verification/runs -count1要求解决一切意外失败——这既覆盖新增的取消清理回归用例也保护Test_CreateScheduledRuns_*、Test_ReapStaleRuns_*等既有调度器行为不被回归破坏。静态检查cd backend make lint重构类改动全量改名、调用方更新最容易留下未使用别名、陈旧注释等 lint 问题此项确保改名在backend/内无残留。强制评审对实现 diff 运行项目规定的 reviewer解决所有CHANGES REQUIRED结论使工作树达到可直接提交的PASS状态。三道闸门分别对应行为正确性代码整洁性评审合规性与项目AGENTS.md与backend/AGENTS.md中关于命名、controller 后盾测试、格式化和强制评审的规则一致。变更边界与风险从源码结构看结合 design.md 与当前源码可以确认本次变更的边界控制得很紧不改入队与执行路径手动验证的创建授权检查 备份可用性检查后落一条PENDING记录与 Agent 认领、心跳回收、重试逻辑均未改动scheduler.go 中createScheduledRuns只遍历启用的配置reapStaleRuns只处理RUNNING与超时的PENDING行取消动作不参与这两条路径不新增配置项手动验证独立于自动调度开关是产品语义而非开关若额外加一个配置标志会制造第二套事实来源design.md 明确否决无迁移、可回滚不改 schema 与存量数据回滚即还原查询谓词存量验证行无需转换残留风险取消语义从此与持久化的 trigger 取值绑定——从源码结构看restore_verifications表的trigger字段取值集合MANUAL/SCHEDULED/AFTER_BACKUP就是手动/自动区分的唯一依据白名单过滤没有引入新的耦合但要求未来新增触发类型时同步评审取消选择。小结一次用命名与谓词固化规则的回归修复这次变更的价值不在于多了一行 SQL 条件而在于把一条隐式的业务规则——禁用调度只影响自动验证不影响手动验证——同时固化在了三个可审计的位置仓库查询的白名单谓词trigger IN (SCHEDULED,AFTER_BACKUP)、描述状态迁移的函数命名cancelAutomaticVerificationsForDisabledSchedules、以及五个覆盖 PENDING/RUNNING × 手动/自动/共存的回归用例。读者若要在自己的调度系统中处理类似按配置开关清理后台任务的场景这套选择规则下沉到查询、动作按执行的迁移命名、测试直接调用动作并断言对外可见状态的模式可以直接参照。赞分享数据库灾备【免费下载链接】databasusPostgreSQL backup tool with Point-In-Time-Recovery and restore verification项目地址https://gitcode.com/gh_mirrors/po/databasus点击查看免费下载相关推荐DataBasus 验证调度器实现解析定时验证关闭时如何保留手动备份验证不被误取消DataBasus 验证调度器实现解析定时验证关闭时如何保留手动备份验证不被误取消 DataBasus 支持对 PostgreSQL/MySQL/Maria数据库灾备Databasus 备份验证设计解析让手动验证独立于自动调度取消清扫只瞄准自动触发的运行Databasus 备份验证设计解析让手动验证独立于自动调度取消清扫只瞄准自动触发的运行 本文基于 Databasus 仓库中已归档的变更记录 allow数据库灾备Cleave.js 设计决策为什么不支持实时表单验证Cleave.js 设计决策为什么不支持实时表单验证 你是否曾在开发表单时遇到这样的困境引入了文本格式化库却还要额外加载验证插件Cleave.js作为一前端上一篇RimWorld游戏优化终极指南Performance Fish性能加速与卡顿解决全方案下一篇系统资源释放大师ProcessCleaner高效清理后台进程指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考