17 KiB
17 KiB
SQLite cleanup v0.1 本地迭代记录
范围与状态
- 开发分支:
feat/sqlite-cleanup-v0.1;首期本地开发及复审根因修复完成;修复后完整make check、覆盖率和Python测试通过,最终干净制品检查记录见文末。 - 用户确认:仅本项目内部数据保留周期调整,不新增
execution_id,源event_id(包括 numberID)原样回传;SaaS 如何处理再次返回的同 ID 结果不在范围内。 - 初轮固定
ef3009d。复审后用户明确批准仅必要一句文字及共享发布,7b4448f3586104cde91509a5d5951575c37a8b2c已发布并固定本项目引用,43个JSON和8项合同检查通过;Schema、接口字段、消息类型、路由不变。 - 没有合入或推送本项目 main、部署、操作现存运行数据库/恢复目录、退役主机
.approved、拨号、抓包或调用真实 AI/OSS。
已完成的分批验证
Agent 永久标记退役(f07bf90)
- 先新增并运行反例,原实现因创建
.approved、依赖旧标记及完成后不允许重用而失败;删除相关生产读写代码后通过。 - 验证同身份活动期间不能重叠执行,结束后可再次执行;旧
.approved文件/目录不读取、不改写、不删除,新运行不重建该目录。 - 仅在临时目录验证私密备份字节、长度和 SHA-256 一致后删除准确标记路径,相邻会话、
.results、.executions、录音、上传恢复、锁及 Dispatcher 数据均保留。 go test -race ./internal/rpc ./internal/agent ./internal/store ./internal/dispatcher通过。
SQLite 实时清理
- 新增测试先因缺少清理入口失败,实现后全部通过。
- 已派发呼叫需要已确认终结、通过现有结果 RPC 验证后持久提交的结果,以及派发回执、最终结果各自的 MQ publisher confirm。结果提交之后没有额外可能失败的业务验收步骤;不增加第二次 Agent 确认,不把 RPC 响应的网络到达或 MQ confirm 当作 SaaS 应用收讫。
- 删除事务重新检查类型、源 ID、归属、号码、线路、冻结快照及上传结果;矛盾证据保留并报错。SQLite 结构仍为 4,没有新表或迁移。
- 未发起拒绝仅清理已确认拒绝;原始拒绝文件仍须由后续文件收尾步骤保护其回执。活动、pending、dispatching、dispatched、unknown、任一确认缺失均保留。
- stopped 的取消记录逐条事务、分批处理;单条失败不阻止其他记录,停止回执到剩余取消/待拨记录清完后才删,任务停止状态不删。205 条取消记录的批次、取消中断和 SQL 故障恢复测试通过。
- 持有待拨指令或原派发调用期间排除清理;重新核对缓冲指令,停止/删除/替换后的旧批次不再拨号。极速终结与原派发返回并发时,先完成原调用再清理。
- MQ publisher confirm 后触发清理;清理故障记录身份与原因,不作为业务准入故障返回。
- 原
event_id清理后可再次接纳、执行和回传;只删除本通数据,共享配置和任务状态保留。报告的是删除的逻辑行/正文字节,不声称 SQLite 文件立即变小。 go test -race ./internal/store ./internal/dispatcher ./internal/rpc通过。
已交付录音文件
- 先添加反例:原逻辑不能读取音频已删但
info.json仍为 delivered 的合法中间状态,且不会删除已交付文件;实现后通过。 - 仅持久 delivered、上传成功回执和原身份/长度/校验和等信息有效、且原事件无未完成
.results引用时删除。prepared、ready、end_pending 引用都保留原恢复文件,引用完成后可以继续收尾。 - 删除前先把原 delivered 信息原样持久保存至私有
.recording-cleanup临时副本;依次删除本条recording.wav、同步目录、删除info.json、同步并删除准确且空的叶目录,同步父目录后才删副本。共享父目录、.results、未知侧文件/空目录与 OSS 对象不删除;返回错误及硬退出均保留原信息或副本,下次启动只补删除,不申请授权、PUT 或重报。 - delivered 且原音频已经缺失时,只放行这一已确认删除的中间状态;其他状态缺音频仍报错。原校验和严格保持有效的小写 SHA-256,上传回执、长度和身份校验不弱化。
- 同一录音跨不同 recovery 实例使用临时按路径互斥;结果引用写入/确认与删除协调,锁使用结束即移除,不形成永久身份历史。并发实例仍只有一次 PUT、一次回报;完成后不存在该记录,后续直接调用明确返回不存在而非虚构已完成历史。
- 既有恢复扫描能续处理 delivered 中间状态,避免清理后同次遍历把已删除音频误报成孤立文件;单条坏目录不妨碍其他合法记录。没有新增十秒全目录清理任务,既有恢复调度保持原用途。
- 信息/目录删除失败后重启、未完成引用、无音频的坏回执、未知文件、跨实例并发及互斥清退测试通过;
go test -race ./internal/agent ./internal/rpc ./cmd/sip-go-agent通过。
已确认拒绝原始文件
- 新增资格/事务/文件失败反例后实现。call.execute、task.control、sip.config 结构拒绝须有对应 typed publisher confirm;无回执、未确认、非拒绝及已接纳执行的冲突不会删原始文件。
- 按接收 Dispatcher、原类型/ID、租户及完整回执字节关联,验证原消息身份、记录结构、私有普通文件和完整记录 SHA-256。关联或内容冲突保留本组原件及完成依据。
- 新文件名仅增加回执正文 SHA-256 前缀,保证即使本条记录无法解析也能保留正确回执、而不阻止独立组;这是内部磁盘索引,不新增业务编号或协议字段。现有仅记录 SHA-256 命名的文件仍以完整内容验证,不改写或迁移;旧文件若连关联身份也无法读取,保留文件及潜在完成依据,日志明确要求人工核验,不猜测删除。
- 一回执多原件先逐条删除并同步目录,全部完成后才删回执;文件删除半途失败和原件删完后回执事务失败都能补收尾。未生成回执的孤立原件、未确认组、未知名称和既存 .pending 临时文件不删。
- RejectData 写入和清理共享生命周期排除;清理结束后同源再来的新拒绝保留新原件和未确认回执,不误删为旧记录。移除了此前 admitted rejected 的“只要整个拒绝目录非空就保留”保护,改为精确本组资格。
- MQ 确认后的真实控制器入口已验证三类拒绝,未产生执行或伪造最终结果;多原件、两阶段失败、损坏组与独立组、既有文件、未知临时文件和并发写入回归通过。
go test -race ./internal/store ./internal/dispatcher ./internal/rpc通过。
每日午夜补扫
- 采用固定 Asia/Shanghai 日历边界,启动只安排下一次午夜,不在启动时额外清理、不在 12:00 运行、不按消息年龄删除;每次重新计算下一日期。系统时钟回退不会提前执行,清理失败等待下一午夜,不形成高频重试。
- Dispatcher 使用独立且可取消的后台任务,分页扫描 completed 候选并复用 MQ 确认后相同的逐条事务/原件资格;单条失败继续其他记录,不变更准入、任务状态、停止状态或发布消息。停服取消并等待清理任务结束。
- 配置录音恢复根目录的 Agent 启动独立午夜任务,复用已有扫描和 delivered 删除;其他状态只校验保留,不申请授权、PUT 或上报结果。既有十秒真实恢复的用途和节奏不变。
- 每条日志记录身份、保留原因或错误、实际文件数量与字节;Dispatcher 汇总扫描、保留、失败、删除行、逻辑数据字节、文件数量/字节及耗时。没有永久扫描进度或二次确认记录。
- UTC/上海转换、12:00 不清理、午夜启动安排次日、时钟回退、失败等待次日、取消计时器,以及 205 条跨页候选、未确认/待拨邻居保留、取消后续处理、只清 delivered 不重试其他录音验证通过。
go test -race ./internal/daily ./internal/store ./internal/dispatcher ./internal/agent ./cmd/sip-go-agent通过。
初轮固定提交验证(复审修复前的历史记录)
make check:格式、合同固定引用/43 JSON及8合同测试、Proto来源、go vet ./...、go test -race ./...、二进制构建及隔离 MQ 检查通过。make release-check-local:在干净固定代码提交afa4fe2重新通过,source dirty=False、production_approval=False;制品 SHA-256 为e03c42d8f6b7b2cfd6c95e810c4ec1461b2f06d515b1f53c17719a1c7b9978ac,合同固定ef3009df3a90f6e941ca0b24e46134aef17a374d。同提交make check和make coverage重新通过,业务覆盖率72.9%。此制品及覆盖率属于复审修复前,不能作为修复后最终代码的制品证据,也不将本地制品批准为生产。- 实际运行的隔离 RabbitMQ + HTTPS + gRPC mTLS 端到端通过。更新旧“完成后永不重用”断言:收到原 ID 最终结果、两个消息类型分别确认、本地清理后,再通过 MQ 投递同一源 ID,Agent 再次接纳且 ID 不变。没有以孤立单元测试代替 MQ/HTTPS/mTLS 运行事实。
- 业务覆盖率 72.9%(新增纯测试后复核),高于 65%;Python生产部署 26 项、脚本 9 项通过。
- SQLite增长:4轮各40通、同源 numberID 重用及重启,完成后 inbox/outbox/recordings 都为0,共享task/config仍各1;预热后 page_count 不继续增长,不执行 VACUUM、不要求数据库文件立即缩小。
- 录音/拒绝文件增长:各3轮×20条重复身份,完成后原件/回执或录音叶目录不存在;保留共享目录,不留
.approved或内存永久完成身份历史。 - 没有修改部署主机或现有运行数据库/文件,未 main 合入/推送、部署、重置、迁移、拨号、抓包、实际 AI/OSS 调用或 OSS 对象删除。SaaS收到、判重、覆盖和真实通话/生产验收不在本次范围。
复审根因修复
- 独立审核发现初轮 info 删除后、空叶删除前的硬退出窗口没有依据;不是普通删除返回错误。新增子进程
os.Exit(23)先复现:info 删除后空叶仍留存。修复后音频、info、叶、副本四个实际删除边界 × 启动/午夜两入口均通过;无 defer、恢复信息回写或有序退出掩盖窗口。 .recording-cleanup/<原bucket/objectKey路径SHA>.json仅是现有 delivered 信息的私有临时副本,不是外部 ID、二次确认或永久完成历史。副本在删除任一原文件前持久保存;空叶 durably gone 后才删副本。没有根据前缀或“空目录”推测完成,读取原 delivered 身份/上传回执/长度/校验和并校验精确副本路径。- 副本缺失/损坏/身份冲突/错名/非delivered/假上传回执不能清原件;原副本持久化失败时音频/info都保留。info已删只允许从有效副本续处理,且音频必须已不存在;其他缺失/损坏仍报错。
- 空叶已删、副本删除失败时仍保留依据;同OSS目标新恢复写入明确拒绝,避免旧副本误删新记录。独立合法记录照常清理,下一实例重试最终只删副本,目标随后可复用;副本清完不留完成文件。
go test -race ./contracts ./internal/agent通过。contracts/cleanup_scope_test.go固定文字测试保留原值/tuple/尚未清理的防重规则;机器Schema无改动。
修复后全量检查
make check重新通过,含格式、固定合同43 JSON及8测试、Proto、vet、全量race、构建和实际隔离RabbitMQ/HTTPS/mTLS;新合同范围回归与四个删除边界硬退出的启动/午夜续收尾均包含在全量测试中。make coverage:业务覆盖率 73.0%。生产Python 26 项、脚本Python 9 项均重新通过。日志/tmp/go-sip-cleanup-audit-final-{check,coverage,python,script-tests}.log。- 两项审核缺口均有对应根因修复及测试,不以普通返回错误模拟硬退出,不忽略共享首次事实的必要文字。
SaaS开发同步说明(不等待外部适配)
共享版本:7b4448f3586104cde91509a5d5951575c37a8b2c。仅把“同类型同身份保留首次事实”明确为 Dispatcher 本地执行/回执仍保留期间;完成且按条件清理后,同源 event_id 可再次执行,回执/结果仍原值,不增加 execution_id。接口字段、Schema、类型、路由不变。此项不规定 SaaS 重复结果接收/判重/覆盖/区分规则,也不以 SaaS 处理或验收为开发条件;本说明供开发同步,不声称对方已收到、正确处理或完成适配。
计划验收逐项对应
| 项目 | 本地证据 |
|---|---|
| finished需结果成功与派发/最终结果各自confirm;任一缺失保留 | store/cleanup_test.go、dispatcher/cleanup_test.go及隔离runtime集成 |
| rejected需正式未发起拒绝confirm,不要求不存在的最终结果 | store/cleanup_test.go、rpc definitive-no-dial及原有占用释放回归 |
| suppressed需durable stopped和成功stop confirm | store/cleanup_control_test.go:205条、单条SQL故障、取消中断及补收尾 |
| Stop回执后删;停止状态/共享配置/未决/unknown保留 | store清理/占用恢复、dispatcher缓冲旧批次/并发派发及既有恢复测试 |
| .approved不生成;活动并发仍受保护 | rpc/approved_retirement_test.go:活动重叠拒绝、结束/重启后重用、旧标记不读改 |
| 已存主机.approved受控退役 | 仅临时目录验证私密备份bytes/size/SHA和相邻边界;主机操作范围外未执行 |
| 音频删、delivered info仍在时续处理;其他状态缺音频报错 | agent/recording_cleanup_test.go,信息/叶目录失败和坏SHA,重启不PUT/report |
| 未完成.results引用、未知侧文件/坏记录保留,独立记录继续 | agent录音清理/扫描及全量结果日志回归;临时锁释放和跨实例一次PUT |
| 原始拒绝准确关联;一回执多文件;孤立/未确认不删 | store/cleanup_rejected_test.go,完整回执/身份/内容/文件索引证明 |
| 两阶段删除失败/并发新捕获不会提前清回执 | 原件半途失败、回执SQL触发器失败、capture-race及独立坏组回归 |
| .results正常成功收尾、SIP来源、既有临时行为不退化 | 全量agent/result_journal、store/sip_source及cmd/rpc回归;未知.pending保持 |
| 实时与午夜同条件;0点非12点;故障/取消不关准入 | daily/midnight_test.go、dispatcher/cleanup_scan_test.go、Agent delivered-only回归 |
| 同源ID原值重用,不新增字段,不验证SaaS重复处理 | controller单元与隔离MQ最终结果/再次执行;Schema/Proto均未改,submodule仅获批文字更新 |
A01–A12 / K01–K16 范围核对
- A01–A03、K01–K02:固定共享合同、来源检查、事件身份及入站/出站边界由本次完整检查和现行Schema回归核验;不另复制或修改运行契约。
- A04–A06、K03–K10:HTTP完整配置、任务控制优先级、租户/任务/线路占用、停止/缓冲并发、publisher confirm及未决重启保护由全量回归及实际隔离MQ/HTTPS/mTLS核验;已完成数据只在本地条件满足后释放记录。
- A07–A09、K11–K14:Agent会话/原值派发、执行终结、上传绑定/未知PUT/恢复与结果交付由rpc/agent/store回归核验;本次只清理成功delivered,不扩大重试或真实云授权。
- A10–A12、K15–K16:可观测性、构建制品、本地门禁和单节点边界检查通过;真实SaaS/management、真实通话/AI/OSS、ECS、容量、多节点/租户及生产签收不适用且未宣称通过。
最终干净固定源码证据
- 复审修复提交
1068188;补齐目录同步失败后再尝试的持久性检查2fd883a。固定代码2fd883a的干净工作区重新执行make check、make coverage、make release-check-local全部通过,业务覆盖率 73.0%;Python 26+9 已通过且未再改Python。 - 录音临时副本不仅校验存在:每次删除前都重新同步其命名空间/父目录,保证前次 rename 或目录同步失败后重试仍有持久完成依据。没有把本进程看到文件当作已持久成功。
- 制品 SHA-256:
5524a995fceaae73d8a4fab430c77785c926c82bda8ae15c9678726fd1fc5403;固定共享合同7b4448f3586104cde91509a5d5951575c37a8b2c;验证清单 SHA-256150a4753f52df87e617140dbaf12c25d77e5734ad3e713b7109d59ebf40cf2c9。source dirty=False、production approved=False。 - 最终日志:
/tmp/go-sip-cleanup-final-accepted-{check,coverage,release}.log;硬退出先失败日志/tmp/go-sip-cleanup-hard-exit-red.log,修复后全量race含四删除边界×两入口与副本损坏/保留/隔离/复用测试。 - 本节之后仅提交证据文档,不改变已验证代码或合同。未推送/合入本项目 main,未部署或操作真实运行数据;共享发布仅限用户批准的一句文字。