Skip to content

v0.3.3

Latest

Choose a tag to compare

@github-actions github-actions released this 12 Aug 02:35
· 7 commits to master since this release

v0.3.3 —— 一个任务不再能拖垮其他任务;缺瓦片不再静默;区域可以导入、成果可以导出成 MBTiles

先说结论:这一版补的是「多任务同时跑」和「结果不完整」两个长期靠运气的地方 —— 现在四条管线共用一份全局并发与磁盘预算,缺瓦片会被分类记账并在界面上要你拍板,区域可以直接导入 GeoJSON / KML / KMZ / Shapefile,瓦片成果可以导出成单个 .mbtiles 文件。已下载的数据、已切好的地形、配置与历史全部照旧,不必重做任何东西。 升级后首次启动会做一次自动迁移(改缓存目录名、改一列历史状态值),不需要你做任何事,但装回旧版会让缓存全部落空——这一条在下面「升级须知」里说清楚。

一个任务不再能把其它任务拖垮

  • 以前四条管线(瓦片 / 高程 / 地形 / 等高线)各管各的并发:配置里的「并发下载数」是每个任务的数字,同时跑两个任务就是两倍连接、两倍内存、两倍磁盘写入,没有任何上限。现在多了一层全局预算,四条管线一起排队。
  • 配置页新增五项:同时运行的任务数(出厂 2)、全局网络连接上限(64)、CPU 工作线程(0 = 按机器 CPU 数自己算)、GDAL 并发槽位(2)、缓存总容量上限(0 = 不限,与旧行为一致)。原来的「并发下载数」照旧存在,但它现在会被全局上限压住 —— 两个任务各填 50,实际不会开出 100 条连接。
  • 出厂值是保守的。机器好、网络快,把「同时运行的任务数」和「全局网络连接上限」调高即可;这些是可配置的默认值,不是硬限制。

磁盘:先估算,再开工,跑到一半空间不够也能安全停下

  • 建任务时会先估这一单要占多少(瓦片、临时文件、拼接产物分别算),减去磁盘预留(出厂 2 GB)再乘一个安全系数(出厂 1.15),不够就直接拦住并告诉你差多少 —— 而不是跑到 80% 时写失败。
  • 估算不再用固定的「平均一张瓦片多少 KB」,而是拿你磁盘上已有的瓦片现量。同类工具在这一点上出过 17 倍的偏差,那个坑的成因就是固定均值。
  • 临时/工作目录现在跟着输出盘走,不再固定用系统临时目录。跨盘意味着每一次拼接都要把数据完整搬一遍。
  • 觉得估算过于保守?配置页里有开关可以整个关掉(磁盘预算检查)。

缺瓦片不再静默:分类记账 + 由你拍板

  • 以前一张瓦片取不到就只是「失败」一个词。现在分五类记账:成功 / 该处本来就没有数据 / 可重试的失败 / 永久失败 / 缓存写入失败
  • 由此多出三个任务状态:补漏中待决策已完成(有缺口)。规则只有一条,值得记住:
    • 只有「该处本来就没有数据」这一类缺口 —— 比如你框到了大洋深处、或者框出了高程数据集的覆盖范围 —— 任务自动完成,状态是「已完成(有缺口)」,不打扰你。
    • 出现任何一类真失败,任务停在待决策不会给你一张残缺的拼接图。你可以点「补漏」只重跑那些格子,也可以点「接受缺口」让它按现状出图 —— 后者出的成果和历史记录会永久带缺块标记,不会伪装成完整成品。
  • 补漏可以反复点,重复点不会重复下载。
  • 任务详情里能看到缺口的分类计数和最多 20 个样例格子(层级 / 行列号 / 失败原因)。

每个任务一份自己的日志,出问题可以直接导出

  • 以前排障只有一份全局日志,多任务并行时几条管线的输出交织在一起。现在每个任务写一份 logs/tasks/<管线>_<任务号>.log,任务详情里能直接看,也能下载一份诊断文本
  • 日志里的密码和 Token 在落盘前就被抹掉了 —— 这份文件设计上就是可以直接贴进 issue 的。
  • 出厂单份上限 4 MB、保留 14 天,超期的在启动时自动清掉。不想要就在配置里关掉。

删任务不再误伤别的任务的缓存

  • 以前删任务时清缓存是按样式整片清的:两个任务框的范围有重叠,删掉其中一个,另一个下次恢复要重新下载重叠的那部分。现在只清这个任务独占的那些格子,别人还用得着的一张不动。
  • 配置页的缓存管理多了两项:按来源命名空间看占用(见下),以及一键清理「没有任何任务认领」的孤儿缓存。

区域输入:可以导入文件了,也能按地名搜

  • 除了在地图上拉框,现在可以直接导入 GeoJSON / KML / KMZ / Shapefile(.zip),支持多边形、多部件与孔洞(挖空的部分不会被下载)。
  • 跨 180° 经线的区域从「报错拒绝」改成「自动拆成两段」。以前这种范围要么被拦下、要么被算成绕地球一圈。
  • 地名搜索需要你自己填一个服务地址才会出现 —— 出厂是空的,程序不内置任何地名服务,理由见下面「这一版刻意没做什么」。

瓦片成果可以打包成单个 .mbtiles

  • 一个 .mbtiles 就是一个文件,里面装着整棵瓦片金字塔 —— 拷给别人、丢进 QGIS / ArcGIS,不用再搬几十万个小文件。影像和等高线用的是同一套写入端。
  • 两个入口,随你用哪个:建任务时在「输出格式」旁边勾上**「同时导出 MBTiles」,跑完自动打包;或者对已经跑完的任务**事后点一次导出。
  • 这是「多给一份产物」,不是「换一种输出格式」。 输出格式的三个选项(只要瓦片 / 只要拼接图 / 两个都要)一个没变,勾了 MBTiles 也不会删掉原来的瓦片目录 —— 那个目录正是打包的原料,也是程序里预览用的那份。同一个任务可以同时留着瓦片目录、拼接图和 .mbtiles
  • 打包出来的库可以直接在本程序里预览(/mbtiles/...)。
  • 打包失败不会把一个已经下载完的任务判成失败 —— 瓦片已经在盘上了,重新点一次导出即可。
  • 有缺口的任务打包时会带缺块标记,不会假装完整。

图源向导

  • 配置页里粘一条瓦片服务地址,程序会替你认出模板形态({z}/{x}/{y}{s} 子域、TMS 行号方向、查询参数),并指出可疑的地方,而不是让你手工拼一遍格式再靠试错。

升级须知(五条,都不需要你动手,但请读一下)

  1. 缓存目录改名了。cache/<样式>/… 改成 cache/<样式>-<源指纹>/…,例如 cache/s/…cache/s-3f8a1c2d/…。首次启动自动改名,是重命名不是重新下载,一张瓦片都不会丢。改这个是因为原来的目录名只认样式不认服务器:同一个「卫星」样式换了服务器列表之后,新旧两家的瓦片会混进同一个成品,而且事后无从分辨。注意:改名之后如果你把程序装回旧版本,旧版会按老目录名去找,结果是缓存全部落空、全部重新下载(数据不会损坏,只是白下一遍)。
  2. 历史任务里的瓦片状态值改了写法。 数据库里旧的 failed 会被改写成 retryable_failure(可重试的失败)—— 这是保守的读法,意味着这些格子仍然可以用「补漏」重跑。一次性迁移,自动完成。
  3. 多了三个任务状态。 如果你有自己写的脚本在读任务接口,注意 status 现在还可能是 retrying / pending_decision / completed_with_gaps。把它们当成「未结束 / 未结束 / 已结束」处理即可。
  4. 只影响直接调 API 的人:删除本地地形任务的 delete_files 默认值从「删」改成「不删」。 DELETE /api/terrain/local/tasks/<id> 此前不带参数时默认连磁盘产物一起删,而另外三条管线的同名接口默认都是保留。四条现在统一为默认保留,要删就显式带 ?delete_files=true(这个写法一直有效,没有变)。界面上的删除按钮不受影响 —— 它一直是显式带着这个参数发的,你在界面上看到和勾选的行为与上一版完全一样。会受影响的只有自己写脚本、依赖了那个隐式「默认删」的人:同样的请求现在会把文件留在盘上。改的只有 HTTP 这一层LocalTerrainTaskManager.delete_task 自己的签名默认值仍然是 True,从代码里直接调它的地方行为一个字没变。
  5. 只影响直接调 API 的人:POST /api/dem/tasks 多了一种写区域的方式。 老的 north/south/east/west 四至照旧可用,没有废弃;新增的 region 字段(一个 RegionSpec)与它二选一,给了 region 就不必再给四至。跨 180° 经线的 DEM 任务只能用 region —— 裸四至那条路对 east <= west 一律回 400,那道校验是有意保留的(它挡的是「填反了四至」这个高频错误)。另外 DELETE /api/tasks/<id> 新增可选的 ?clear_cache=1,带上它会顺带清掉只被这个任务引用的共享缓存,响应里多出 cache_removed_bytes / cache_removed_files / cache_deferred 三个字段;不带就是旧行为。

这一版刻意没做什么(写出来是为了让你不用去找)

  • 不内置地名 / 行政区搜索的数据源。 功能本身做好了,但 地名服务地址 出厂是空的,你不填就不会在界面上出现。原因有两条:公共地名服务(如 OSM Nominatim)都有明确的批量使用政策,程序替你内置一个等于替你接受了那份政策;中国境内的行政区数据还叠着测绘资质的要求。这两件都不是工程能替用户决定的事。要用就自己填一个 Nominatim 兼容的地址,程序会把它当作不可信的外部 URL 做安全校验后再请求。(依据:docs/notes/external-projects-takeaways.md §11「不内置未经政策审核的公共或商业批量下载源」,以及 §13 末尾把「行政区与地名搜索的数据源与测绘合规」列为仍待产品层决定。)
  • 没有安装包,仍然是解压即用。 不做 MSI / DMG / DEB,也没有自动更新(§13-6 的决定)。自动更新的前置条件是签名清单、资产哈希与代码签名,一样都还不具备 —— 与其做一个「从某个地址下载 exe 然后直接执行」的更新器,不如不做。
  • 没有任何遥测、埋点或使用统计。 一行都没有,将来也不打算加(§11)。程序除了你自己配置的图源、高程源与代理之外不连接任何服务器。
  • 可选数据插件(Wayback / MVT / OSM 矢量 / 3D Tiles)一行未写。 那是下一阶段的事,插件契约都还没定稿。

给排障和构建的人

  • 新增合同层 src/contracts/region / region_tiles / source / outcome / artifact / reservation)。region_tiles.py 是全仓唯一一处经纬度↔瓦片换算 —— 估算、下载、拼接、MBTiles 四至与界面预览共用它,「预览说的张数」和「实际切的张数」因此不会再各算各的。
  • 新增服务:resource_scheduler / disk_budget / task_logging / cache_exclusive / source_registry / mbtiles / artifact_export / region_import / url_guard / source_wizard / geocoding / artifact_store。架构说明、配置键含义与状态机规则都写进了 CLAUDE.md
  • 数据库 user_version 推到 6:5 = task_tiles.statusfailedretryable_failure,6 = 缓存目录改名。两条都是幂等的一次性迁移。新增 artifacts 表,tasks 新增 export_mbtiles 列(与 output_format 正交,见下条)。
  • MBTiles 是「多一份产物」而不是第四种 output_format OutputFormat 一个值没加;打包由独立的布尔列 tasks.export_mbtiles 驱动,打包器只有一处 src/services/artifact_export.pyexport_task_mbtiles 幂等,按管线查一张布局表,同时覆盖影像与等高线)。做成第四种格式会删掉打包的原料目录 —— 而那个目录正是 /tiles/<id>/ 预览用的那份。
  • MBTiles 对外只有两条路由:读走 /mbtiles/<管线>/<任务号>/<z>/<x>/<y>.<扩展名>(影像、等高线与将来的矢量共用,刻意不按数据类型各开一条,它同时登记进 5001 瓦片端口的路径白名单,前后端两份名单由一条相等性断言钉死);写走 POST /api/export/<管线>/<任务号>,管线名对着 contracts.artifact.PIPELINES 校验。
  • 日志尾随走 REST 轮询,不走 Socket.IO。 本应用没有 room / namespace,任何 emit 都会发给所有连着的客户端,逐行日志事件等于把一个任务的日志广播给所有人。新增的 socket 事件只有一个:task_gap_decision
  • CI 三项新门禁:pytest-cov 覆盖率地板 --cov-fail-under=55棘轮起步值,只准往上调)、tag 与 Config.APP_VERSION 的一致性检查、发布产物的 SHA-256 清单(随包挂在 Release 上,生成后立刻自校验)。
  • 高程/地形的规模预告修了两处:速度档下超高分辨率源的最大层级此前少报一级(层级偏移被加在上限截断之后,而实际切片是在之后才截断的);跨 180° 经线的栅格张数此前少报约六成。/api/raster/inspect 因此在每个文件与汇总节点上都多返回一个 recommended_maxzoom_by_quality(三档 → 实际会切到的层级),recommended_maxzoom 本身没变。

验证

  • 本节没有全量测试的通过数 —— 发版时由跑完整套件的那一步填。这里只写已经机器核对过的事实,不给一个编出来的数字。
  • 已机器核对:src/routes/ 里的 71 条路由与本仓 README「API 端点」一节双向逐条对上(多一条、少一条都会让 tests/test_docs_claims.py 变红);README 项目结构树里列的每一个仓内路径都真的存在;两个 CI workflow 里 python -m pytest tests/ 仍然是字面子串且仍排在 python nuitka_build.py 之前;新增的界面文案中英双语齐全、占位符两边一致。
  • 打包不需要为新模块加任何 Nuitka 参数,这一条是核对出来的不是猜的:从 app.py 出发对 src/ 做了一次导入图可达性遍历,src/contracts/ 与全部新服务都静态可达(含几处函数体内的 import —— 模块名是编译期常量,静态分析跟得住)。理由与链路记在 nuitka_build.py 的注释里。
  • 没有做的:三平台产物的实机冒烟由 CI 在发版时跑;本轮没有做「快了多少 / 省了多少磁盘」的改前改后计时对比,所以上面任何一条都不带性能倍数。

通用说明

  • 下载安装:从下方 Assets 下载对应平台压缩包(terraforge-windows.zip / terraforge-linux.tar.gz / terraforge-macos.tar.gz),解压即用,无需安装 Python 环境。
  • 下载体积:每个平台仍包含 167 MB 的全球底图分卷(自 v0.2.8 起)。
  • 首次运行:启动可执行文件后,浏览器访问 http://localhost:5000 ;代理、并发、缓存管理等在「配置」页修改。程序另会监听 5001 出瓦片,不放行也能用。
  • 许可证与第三方声明:程序目录下的 LICENSE(MIT)与 THIRD_PARTY_NOTICES.md。MIT 只覆盖软件代码,不授予任何数据与在线服务的使用权。
  • 历史版本:完整更新历史见仓库 CHANGELOG.md
  • 使用文档:见仓库 README.mddocs/guides/QUICKSTART.md