9.9 KiB
周期归档与作业管理
Orbit 控制台的「归档作业」页面提供周期配置、作业列表、失败重试及关闭。沿用单管理员账号密码登录,不引入角色体系。业务 SDK 不需要也不能领取归档作业。
1. 部署执行器
需要 Schema 31。停止旧节点后执行 orbit-migrate up,再启动新版本节点。000031 只增加 orbit_archive_plans、orbit_archive_jobs,不包含外键或源数据清理。
# 必须挂载持久卷,并让 Orbit 运行用户拥有目录,权限 0700。
ORBIT_ARCHIVE_ROOT=/var/lib/orbit/archive
# 初次部署生成并保存一个固定的 32 位小写十六进制 ID,例如 openssl rand -hex 16。
ORBIT_ARCHIVE_STORAGE_ID=11111111111111111111111111111111
# 全卷逻辑文件字节预算,默认 10 GiB;范围 1 MiB–1 TiB。
ORBIT_ARCHIVE_MAX_BYTES=10737418240
# 默认 10s,范围 1s–1m。
ORBIT_ARCHIVE_TICK_INTERVAL=10s
ROOT 和 STORAGE_ID 均为空时关闭此节点后台执行器,控制台仍可查询历史。两者必须一起设置。路径只来自部署配置,页面不能指定任意服务器目录。镜像用户为 65532:65532,目录须可由该用户访问。
运行示意(orbit.env 同时包含已有数据库等配置,不要提交到 Git):
mkdir -p ./archive-data
chmod 700 ./archive-data
# Linux 主机上按镜像实际 UID/GID 配置归档目录归属。
sudo chown 65532:65532 ./archive-data
docker run --name orbit --env-file orbit.env \
--mount type=bind,src="$(pwd)/archive-data",dst=/var/lib/orbit/archive \
-p 127.0.0.1:8080:8080 orbit:local
同一 STORAGE_ID 的所有执行节点必须挂载同一物理卷,支持 POSIX 文件锁、原子硬链接和目录 fsync;同名路径、复制目录或相同 ID 不等于共享存储。卷根目录持久化 .storage-id 身份标记,恢复已有作业时要求原清单存在。独立本地盘使用不同卷 ID;其归档作业不能由别的独立盘接管。没有验证任意 NFS/对象存储语义,不据此宣称跨故障域归档高可用。
同卷执行串行,后台每轮最多调度 16 个到期类别、执行一个文件批次,工作截止 45 秒,数据库租约 5 分钟。正常继续在下一轮领取;进程异常退出且未确认时,等待租约到期后恢复。关机取消不写成文件损坏。
2. 使用顺序
- 登录控制台,在「保留策略」确认各类保留天数,开启只读归档并保存。
- 打开「归档作业」,选择类别,配置间隔、批大小、单作业容量和变更原因,开启周期并保存。
- 首次启用立即到期,后台生成固定身份的作业;页面每 10 秒刷新,显示批次、根记录数、文件字节和链尾 SHA-256。
- 失败时查看分类,修复原因后填写处理原因,从原作业重试;不能恢复的旧版本作业可以关闭,原文件与审计保留。
任务、流程、事件、审计、交付、Inbox、幂等记录各有独立计划。间隔范围 1–720 小时,HTTP 支持 3600–2592000 整数秒;每批 1–100 条根记录,单作业 1 MiB–1 GiB。关联历史行不计入根记录数,但全部计入文件容量。
同一类别最多一个未结清作业,失败也占位,避免周期不断制造重复失败。错过多个周期合并触发一次,next_run_at 按本次数据库时间加周期计算,不补齐每个错过的时间槽。关闭计划仅停止新作业,已有作业继续结清。
每次周期是新的有限全量候选快照:会再次读取仍满足保留窗口的源记录,不是跨作业增量清理。每个作业内的分页截止、游标、类别、策略版本及批大小固定。文件落盘后才确认数据库进度;已落盘而未确认的文件可在恢复时重新核验并收敛。源数据库内容不删除。
保留策略修改后,计划仍绑定旧版本,因此不会再生成新作业,须重新保存计划确认新版本。正在运行的旧作业在下一次导出时以 POLICY_CHANGED 停止;若已完整落盘,则可核验并确认已完成的原快照。旧作业重试不能更换策略版本或重置截止。
3. HTTP 接口
以下接口只接受控制台 HttpOnly 会话 Cookie,普通 Bearer 凭据不可访问。命名空间取自会话,写请求拒绝跨来源浏览器调用。保存与人工操作必须提供一个 Idempotency-Key;网络或服务器错误后保持原路径、原请求体和原键重试。明确的 4xx 拒绝可核对并修正后使用新键。
查询周期配置
GET /console/archive/plans
{"data":{"executor_configured":true,"storage_id":"11111111111111111111111111111111","items":[{"namespace_id":"22222222222222222222222222222222","kind":"tasks","revision":"1","enabled":true,"policy_revision":"3","storage_id":"11111111111111111111111111111111","interval_seconds":86400,"batch_size":20,"max_bytes":268435456,"next_run_at":"2026-09-24T02:00:00Z","active_job_id":null,"updated_at":"2026-09-23T02:00:00Z"}]}}
实际返回全部七类。未保存的类别 revision="0"、enabled=false,没有卷绑定,时间为空。executor_configured 只表示当前 HTTP 节点已配置执行器,不表示实时健康探针或整个集群状态。
保存周期配置
PUT /console/archive/plans/{kind}
Content-Type: application/json
Idempotency-Key: archive-plan-change-001
{
"expected_revision":"0",
"policy_revision":"3",
"enabled":true,
"interval_seconds":86400,
"batch_size":20,
"max_bytes":268435456,
"reason":"每日归档已超过保留窗口的任务历史"
}
全部字段必填,原因是 1–1024 个 UTF-8 字节的非空单行。响应 data 为保存后的计划。计划版本或保留策略版本不符返回 409;开启时保留策略必须已启用,当前节点必须配置卷。关闭已有计划时允许当前节点未配置执行器。存在未结清作业时不允许更换卷绑定。
查询作业列表
GET /console/archive/jobs,下一页 GET /console/archive/jobs?before={next_before}。
每页最多 20 条,按创建时间和 ID 倒序;位置必须是当前命名空间内的作业 ID。不是跨页冻结快照。返回:
{"data":{"items":[{"id":"33333333333333333333333333333333","namespace_id":"22222222222222222222222222222222","kind":"tasks","plan_revision":"1","policy_revision":"3","storage_id":"11111111111111111111111111111111","batch_size":20,"max_bytes":268435456,"state":"SUCCEEDED","revision":"5","attempts":2,"batches":2,"roots":32,"bytes":86124,"last_sha256":"64位小写十六进制摘要","error_code":"","lease_until":null,"created_at":"2026-09-23T02:00:00Z","updated_at":"2026-09-23T02:00:20Z"}],"next_before":""}}
attempts 是批次领取次数,包含分批继续和崩溃重领,不是业务任务重试次数。batches/roots/bytes/last_sha256 只展示已经入库确认的进度,落盘后确认失败时页面可能暂时落后。列表不返回文件正文、分页游标或内部租约代次。
| 状态 | 含义 |
|---|---|
| PENDING | 等待首批或下一批执行 |
| RUNNING | 已领取,租约内执行;到期可接管 |
| SUCCEEDED | 全部批次落盘、校验并确认完成 |
| FAILED | 等待管理员核查;阻止本类别创建后续作业 |
| ABANDONED | 管理员关闭失败作业,文件、数据库历史与审计保留 |
重试或关闭失败作业
POST /console/archive/jobs/{id}/actions
Content-Type: application/json
Idempotency-Key: archive-job-retry-001
{"expected_revision":"8","action":"retry","max_bytes":536870912,"reason":"确认原归档卷完整,并将单作业预算提高到512MiB"}
响应 data 为操作后的作业。仅 FAILED 可操作;重试保持原 ID、目录、范围、截止与已确认链前缀,预算只可保持或提高。action="abandon" 关闭作业,max_bytes 必须等于原值;关闭后不删除文件,开启的计划可按到期时间生成新作业。原键重放仅返回原操作回执,不代表作业当前仍处于回执中的状态;随后查询列表确认实时状态。
4. 故障处理和文件核验
| 错误分类 | 处理方式 |
|---|---|
| STORAGE_LIMIT | 检查单作业预算和全卷预算;按需提高,或在运维确认备份后转移已经结清的文件。不会自动删除旧文件腾空间 |
| FILE_CHECK_FAILED | 检查原卷、目录、权限和文件完整性;恢复原字节后重试,禁止伪造摘要或跳过缺失批次 |
| STORAGE_BUSY | 同目录有其他 CLI/进程操作;核实旧执行者退出后重试 |
| POLICY_CHANGED | 原策略已变化或关闭;通常关闭旧作业,再按新版本保存计划 |
| PERMISSION_DENIED | 应用或命名空间停用;核查后按原状态重试或关闭 |
| EXPORT_FAILED | 数据库读取未完成;确认数据库恢复后用原作业重试 |
如果在首份清单落盘前进程退出、卷不可写或全卷预算耗尽,接管不会擅自创建一个新的空目录。此时可核查后关闭失败作业,让计划生成新作业。已有清单的容量故障可提高预算后重试原作业。
文件位于 ORBIT_ARCHIVE_ROOT/{namespace_id}-{job_id}/,清单及批次格式与 文件归档 CLI 一致。数据库确认的链尾摘要可独立保存。服务端停止操作该目录后,可离线核验:
orbit-admin retention verify-archive \
--directory /var/lib/orbit/archive/22222222222222222222222222222222-33333333333333333333333333333333 \
--expected-sha256 "$TRUSTED_SHA256"
全卷预算按普通文件的逻辑大小累计,单次扫描最多 100000 个目录项,包含未完成、失败与已关闭作业;超过边界停止。并发同卷执行受全卷文件锁约束。它不等价于文件系统物理空间配额,不包含块分配/元数据开销,也不能约束绕过平台直接写目录的外部进程。生产使用独立持久卷,并监测实际磁盘余量。暂不提供文件删除、自动迁移介质、下载正文或对象存储接口。