import { type S3Client } from "@aws-sdk/client-s3"; import { type BackupConfig } from "./config.js"; import type { DrillReport } from "./drill.js"; /** * `drill --record` 写进桶里的演练结论。`exporter` 只读桶,演练结果不落桶它就无从得知。 * * 每次演练写一个新对象,从不覆盖: * /.drills/<结束时间>--<8 位随机>.json * 为什么不是一份可覆盖的"最近一次":两次演练重叠时,先结束的那次可能后写进桶,把更新的 * "没通过"盖成更早的"通过",失败告警就没了;先读后写也挡不住(不是原子的),而各家 * S3 兼容存储对条件写入的支持参差不齐。每次一个对象,"哪次最新"留给读的一方按名字判断, * 写入顺序就无所谓了。 * * 为什么放在 .drills/,和快照目录并排而不是在它里面:resolveSnapshot(包括已经发出去的 * 旧版本)按字典序取 / 下最大的目录当最新快照,里面多一个 drills/ 会被当成快照。 * * 文件名本身带着结束时间和结论,exporter 列一下目录就知道最近一次和最近一次通过是哪个; * 只为了恢复用时才读一次通过的那份。只记结论,不记检查明细:失败明细里可能有 pg_restore * 回显的表数据,而桶的读权限可能比演练日志给得更宽(exporter 只要只读 key)。 */ /** 版本规则同 manifest:缺省不接受,更高的版本明确报错让用户升级,不按旧结构硬读。 */ export declare const DRILL_RECORD_SCHEMA_VERSION = 1; export interface DrillRecord { schemaVersion: number; tool: "backupdrill-cli"; toolVersion: string; /** 演练结束的时间(ISO8601),与文件名里的时间相同 */ finishedAt: string; pass: boolean; /** 演练的快照名;演练在选定快照之前就失败了(没装 Docker、桶里没有快照)时没有 */ snapshot?: string; /** 恢复用时,只有通过的演练才记:没通过时这个数可能只是半程,拿来估恢复时间会误导 */ restoreSeconds?: number; } /** 演练记录所在的"目录",带尾斜杠 */ export declare function drillRecordsPrefix(config: BackupConfig): string; export declare function drillRecordName(record: Pick, unique?: string): string; /** 从文件名读出结束时间(毫秒)和结论;不是记录文件的名字返回 null */ export declare function parseDrillRecordName(name: string): { finishedAt: number; pass: boolean; } | null; /** report 为 null = 演练中途抛错、没有报告;这也算一次没通过的演练。 */ export declare function buildDrillRecord(report: DrillReport | null, finishedAt: Date): DrillRecord; /** 写一个新对象,返回它的 key。不读桶:只需要写权限 */ export declare function writeDrillRecord(s3: S3Client, config: BackupConfig, record: DrillRecord, abortSignal?: AbortSignal): Promise; /** * CLI 的 `drill --record`:写不进去只警告,演练本身的结论和退出码不变。 * 常见原因是给演练配的是只读 key;这种情况下 exporter 的演练时间会一直不动,告警规则会发现。 */ export declare function recordDrillOutcome(config: BackupConfig, report: DrillReport | null, s3?: S3Client, timeoutMs?: number): Promise; /** 读桶里的演练记录。结构不对就报错:exporter 宁可报 up=0,也不报一个读错的结论。 */ export declare function parseDrillRecord(json: string, file: string): DrillRecord;