4.4 KiB
Agent Note: 有界的共享 Office 转换
Status: implemented
English | 中文
问题
Office 预览和显式文档检查可能请求相同转换。仅缓存已完成结果无法限制源读取、排队载荷和并发读取方。推测工作也可能占用用户需要的容量,而取消一个消费者不能破坏另一个消费者的转换。
决策
office-to-pdf 服务返回完整 PDF 字节。其 Remote 文件入口通过 workspaceFiles 授权 Session 文件,进程内转换则接受已授权的延迟读取,不要求该服务。api/remotes 装配负责 Client 命名空间挂载。页面栅格化和用户展示由独立消费方负责,因此转换命名不隐含图片渲染或预览 UI。
宿主提供方拥有共享转换队列和临时内容缓存。已授权的源文件元数据在加载字节之前进入准入流程。源回调接收预留的字节容量并返回读取版本;源文件变化会导致失败,不发布别名。确切的源字节和 Office 扩展名决定摘要。每个转换器生命周期附加代次,因此引擎、字体或配置替换会使复用失效。
有界的源版本索引在授权后避免重复读取;摘要仍是不同路径间共享转换的身份。已就绪 PDF 使用按条目与字节限制的 LRU。排队任务包含元数据和延迟回调。读取方、队列、源字节与转换限制在工作完成前也适用。每个在途源定位信息归属于活跃读取方,因此取消操作不能让保留的源元数据脱离读取方准入限制增长。未知源大小预留输入上限;取消后仍保留活动容量,直至实际读取、转换与清理结束。
前台预览和显式 QA 请求优先于后台工作。禁用后台转换时,推测读取方在加入排队或运行任务前即被拒绝,但仍可命中已完成的别名缓存。移除排队的前台阻塞任务后,符合条件的后台工作立即准入。排队优先级取决于活跃读取方:前台加入会提升预热,最后一个前台读取方取消后则恢复后台优先级,并准入符合条件的工作。队列满时为前台准入移除排队推测工作。总并发允许时,后台并发为前台预留一个槽位。推测工作的准入名额保留到工作结束,因此提权不会把为用户预留的容量用于更多推测工作。共享读取方独立取消,包括内容哈希后加入的读取方。缓存拥有私有输出字节,并为各调用方返回副本。
考虑过的替代方案
仅缓存已完成 PDF。 无法限制待完成源缓冲区、引擎工作和响应扇出,不同消费者仍会重复转换。
以源元数据作为最终缓存身份。 元数据在读取前有用,但不同的已授权路径可能包含相同字节。内容哈希提供跨路径复用,而不把路径当作文档内容。
一个读取方离开就取消整个转换。 打开的预览可能与推测工作或显式 QA 共享工作。只有最后一个读取方拥有共享工作取消权。
另建预热或 QA 转换器。 独立队列重复拥有资源,无法优先调度共享前台工作。
为唯一的 LibreOffice 实现拆分服务定义和提供方包。 两者共同演化,没有独立的替代实现。单个 office-to-pdf 包直接提供可挂载服务,避免重复维护包、依赖和发布配置。原生与 WASM 引擎选择仍由 kit 负责;若出现独立的第二种实现,再根据实际消费者提取接口。
后果
缓存为临时数据,不能绕过源授权。超出缓存上限的 PDF 可返回而不保留;失败或取消的转换在后续显式请求时重试。源预留按二进制字节计量;Remote base64 膨胀、引擎 RSS、调用方保留的输出和 PDF.js 页面内存不计入这些限制。仅配置一个转换槽位时,前台工作等待已运行的后台转换结束。
Office 预览通过 Workspace Files 检查源文件授权与版本,再使用 fs.readBytes 在转换预留容量内读取原始输入。该读取受 Office 输入上限约束。Host 转换路径不分配 base64 源数据;PDF 响应只编码转换后的输出。
受控的源读取和引擎完成验证读取前准入、内容合并、优先级、取消隔离、延迟资源释放、LRU 与别名限额、过期版本及转换器替换。Loader 组合与原生转换检查独立于展示消费者验证共享提供方。