防复发:把「删数据集带走站点自建数据」做成结构性门禁 + 常驻体检
用户放弃继续救那批旧图,要求的是「别再发生同类事件」。所以不靠记性,靠结构:
1) 归属铁律(写进 schema.sql 抬头 + README 新章节)
判断标准只有一句:**这份记录能不能从备份重新导入?**
能(places/visits/movements/weather/activities/tags/entity_raw)⇒ 可挂
`REFERENCES datasets(id) ON DELETE CASCADE`;
不能(place_images/place_notes/place_votes/topics)⇒ 只留 dataset_id 当出处、**不许挂外键**。
2) 两道门禁(dataset_ownership_test.go),都做了变异验证:
- 运行时:查 pg_constraint,凡挂 datasets 的表必须在白名单里;**反向也查**
(白名单里的表不许被顺手摘掉,否则删数据集会留成片孤儿行)。
- 静态:扫 schema.sql 的 CREATE TABLE。只看运行时有盲点——新建的库走 CREATE TABLE,
开发库可能压根没跑过那次迁移。变异(把 topics 的 CASCADE 补回去)当场红。
- 变异验证顺带发现:扫描必须先跳过 `--` 注释行,规矩的说明文字里就写着
`REFERENCES datasets(id)`,不跳过会把自己写的文档当成违规。
- 还发现运行时那道单独看**不够**:夹具每次跑迁移,迁移自己就把坏外键摘了,
它永远不会在不健康的库上报警 ⇒ 补了「注入事故原样的外键再跑迁移,断言被摘掉」
的自愈用例(并先确认变异真的生效,防假绿)。
3) 常驻体检:后台首页显示「库里 N 张 / 本地盘上 M 个 / 落单 K 个」,落单 >0 直接报警。
事故的本质不是「删数据集」本身,而是**行与对象悄悄对不上、没人发现**,等照片看不见了才追。
自愈用例又抓出一个此前漏掉的缺口:place_notes / place_votes 上的同类外键迁移并不会摘
(原先只写了 place_images 与 topics 两句 DROP)⇒ 补成五张自建数据表全覆盖。
⚠️ 排序坑(本项目第二次踩):摘外键那段最初放在 place_images 建表**之前**,
开发库毫无症状、**全新库起不来**(ALTER 报「关系不存在」),被
TestFreshDatabaseServesAppQueries 抓住。整段已挪到 place_images 之后,并把坑写进注释。
顺带订正「删除数据集」的二次确认文案(专题改完之后它还在说专题会一起删)。
全量验收 PASS=336 FAIL=0 SKIP=0。
This commit is contained in:
@@ -112,6 +112,16 @@
|
||||
而图片文件还留在磁盘里。点这里按坐标把它们挂回去(假如图片属于旧数据集,先别删它的底座文件——
|
||||
认地点要用它)。现在这版已经不会再有这个问题了。
|
||||
</div>
|
||||
<div class="card-sub" style="margin-top:10px">
|
||||
体检:库里 <b>{{num .ImgRows}}</b> 张 · 本地盘上 <b>{{num .ImgObjects}}</b> 个{{if gt .ImgOrphans 0}}
|
||||
· <b style="color:#b42318">落单 {{num .ImgOrphans}} 个</b>{{end}}
|
||||
</div>
|
||||
{{if gt .ImgOrphans 0}}
|
||||
<div class="alert err">
|
||||
有 <b>{{num .ImgOrphans}}</b> 个图片文件在库里没有记录——它们现在谁也看不到。
|
||||
点「扫描并恢复」按坐标挂回去(对象存储上的也会一并扫,需要 s3:ListBucket 权限)。
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
@@ -162,7 +172,7 @@
|
||||
</form>
|
||||
{{end}}
|
||||
<form method="post" action="/admin/datasets/{{.ID}}/delete" style="display:inline"
|
||||
onsubmit="return confirm('删除后该数据集的到访、地点、位移、原始行留档都会从数据库移除,且不可恢复;挂在它下面的专题也会一起删掉(备注、结论、图片按坐标键保留,不受影响)。确认删除?')">
|
||||
onsubmit="return confirm('删除后这份数据集的到访、地点、位移、天气、活动、标签、原始行留档都会从数据库移除,且不可恢复(重新上传同一份备份可以再导回来)。你在站点上自建的备注、结论、地点图片、专题都不受影响,会按坐标键 / 按人保留。确认删除?')">
|
||||
<button class="btn sm danger" type="submit">删除</button>
|
||||
</form>
|
||||
</td>
|
||||
|
||||
Reference in New Issue
Block a user