import { IFileSystem, StoredDocument, DataFileContent, SyncOptions } from '../types.js'; /** * 存储管理器 * * rev2 存储策略: * - 写入即分片:文件直接写入 data/YYYY/MM/DD/ 对应日期子目录(不再先写根目录再重排) * - 单文件体积上限 maxFileSize:一次写入差异集超过上限则拆成多个 data-{timestamp}.json * - 文件名不含 sequence,仅靠 timestamp 区分 * - 文件发现靠递归列目录(data + merged),不依赖 manifest */ export declare class StorageManager { private fs; private fsUtils; private basePath; private maxFileSize; private mergeThreshold; private mergeCheckInterval; private autoMerge; constructor(fs: IFileSystem, options: SyncOptions); /** * 初始化存储目录 */ initialize(): Promise; get options(): Required>; /** * 将差异文档集写入目标文件系统(写入即分片) */ writeDocuments(documents: StoredDocument[], onChunkWritten?: (written: number, total: number) => void): Promise; /** * 按单文件体积上限把文档集切成若干 chunk */ private chunkBySize; /** * 把一个 chunk 写入 data/YYYY/MM/DD/data-{timestamp}.json(原子写入) */ private writeChunk; /** * 由 timestamp 计算 data/YYYY/MM/DD 分片相对路径 */ private shardDirForTimestamp; /** * 递归列出 data + merged 目录下所有数据文件路径(含日期分片子目录) */ listAllDataFiles(): Promise; /** * 全树枚举兜底:从 basePath 递归 readdir,不依赖层级格式与 isDirectory, * 遇到「集合自身当子条目返回」或重复路径则跳过,按文件名匹配 data-/merged- 文件。 */ private fallbackListAll; /** * 按 data/merged 的固定层级 YYYY/MM/DD 收集数据文件。 * 不依赖 WebDAV 的 isDirectory 判定(teracloud 等会把集合自身当子条目返回, * 且 stat 对 404 行为不稳定),改为按层级格式直接下钻,天然过滤自引用/噪声条目。 */ private collectShardFiles; private readFiltered; private readDirSafe; private isDirectory; /** * 读取所有文件并合并去重,返回每个文档的最新版本(按 _rev generation 取大) */ readAllDocuments(): Promise; private readDocumentsFromFiles; /** * 读取单个文件的完整内容(含 documents) */ readFileContent(file: string): Promise; /** * 按 docId 取 _rev generation 最大者 */ private latestByRev; private revGeneration; /** * 找到可合并的候选组(「每月合并上个月」语义)。 * 只聚合「当前月之前(上月及更早)」的 data 文件;本月新写入的 data 不参与,留到下月。 * 因此即便只有 1 个历史 data 文件也会返回候选(合并后该文件从 data 移走、空目录被清理), * 从而持续压低 data 目录的文件数与层级。 * 按累计体积(不超过 maxFileSize)分批;不依赖 mergeThreshold 硬门槛——WebDAV 的 size() 常不可靠。 * @param force 跳过「排除本月文件」过滤(手动/测试用),连同本月的 data 一起合并。 */ findMergeCandidates(force?: boolean): Promise; private fileSizeOf; /** * 执行一组文件的合并:读取全部文档 -> 去重取最新 -> * 写入 merged/merged-{timestamp}.json -> 把源文件移至 archive/<原相对路径>(可回溯) */ mergeFiles(fileGroup: string[]): Promise; /** * 上个月的 data 是否已在共享存储上合并过(「每月合并上个月」语义)。 * 标记键 = 上个月的 UTC 月(如 2026-08 运行时,标记 merged-up-to-2026-07 表示"7 月及更早已汇总")。 * 所有设备统一看 UTC 月,避免不同时区/本地时钟导致同一个月被重复合并。 * 同时兼容旧版 `.last-merge-YYYY-MM` 标记(视为已合并)。 */ hasMergedThisMonth(): Promise; /** * 写入「已合并到哪个月」标记(基于上个月 UTC 月)。内容为 UTC 写入时间戳(ISO 字符串),便于审计。 * 若标记已存在(极小概率并发),覆盖即可——不影响去重语义。 */ private markMergedThisMonth; /** * 把 basePath 下的绝对路径转为相对 basePath 的路径(用于 archive 内保留原结构) */ private relativeToBase; private parentDir; private baseName; private moveToArchive; private safeUnlink; /** * 清理空的日期分片子目录(data/YYYY/MM/DD 与 merged/YYYY/MM/DD), * 避免合并删除源文件后残留空目录。只删除空目录,不触碰任何文件。 */ cleanupArchivedFiles(): Promise; private removeEmptyDirs; private safeRmdir; /** * 自底向上删除空目录:从 startDir 起逐层向上,遇到空目录就删, * 直到碰到 stopDir(含,不删)或目录非空/删除失败为止。 * 用于合并后清理 data 下被移空的日期分片子目录,避免空目录累积。 */ private removeEmptyDirsUpward; } //# sourceMappingURL=storage-manager.d.ts.map