Files
Endoleap/src/lib/canvas-runtime/storage-port.ts
T

48 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 便携持久化端口:定义 scope、leader/fence、恢复图像与原子 DurableBatch。
* 这里不导入 IndexedDB/Web Locks 实现,Node/测试宿主可以提供其它 adapter。
* 成功 commit 才能确认 durable,内存发布或排队成功不能替代它。
*/
import type { Json } from '../canvas-core/types.ts';
/** Portable durable-store contract. Browser database types belong to the adapter. */
/** 持久键由账号/工作区/项目组成,不含 view/navigation/authEpoch;身份退役另由宿主与 leader 围栏处理。
* 类型声明不捕获字符串、不验证权限,adapter 应按此作用域隔离事实,不能仅用 projectId 作全局键。 */
export type StorageScope = { readonly accountId: string; readonly workspaceId: string; readonly projectId: string };
/** 可恢复单 Root 图像;formatVersion 是解释器版本,rootRevision 与文档 localRevision 分开。 */
export type RecoveryImage = { readonly formatVersion: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17; readonly rootRevision: number; readonly localRevision: number; readonly payload: Json };
/** 恢复图像与可选文件增删/depot 清单的同次原子提交合同;不表示对象构造后已保存。
* files 是 Blob 原字节,image/depot 保存逻辑引用/证明;adapter 需在异步前捕获输入并核对身份/删除资格。
* 需要删除时还须显式 fileDeletion 能力,不能将独立异步删文件视为与 Root 同一事务。 */
export type DurableBatch = { readonly image: RecoveryImage; readonly deleteFiles?:readonly string[]; readonly depot?:import('./asset-depot.ts').DepotCut; readonly files?: readonly { readonly id: string; readonly bytes: Blob }[] };
/** 排他写者句柄,fence 标识持有代次,active 可随 release/失效改变;只读类型不代表 active 永远不变。
* 宿主准入检查不能替代 adapter 在真实 I/O/提交处复核 scope/fence/有效性,接口自身不实现跨进程锁。 */
export type StorageLeader = { readonly scope: StorageScope; readonly fence: number; readonly active: boolean; release(): Promise<void> };
/** 文件盘点只返回元信息,不为扫描加载全部 Blob 字节。 */
export type StoredFileInfo={readonly id:string;readonly byteLength:number;readonly mimeType:string};
/** 分页盘点绑定 rootRevision,nextAfter 是后续页游标,不能跨变更拼接成完整清理依据。 */
export type FileInventoryPage={readonly files:readonly StoredFileInfo[];readonly rootRevision:number;readonly nextAfter?:string};
/** 宿主实现的持久协议,声明本身不执行校验/深冻结、获取锁或操作数据库。
* 可选能力须显式探测;引擎的 ledger generation/Root 发布只是内存事实,commit 成功确认后才推进可靠水位。
* close 为同步本地句柄收尾,异步 leader.release 独立;失败/取消的 I/O 不自动说明数据从未提交。 */
export type StoragePort = {
/** 可选工作区共享资源仓库,文件/引用保留通过 depot 合同处理。 */
readonly assetDepot?:import('./asset-depot.ts').AssetDepotPort;
/** 在 expectedRootRevision 下按稳定游标读取文件页,revision 不匹配应拒绝。 */
scanFiles?(leader:StorageLeader,input:{readonly expectedRootRevision:number;readonly after?:string;readonly limit:number}):Promise<FileInventoryPage>;
/** atomic-v1 明确声明支持与 Root 一起提交文件删除,不能用普通异步 delete 冒充。 */
readonly fileDeletion?: 'atomic-v1';
/** 取得作用域 leader,已有有效写者时拒绝,而不是悄悄允许两个 writer。 */
claim(scope: StorageScope): Promise<StorageLeader>;
/** 恢复最后已提交图像,不直接把任意 payload 当合法 Root;codec/engine 仍需版本、结构与身份校验。
* null 只表示该作用域没有已提交快照,不证明所有本地文件/共享 depot 记录也不存在。 */
recover(leader: StorageLeader): Promise<RecoveryImage | null>;
/** adapter 捕获/验证并原子提交批次,返回实际完成的 durableRootRevision;不能在入队/单条写请求成功时提前 resolve。
* 回执不直接修改 editor 或放行 scheduler,调用方还需核对水位并按同切点恢复调度。 */
commit(leader: StorageLeader, batch: DurableBatch): Promise<{ readonly durableRootRevision: number }>;
/** 读取指定文件的 Blob,缺失用 undefined;不从文档资源引用猜字节已经存在。 */
readFile(leader: StorageLeader, id: string): Promise<Blob | undefined>;
/** 关闭 adapter 的本地句柄,leader 的异步释放仍通过其 release 合同完成。 */
close(): void;
};